diff --git a/game/engines/default/engine/ui/Numberbox.lua b/game/engines/default/engine/ui/Numberbox.lua index eb118f0280aba11c8fabc7e90bdace2ef08e6501..bfaa9f9310bae6470d63ce7d8cb0a77625ba7a3c 100644 --- a/game/engines/default/engine/ui/Numberbox.lua +++ b/game/engines/default/engine/ui/Numberbox.lua @@ -168,7 +168,7 @@ function _M:display(x, y, nb_keyframes) end if self.focused then self:drawFrame(self.frame_sel, x + self.title_w, y) - self.texcursor.t:toScreenFull(x + self.text_x + (self.cursor-self.scroll) * self.font_mono_w, y + self.cursor_y, self.texcursor.w, self.texcursor.h, self.texcursor.tw, self.texcursor.th) + self.texcursor.t:toScreenFull(x + self.text_x + (self.cursor-self.scroll) * self.font_mono_w - (self.texcursor.w / 2), y + self.cursor_y, self.texcursor.w, self.texcursor.h, self.texcursor.tw, self.texcursor.th) else self:drawFrame(self.frame, x + self.title_w, y) if self.focus_decay then diff --git a/game/engines/default/engine/ui/Textbox.lua b/game/engines/default/engine/ui/Textbox.lua index bb453f02ec2a2ca0885c8ca661d012e0a413e56f..8f892220b44030a96ef8fd9366712735c5fa076c 100644 --- a/game/engines/default/engine/ui/Textbox.lua +++ b/game/engines/default/engine/ui/Textbox.lua @@ -183,7 +183,7 @@ function _M:display(x, y, nb_keyframes) end if self.focused then self:drawFrame(self.frame_sel, x + self.title_w, y) - self.texcursor.t:toScreenFull(x + self.text_x + (self.cursor-self.scroll) * self.font_mono_w, y + self.cursor_y, self.texcursor.w, self.texcursor.h, self.texcursor.tw, self.texcursor.th) + self.texcursor.t:toScreenFull(x + self.text_x + (self.cursor-self.scroll) * self.font_mono_w - (self.texcursor.w / 2), y + self.cursor_y, self.texcursor.w, self.texcursor.h, self.texcursor.tw, self.texcursor.th) else self:drawFrame(self.frame, x + self.title_w, y) if self.focus_decay then diff --git a/game/engines/default/engine/ui/WebView.lua b/game/engines/default/engine/ui/WebView.lua index c5025b8b768e67aa0e025e9edf1bd4448e311fa8..7749a4cd721e1b96dd686dc0196e05448a0b7125 100644 --- a/game/engines/default/engine/ui/WebView.lua +++ b/game/engines/default/engine/ui/WebView.lua @@ -69,6 +69,10 @@ function _M:generate() on_loading = function(url, status) self.loading = status end, + on_crash = function() + print("WebView crashed, closing C view") + self.view = nil + end, } if self.allow_downloads then self:onDownload(handlers) end self.view = core.webview.new(self.w, self.h, handlers) diff --git a/game/engines/default/modules/boot/dialogs/Credits.lua b/game/engines/default/modules/boot/dialogs/Credits.lua index a9f0d0b96d6f2b8e54ddc59fc0303dbec2c3b6d9..6861b57f3edd4c1ece4a3024a4fc72cf5a85ab04 100644 --- a/game/engines/default/modules/boot/dialogs/Credits.lua +++ b/game/engines/default/modules/boot/dialogs/Credits.lua @@ -105,11 +105,13 @@ local credits = { {"Code Helpers", title=1}, {"Antagonist"}, + {"Doctornull"}, {"Graziel"}, {"Grayswandir"}, {"Hachem Muche"}, {"Jules 'Quicksilver' Bean"}, {"Madmonk"}, + {"Mark 'Marson' Carpente"}, {"Neil Stevens"}, {"Sebastian 'Sebsebeleb' Vråle"}, {"Shani"}, diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 9d6448a45ae73f700e82eea0d47eac3fbad10622..f2b60f4a5f7527b2bdb1e6094a35217e48b80859 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -1627,14 +1627,6 @@ function _M:tooltip(x, y, seen_by) local rank, rank_color = self:TextRank() - local resists = {} - for t, v in pairs(self.resists) do - if v ~= 0 then - if t ~= "all" then v = self:combatGetResist(t) end - resists[#resists+1] = string.format("%d%% %s", v, t == "all" and "all" or DamageType:get(t).name) - end - end - local ts = tstring{} ts:add({"uid",self.uid}) ts:merge(rank_color:toTString()) ts:add(self.name, {"color", "WHITE"}) if self.type == "humanoid" or self.type == "giant" then ts:add({"font","italic"}, "(", self.female and "female" or "male", ")", {"font","normal"}, true) else ts:add(true) end @@ -1654,7 +1646,26 @@ function _M:tooltip(x, y, seen_by) ts:add({"color", 0, 255, 128}, ("Iceblock: %d"):format(eff.hp), {"color", "WHITE"}, true) end --ts:add(("Stats: %d / %d / %d / %d / %d / %d"):format(self:getStr(), self:getDex(), self:getCon(), self:getMag(), self:getWil(), self:getCun()), true) - if #resists > 0 then ts:add("Resists: ", table.concat(resists, ','), true) end + --if #resists > 0 then ts:add("Resists: ", table.concat(resists, ','), true) end + + local resists = tstring{} + ts:add({"color", "ANTIQUE_WHITE"}, "Resists: ") + for t, v in pairs(self.resists) do + if t == "all" then + ts:add({"color", "LIGHT_BLUE"}, tostring(math.floor(v)) .. "%", " ", {"color", "LAST"}, "all, ") + elseif math.abs(v) >= 20 then + local res = tostring ( math.floor(self:combatGetResist(t)) ) .. "%" + if v > 0 then + ts:add({"color", "LIGHT_GREEN"}, res, " ", {"color", "LAST"}, DamageType:get(t).name, ", ") + else + ts:add({"color", "LIGHT_RED"}, res, " ", {"color", "LAST"}, DamageType:get(t).name, ", ") + end + end + end + + if ts[#ts] == ", " then table.remove(ts) end + ts:add(true) + ts:add("Hardiness/Armour: ", tostring(math.floor(self:combatArmorHardiness())), '% / ', tostring(math.floor(self:combatArmor())), true) ts:add("Size: ", {"color", "ANTIQUE_WHITE"}, self:TextSizeCategory(), {"color", "WHITE"}, true) @@ -1667,9 +1678,50 @@ function _M:tooltip(x, y, seen_by) ts:add("#FFD700#M. power#FFFFFF#: ", self:colorStats("combatMindpower"), " ") ts:add("#0080FF#M. save#FFFFFF#: ", self:colorStats("combatMentalResist"), true) ts:add({"color", "WHITE"}) + + if (150 + (self.combat_critical_power or 0) ) > 150 then + ts:add("Critical Mult: ", ("%d%%"):format(150 + (self.combat_critical_power or 0) ), true ) + end + if self.summon_time then ts:add("Time left: ", {"color", "ANTIQUE_WHITE"}, ("%d"):format(self.summon_time), {"color", "WHITE"}, true) end + + if self:getInven("MAINHAND") and self:getInven("MAINHAND").worn and self:getInven("MAINHAND")[1] and self:getInven("MAINHAND")[1].keywords then + ts:add("Weapon Keywords: ", {"color", "RED"}) + local keywords = tstring{} + local archery = self:getInven("MAINHAND")[1].archery or false + + + for k, v in pairs(self:getInven("MAINHAND")[1].keywords) do + ts:add(tostring(k), ", " ) + end + + if self:getInven("OFFHAND") and self:getInven("OFFHAND").worn and self:getInven("OFFHAND")[1] and self:getInven("OFFHAND")[1].keywords then + for k, v in pairs(self:getInven("OFFHAND")[1].keywords) do + ts:add(tostring(k), ", ") + end + end + + if archery and self:getInven("QUIVER") and self:getInven("QUIVER").worn and self:getInven("QUIVER")[1] and self:getInven("QUIVER")[1].keywords then + for k, v in pairs(self:getInven("QUIVER")[1].keywords) do + ts:add(tostring(k), ", ") + end + end + + if ts[#ts] == ", " then table.remove(ts) end + ts:add({"color", "LAST"}, true) + end + + local retal = 0 + for k, v in pairs(self.on_melee_hit) do + if type(v) == "number" then retal = retal + v + elseif type(v) == "table" and type(v.dam) == "number" then retal = retal + v.dam + end + end + + if retal > 0 then ts:add("Melee Retaliation: ", {"color", "RED"}, tostring(math.floor(retal)), {"color", "WHITE"}, true ) end + if self.desc then ts:add(self.desc, true) end if self.faction and Faction.factions[self.faction] then ts:add("Faction: ") ts:merge(factcolor:toTString()) ts:add(("%s (%s, %d)"):format(Faction.factions[self.faction].name, factstate, factlevel), {"color", "WHITE"}, true) end if game.player ~= self then ts:add("Personal reaction: ") ts:merge(pfactcolor:toTString()) ts:add(("%s, %d"):format(pfactstate, pfactlevel), {"color", "WHITE"} ) end @@ -1682,28 +1734,40 @@ function _M:tooltip(x, y, seen_by) if ts[#ts-1] == "Sustained Talents: " then table.remove(ts) table.remove(ts) table.remove(ts) table.remove(ts) end ts:add(true, {"color", "ORANGE"}, "Temporary Status Effects: ",{"color", "WHITE"}) + + local effmental = tstring{} + local effphysical = tstring{} + local effmagical = tstring{} + local effother = tstring{} + local effbeneficial = tstring{} + for eff_id, p in pairs(self.tmp) do local e = self.tempeffect_def[eff_id] local dur = p.dur + 1 if e.status == "detrimental" then if e.type == "physical" then - if act then ts:add(true, "- ", {"color", "LIGHT_RED"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end + if act then effphysical:add(true, "- ", {"color", "LIGHT_RED"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end elseif e.type == "magical" then - if act then ts:add(true, "- ", {"color", "DARK_ORCHID"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end + if act then effmagical:add(true, "- ", {"color", "DARK_ORCHID"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end elseif e.type == "mental" then - if act then ts:add(true, "- ", {"color", "YELLOW"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end + if act then effmental:add(true, "- ", {"color", "YELLOW"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end elseif e.type == "other" then - if act then ts:add(true, "- ", {"color", "ORCHID"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end - + if act then effother:add(true, "- ", {"color", "ORCHID"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end else if act then ts:add(true, "- ", {"color", "LIGHT_RED"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end end else - if act then ts:add(true, "- ", {"color", "LIGHT_GREEN"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end + if act then effbeneficial:add(true, "- ", {"color", "LIGHT_GREEN"}, (e.decrease > 0) and ("%s(%d)"):format(e.desc,dur) or e.desc, {"color", "WHITE"} ) end end end + ts:merge(effphysical) + ts:merge(effmental) + ts:merge(effmagical) + ts:merge(effother) + ts:merge(effbeneficial) + if ts[#ts-1] == "Temporary Status Effects: " then table.remove(ts) table.remove(ts) table.remove(ts) table.remove(ts) end return ts @@ -1914,9 +1978,13 @@ function _M:onTakeHit(value, src, death_note) value = value / 2 end end + + --Special Flag (currently for Terrasca) + if value > 0 and self:attr("speed_resist") then + value = value * (util.bound(self.global_speed * self.movement_speed, 0.3, 1)) + end -- Reduce damage and trigger for Trained Reactions - --print("[onTakeHit] Before Trained Reactions ", value) if self:attr("incoming_reduce") then value = value * (100-self:attr("incoming_reduce")) / 100 print("[onTakeHit] After Trained Reactions effect reduction ", value) diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua index 2efffc5bd34776de5ebf1133740ee0b553ad5722..5ea24a01d96cac92e7806b3f79d18b91bab2ecfc 100644 --- a/game/modules/tome/class/GameState.lua +++ b/game/modules/tome/class/GameState.lua @@ -508,6 +508,31 @@ function _M:generateRandart(data) -- Setup the name o.name = name + local theme_map = { + physical = engine.DamageType.PHYSICAL, + --mental = engine.DamageType.MIND, + fire = engine.DamageType.FIRE, + lightning = engine.DamageType.LIGHTNING, + acid = engine.DamageType.ACID, + mind = engine.DamageType.MIND, + arcane = engine.DamageType.ARCANE, + blight = engine.DamageType.BLIGHT, + nature = engine.DamageType.NATURE, + temporal = engine.DamageType.TEMPORAL, + light = engine.DamageType.LIGHT, + dark = engine.DamageType.DARK, + } + + local pickDamtype = function(themes_list) + if not rng.percent(18) then return engine.DamageType.PHYSICAL end + for k, v in pairs(themes_list) do + if theme_map[k] then return theme_map[k] end + end + return engine.DamageType.PHYSICAL + end + + if o and o.combat and not (o.subtype and o.subtype == "staff") and not (o.subtype and o.subtype == "mindstar") then o.combat.damtype = pickDamtype(themes) end + if data.post then data.post(o) end diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua index ed32980cbeda32eb482fdf23a3a98302bbc22c67..a0fa7e1c0a65a2ec0dd8170e984e9a9ded72e54b 100644 --- a/game/modules/tome/class/Object.lua +++ b/game/modules/tome/class/Object.lua @@ -647,6 +647,21 @@ function _M:getTextualDesc(compare_with, use_actor) end end + + local ranged_string = tstring{} + local ranged_combat = { ranged_project = {} } + for i, v in pairs(combat.ranged_project or {}) do + local def = DamageType.dam_def[i] + if def and def.tdesc then + local d = def.tdesc(v) + found = true + ranged_string:add(d, {"color","LAST"}, true) + + else + ranged_combat.ranged_project[i] = v + end + end + -- Add the on hit section only if theres a tdesc DT or a special_on_hit if found or special ~= "" then desc:add({"color","ORANGE"}, "When this weapon hits: ", {"color","LAST"}, true) @@ -661,6 +676,7 @@ function _M:getTextualDesc(compare_with, use_actor) -- Add the extended melee_project descriptions after special_on_hit, colors defined by tdesc if found then desc:merge(dt_string) + desc:merge(ranged_string) end -- only special_on_hit display is modified, not special_on_crit and so on @@ -724,7 +740,7 @@ function _M:getTextualDesc(compare_with, use_actor) return col[2], (" %s"):format(DamageType.dam_def[item].name),{"color","LAST"} end) - compare_table_fields(combat, compare_with, field, "ranged_project", "%+d", "Damage when this weapon hits(ranged): ", function(item) + compare_table_fields(ranged_combat, compare_with, field, "ranged_project", "%+d", "Damage (Ranged): ", function(item) local col = (DamageType.dam_def[item] and DamageType.dam_def[item].text_color or "#WHITE#"):toTString() return col[2], (" %s"):format(DamageType.dam_def[item].name),{"color","LAST"} end) diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 83a68b546366120a219c4e4822118316bf11a8f4..ceb88383daea7199de9ea90f52f5fbd3847ced27 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -434,7 +434,9 @@ function _M:updateMainShader() end -- Blur shader - if self:attr("confused") and self.confused >= 1 then pf.blur.shad:uniBlur(2) effects[pf.blur.shad] = true + if config.settings.tome.fullscreen_confusion then + if self:attr("confused") and self.confused >= 1 then pf.blur.shad:uniBlur(2) effects[pf.blur.shad] = true + end end -- Moving Blur shader @@ -448,8 +450,10 @@ function _M:updateMainShader() end -- Wobbling shader - if self:attr("stunned") and self.stunned >= 1 then pf.wobbling.shad:uniWobbling(1) effects[pf.wobbling.shad] = true - elseif self:attr("dazed") and self.dazed >= 1 then pf.wobbling.shad:uniWobbling(0.7) effects[pf.wobbling.shad] = true + if config.settings.tome.fullscreen_stun then + if self:attr("stunned") and self.stunned >= 1 then pf.wobbling.shad:uniWobbling(1) effects[pf.wobbling.shad] = true + elseif self:attr("dazed") and self.dazed >= 1 then pf.wobbling.shad:uniWobbling(0.7) effects[pf.wobbling.shad] = true + end end game.posteffects_use = table.keys(effects) @@ -828,8 +832,8 @@ function _M:automaticTalents() end table.sort(uses, function(a, b) local an, nb = util.getval(a.no_energy, self, a), util.getval(b.no_energy, self, b) - if an < bn then return true - elseif an > bn then return false + if an < nb then return true + elseif an > nb then return false else if a.cd > b.cd then return true else return false diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua index 8d4b1ab577da26d8f0d893ebd81528ee2e0e5285..f751bf690688e66fa082e3a5671ad957f514f24d 100644 --- a/game/modules/tome/class/interface/Combat.lua +++ b/game/modules/tome/class/interface/Combat.lua @@ -400,7 +400,7 @@ function _M:attackTargetWith(target, weapon, damtype, mult, force_dam) if target:knowTalent(target.T_SKIRMISHER_BUCKLER_EXPERTISE) then local t = target:getTalentFromId(target.T_SKIRMISHER_BUCKLER_EXPERTISE) if t.shouldEvade(target, t) then - game.logSeen(target, "%s deflects the attack.", target.name:capitalize()) + game.logSeen(target, "#ORCHID#%s deflects the attack with their buckler!#LAST#", target.name:capitalize()) t.onEvade(target, t, self) repelled = true end @@ -680,9 +680,13 @@ function _M:attackTargetWith(target, weapon, damtype, mult, force_dam) -- Arcane Destruction if hitted and crit and weapon and self:knowTalent(self.T_ARCANE_DESTRUCTION) then - local typ = rng.table{{DamageType.FIRE,"ball_fire"}, {DamageType.LIGHTNING,"ball_lightning_beam"}, {DamageType.ARCANE,"ball_arcane"}} - self:project({type="ball", radius=2, friendlyfire=false}, target.x, target.y, typ[1], self:combatSpellpower() * 2) - game.level.map:particleEmitter(target.x, target.y, 2, typ[2], {radius=2, tx=target.x, ty=target.y}) + local chance = 100 + if self:hasDualWeapon() or self:hasShield() then chance = 50 end + if rng.percent(chance) then + local typ = rng.table{{DamageType.FIRE,"ball_fire"}, {DamageType.LIGHTNING,"ball_lightning_beam"}, {DamageType.ARCANE,"ball_arcane"}} + self:project({type="ball", radius=2, friendlyfire=false}, target.x, target.y, typ[1], self:combatSpellpower() * 2) + game.level.map:particleEmitter(target.x, target.y, 2, typ[2], {radius=2, tx=target.x, ty=target.y}) + end end -- Onslaught @@ -1060,7 +1064,6 @@ function _M:combatDefenseBase(fake) if self:knowTalent(self.T_MISDIRECTION) then mult = mult + self:callTalent(self.T_MISDIRECTION,"getDefense")/100 end - return math.max(0, d * mult + add) -- Add bonuses last to avoid compounding defense multipliers from talents end @@ -1139,7 +1142,7 @@ function _M:combatAttack(weapon, ammo) end local d = self:combatAttackBase(weapon, ammo) + stats if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) end @@ -1151,7 +1154,7 @@ function _M:combatAttackRanged(weapon, ammo) end local d = self:combatAttackBase(weapon, ammo) + stats + (self.combat_atk_ranged or 0) if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) end @@ -1160,7 +1163,7 @@ end function _M:combatAttackStr(weapon, ammo) local d = self:combatAttackBase(weapon, ammo) + (self:getStr(100, true) - 10) if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) end @@ -1168,7 +1171,7 @@ end function _M:combatAttackDex(weapon, ammo) local d = self:combatAttackBase(weapon, ammo) + (self:getDex(100, true) - 10) if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) end @@ -1176,7 +1179,7 @@ end function _M:combatAttackMag(weapon, ammo) local d = self:combatAttackBase(weapon, ammo) + (self:getMag(100, true) - 10) if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) end @@ -1449,7 +1452,7 @@ function _M:combatPhysicalpower(mod, weapon, add) local d = math.max(0, self.combat_dam + add) + self:getStr() -- allows strong debuffs to offset strength if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) * mod end @@ -1481,7 +1484,7 @@ function _M:combatSpellpower(mod, add) local d = (self.combat_spellpower > 0 and self.combat_spellpower or 0) + add + self:getMag() if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) * mod * am end @@ -1622,7 +1625,7 @@ function _M:physicalCrit(dam, weapon, target, atk, def, add_chance, crit_power_a chance = chance - target:callTalent(target.T_SCOUNDREL,"getCritPenalty") end - if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and not target:canSee(self) then -- bug fix + if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and self:callTalent(self.T_SHADOWSTRIKE,"checkWeapon") and not target:canSee(self) then -- bug fix chance = 100 crit_power_add = crit_power_add + self:callTalent(self.T_SHADOWSTRIKE,"getMultiplier") end @@ -1667,8 +1670,8 @@ function _M:spellCrit(dam, add_chance, crit_power_add) local chance = self:combatSpellCrit() + (add_chance or 0) local crit = false --- if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and not target:canSee(self) then -- bug fix - if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) then -- bug fix + -- Unlike physical crits we can't know anything about our target here so we can't check if they can see us + if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and self:callTalent(self.T_SHADOWSTRIKE,"checkWeapon")then chance = 100 crit_power_add = crit_power_add + self:callTalent(self.T_SHADOWSTRIKE,"getMultiplier") end @@ -1717,8 +1720,7 @@ function _M:mindCrit(dam, add_chance, crit_power_add) local chance = self:combatMindCrit() + (add_chance or 0) local crit = false --- if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and not target:canSee(self) then -- bug fix - if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) then -- bug fix + if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and self:callTalent(self.T_SHADOWSTRIKE,"checkWeapon") then -- bug fix chance = 100 crit_power_add = crit_power_add + self:callTalent(self.T_SHADOWSTRIKE,"getMultiplier") end @@ -1773,7 +1775,7 @@ function _M:combatMindpower(mod, add) local d = (self.combat_mindpower > 0 and self.combat_mindpower or 0) + add + self:getWil() * 0.7 + self:getCun() * 0.4 if self:attr("dazed") then d = d / 2 end - if self:attr("scoured") then d = d / 1.5 end + if self:attr("scoured") then d = d / 1.2 end return self:rescaleCombatStats(d) * mod end @@ -1809,7 +1811,6 @@ end --- Gets damage based on talent, stat, and interval function _M:combatStatTalentIntervalDamage(t, stat, min, max, stat_weight) local stat_weight = stat_weight or 0.5 - scaled_stat = self[stat](self) return self:rescaleDamage(min + (max - min)*((stat_weight * self[stat](self)/100) + (1 - stat_weight) * self:getTalentLevel(t)/6.5)) end @@ -2256,7 +2257,7 @@ end -- grapple size check; compares attackers size and targets size function _M:grappleSizeCheck(target) - size = target.size_category - self.size_category + local size = target.size_category - self.size_category if size > 1 then self:logCombat(target, "#Source#'s grapple fails because #Target# is too big!") return true diff --git a/game/modules/tome/data/birth/classes/celestial.lua b/game/modules/tome/data/birth/classes/celestial.lua index f042c8f20d3f58b88ca87b433413c631738a49bf..283fb3a53d7eadf7f0414f47e1c8d933c13c6a91 100644 --- a/game/modules/tome/data/birth/classes/celestial.lua +++ b/game/modules/tome/data/birth/classes/celestial.lua @@ -96,6 +96,13 @@ newBirthDescriptor{ {type="armor", subtype="shield", name="iron shield", ignore_material_restriction=true, autoreq=true, ego_chance=-1000}, {type="armor", subtype="heavy", name="iron mail armour", ignore_material_restriction=true, autoreq=true, ego_chance=-1000}, }, + resolvers.inventory{ id=true, + {type="weapon", subtype="greatsword", name="iron greatsword", ignore_material_restriction=true, autoreq=true, ego_chance= -1000}, + }, + resolvers.inventory{ id=true, inven="QS_MAINHAND", + {type="weapon", subtype="longbow", name="elm longbow", autoreq=true, ego_chance=-1000}, + }, + }, copy_add = { life_rating = 2, diff --git a/game/modules/tome/data/birth/classes/rogue.lua b/game/modules/tome/data/birth/classes/rogue.lua index eb74b9411d960b612ac8fce43973b35f968a240c..43cdcd0b30e89f8e3947919020fa2c8ea90ea9a6 100644 --- a/game/modules/tome/data/birth/classes/rogue.lua +++ b/game/modules/tome/data/birth/classes/rogue.lua @@ -240,6 +240,9 @@ newBirthDescriptor{ {type="armor", subtype="shield", name="iron shield", autoreq=false, ego_chance=-1000, ego_chance=-1000}, {type="ammo", subtype="shot", name="pouch of iron shots", autoreq=true, ego_chance=-1000}, }, + resolvers.generic(function(e) + e.auto_shoot_talent = e.T_SHOOT + end), }, copy_add = { life_rating = 0, diff --git a/game/modules/tome/data/birth/classes/warrior.lua b/game/modules/tome/data/birth/classes/warrior.lua index e9c09d2faeb13f275967cd22bfa7efe6b841c3da..b8137eac4b114d3c6a147063f0b7a61dd3823fc4 100644 --- a/game/modules/tome/data/birth/classes/warrior.lua +++ b/game/modules/tome/data/birth/classes/warrior.lua @@ -218,14 +218,14 @@ newBirthDescriptor{ ["spell/conveyance"]={true, 0.2}, ["spell/aegis"]={true, 0.1}, ["spell/enhancement"]={true, 0.2}, - ["technique/battle-tactics"]={false, 0.2}, + --["technique/battle-tactics"]={false, 0.2}, ["technique/superiority"]={false, 0.2}, ["technique/combat-techniques-active"]={true, 0.1}, ["technique/combat-techniques-passive"]={false, 0.1}, ["technique/combat-training"]={true, 0.1}, ["technique/magical-combat"]={true, 0.3}, ["technique/shield-offense"]={false, 0}, - ["technique/2hweapon-cripple"]={false, 0}, + ["technique/2hweapon-assault"]={false, 0}, ["technique/dualweapon-attack"]={false, 0}, ["cunning/survival"]={true, 0.1}, ["cunning/dirty"]={true, 0.2}, diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 7726294e9e65fc693fcd298ba4220e9fdb6daddb..4379f9409e2f69fc3df050a17df5e583b31107cc 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -873,7 +873,7 @@ newDamageType{ -- Silence newDamageType{ - name = "arcane silence", type = "ARCANE_SILENCE", + name = "arcane silence", type = "ARCANE_SILENCE", text_color = "#PURPLE#", projector = function(src, x, y, type, dam) local chance = 100 if _G.type(dam) == "table" then dam, chance = dam.dam, dam.chance end @@ -1682,6 +1682,7 @@ newDamageType{ -- Name: item - theme - debuff/effect +-- Log entries are pretty limited currently because it can be quite spammy with the default messages already newDamageType{ name = "item mind gloom", type = "ITEM_MIND_GLOOM", tdesc = function(dam) @@ -1696,7 +1697,7 @@ newDamageType{ if effect == 1 then -- confusion if target:canBe("confusion") and not target:hasEffect(target.EFF_GLOOM_CONFUSED) then - target:setEffect(target.EFF_GLOOM_CONFUSED, 2, {power=70, no_ct_effect=true} ) + target:setEffect(target.EFF_GLOOM_CONFUSED, 2, {power=25, no_ct_effect=true} ) end elseif effect == 2 then -- stun @@ -1736,7 +1737,7 @@ newDamageType{ projector = function(src, x, y, type, dam) local target = game.level.map(x, y, Map.ACTOR) if target and src and src.name and rng.percent(dam) then - if src.turn_procs and src.turn_procs.item_temporal_energize and src.turn_procs.item_temporal_energize > 5 then + if src.turn_procs and src.turn_procs.item_temporal_energize and src.turn_procs.item_temporal_energize > 3 then game.logSeen(src, "#LIGHT_STEEL_BLUE#%s can't gain any more energy this turn! ", src.name:capitalize()) return end @@ -1793,15 +1794,15 @@ newDamageType{ if target and rng.percent(dam) then if target:canBe("stun") then local check = math.max(src:combatAttack(), src:combatSpellpower(), src:combatMindpower()) - target:setEffect(target.EFF_DAZED, 4, {apply_power=check, no_ct_effect=true}) + --game:onTickEnd(function() target:setEffect(target.EFF_DAZED, 3, {src=src, apply_power=dam.power_check or math.max(src:combatSpellpower(), src:combatMindpower(), src:combatAttack())}) end) -- Do it at the end so we don't break our own daze + game:onTickEnd(function() target:setEffect(target.EFF_DAZED, 4, {apply_power=check, no_ct_effect=true}) end) else --game.logSeen(target, "%s resists the daze!", target.name:capitalize()) end end end, } - --- Note: This spams a lot of magic debuffs. + newDamageType{ name = "item blight disease", type = "ITEM_BLIGHT_DISEASE", text_color = "#DARK_GREEN#", tdesc = function(dam) @@ -1809,12 +1810,10 @@ newDamageType{ end, projector = function(src, x, y, type, dam) local target = game.level.map(x, y, Map.ACTOR) - if target and target:canBe("disease") and rng.percent(dam) then + if target and rng.percent(dam) and target:canBe("disease") then local check = math.max(src:combatSpellpower(), src:combatMindpower(), src:combatAttack()) local disease_power = math.min(30, dam / 2) - local disease_dam = 0 - local eff = rng.table{{target.EFF_ROTTING_DISEASE, "con"}, {target.EFF_DECREPITUDE_DISEASE, "dex"}, {target.EFF_WEAKNESS_DISEASE, "str"}} - target:setEffect(eff[1], 5, { src = src, apply_power = check, no_ct_effect=true, [eff[2]] = disease_power, dam = disease_dam }) + target:setEffect(target.EFF_ITEM_BLIGHT_ILLNESS, 5, {reduce = disease_power}) end end, } @@ -1822,7 +1821,7 @@ newDamageType{ newDamageType{ name = "item manaburn arcane", type = "ITEM_ANTIMAGIC_MANABURN", text_color = "#PURPLE#", tdesc = function(dam) - return ("#PURPLE#%d#LAST# damage based on #PURPLE#arcane resource#LAST#"):format(dam) + return ("#DARK_ORCHID#%d arcane resource#LAST# burn"):format(dam) end, projector = function(src, x, y, type, dam) local target = game.level.map(x, y, Map.ACTOR) @@ -1853,26 +1852,26 @@ newDamageType{ newDamageType{ name = "item nature slow", type = "ITEM_NATURE_SLOW", text_color = "#LIGHT_GREEN#", tdesc = function(dam) - return ("#LIGHT_GREEN#%d%% nature#LAST# slow"):format(dam) + return ("Slows global speed by #LIGHT_GREEN#%d%%#LAST#"):format(dam) end, projector = function(src, x, y, type, dam) local target = game.level.map(x, y, Map.ACTOR) if target then - target:setEffect(target.EFF_SLOW, 3, {power=dam / 100, no_ct_effect=true}) + target:setEffect(target.EFF_SLOW, 3, {power= math.min(60, dam / 100), no_ct_effect=true}) end end, } --- Mostly used on specific egos +-- Reduces all offensive powers by 20% newDamageType{ name = "item antimagic scouring", type = "ITEM_ANTIMAGIC_SCOURING", text_color = "#ORCHID#", tdesc = function(dam) - return ("#LIGHT_GREEN#%d%%#LAST# chance to #ORCHID#reduce power ratings#LAST# by %d%%"):format(dam, 30) + return ("#LIGHT_GREEN#%d%%#LAST# chance to #ORCHID#reduce powers#LAST# by %d%%"):format(dam, 20) end, projector = function(src, x, y, type, dam) local target = game.level.map(x, y, Map.ACTOR) if target then - target:setEffect(target.EFF_ITEM_ANTIMAGIC_SCOURED, 3, {pct = 0.3, no_ct_effect=true}) + target:setEffect(target.EFF_ITEM_ANTIMAGIC_SCOURED, 3, {pct = 0.2, no_ct_effect=true}) end end, } diff --git a/game/modules/tome/data/general/objects/boss-artifacts-far-east.lua b/game/modules/tome/data/general/objects/boss-artifacts-far-east.lua index 961164fb54b0b32853e8ec528b3611a019f7dd97..91bac1ca6524001cd79ef60966eaea79e04590d7 100644 --- a/game/modules/tome/data/general/objects/boss-artifacts-far-east.lua +++ b/game/modules/tome/data/general/objects/boss-artifacts-far-east.lua @@ -460,11 +460,11 @@ newEntity{ base = "BASE_GREATMAUL", define_as="ROTTING_MAUL", dammod = {str=1.4}, convert_damage = {[DamageType.BLIGHT] = 20}, melee_project={[DamageType.ITEM_BLIGHT_DISEASE] = 50}, - special_on_hit = {desc="Damage nearby creatures", on_kill=1, fct=function(combat, who, target) + special_on_hit = {desc="Damages enemies in radius 1 around your target (based on Strength).", on_kill=1, fct=function(combat, who, target) local o, item, inven_id = who:findInAllInventoriesBy("define_as", "ROTTING_MAUL") - local dam = rng.avg(1,2) * (70+ who:getStr()) + local dam = rng.avg(1,3) * (70+ who:getStr()) game.logSeen(who, "The ground shakes as the %s hits!", o:getName()) - local tg = {type="ball", range=0, selffire=false, radius=2, no_restrict=true} + local tg = {type="ball", range=10, selffire=false, force_target=target, radius=1, no_restrict=true} who:project(tg, target.x, target.y, engine.DamageType.PHYSICAL, dam) end}, }, diff --git a/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua b/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua index 1d7eb10143d5b62d7f98fc423237ed913966950e..95bc4a4b3c9b9d445083ac0b220396e3d76b2f3a 100644 --- a/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua +++ b/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua @@ -1138,7 +1138,7 @@ Though clearly a powerful piece, it must once have been much greater.]], material_level = 3, wielder = { combat_def = 10, - combat_armor = 15, + combat_armor = 20, fatigue = 24, inc_stats = { [Stats.STAT_CON] = 5, }, diff --git a/game/modules/tome/data/general/objects/boss-artifacts.lua b/game/modules/tome/data/general/objects/boss-artifacts.lua index 35f575f2d4c2010aeb0aa71e0849fbe1aabd4e27..81c58ac7f0b0c55404917a9f9f152b758a5edc71 100644 --- a/game/modules/tome/data/general/objects/boss-artifacts.lua +++ b/game/modules/tome/data/general/objects/boss-artifacts.lua @@ -103,8 +103,9 @@ newEntity{ base = "BASE_TOOL_MISC", image="object/temporal_instability.png", [DamageType.PHYSICAL] = 5, }, }, + -- Trinket slots are allowed to have extremely good actives because of their opportunity cost max_power = 25, power_regen = 1, - use_talent = { id = Talents.T_ANIMATE_BLADE, level = 1, power = 25 }, + use_talent = { id = Talents.T_ANIMATE_BLADE, level = 1, power = 15 }, } newEntity{ base = "BASE_LONGSWORD", define_as = "RIFT_SWORD", @@ -174,6 +175,13 @@ newEntity{ base = "BASE_BATTLEAXE", physcrit = 8, dammod = {str=1.2}, melee_project={[DamageType.SLIME] = 50, [DamageType.ACID] = 50}, + special_on_crit = {desc="deal manaburn damage equal to your mindpower in a radius 3 cone", on_kill=1, fct=function(combat, who, target) + who.turn_procs.gaping_maw = (who.turn_procs.gaping_maw or 0) + 1 + local tg = {type="cone", range=10, radius=3, force_target=target, selffire=false} + local grids = who:project(tg, target.x, target.y, engine.DamageType.MANABURN, who:combatMindpower() / (who.turn_procs.gaping_maw)) + game.level.map:particleEmitter(target.x, target.y, tg.radius, "directional_shout", {life=8, size=3, tx=target.x-who.x, ty=target.y-who.y, distorion_factor=0.1, radius=3, nb_circles=8, rm=0.8, rM=1, gm=0.4, gM=0.6, bm=0.1, bM=0.2, am=1, aM=1}) + who.turn_procs.gaping_maw = (who.turn_procs.gaping_maw or 0) + 1 + end}, }, wielder = { talent_cd_reduction= { diff --git a/game/modules/tome/data/general/objects/egos/ammo.lua b/game/modules/tome/data/general/objects/egos/ammo.lua index 2d99e220760bd420e80ff2716e82f4e8f6f8291a..063fcc3cda7d5ceba4dd155ca94fd030c3b6bb1b 100644 --- a/game/modules/tome/data/general/objects/egos/ammo.lua +++ b/game/modules/tome/data/general/objects/egos/ammo.lua @@ -184,7 +184,7 @@ newEntity{ cost = 10, combat = { burst_on_hit={ - [DamageType.FIRE] = resolvers.mbonus_material(15, 5) + [DamageType.FIRE] = resolvers.mbonus_material(15, 10) }, }, } @@ -198,7 +198,7 @@ newEntity{ cost = 10, combat = { ranged_project={ - [DamageType.ICE] = resolvers.mbonus_material(15, 5) + [DamageType.COLD] = resolvers.mbonus_material(15, 5) }, }, } @@ -263,7 +263,8 @@ newEntity{ } -- Greater Egos --- This keeps its conversion because its an excellent swap ego for resistance problems + +-- Mostly flat damage because combatSpellpower is so frontloaded newEntity{ power_source = {arcane=true}, name = "elemental ", prefix=true, instant_resolve=true, @@ -272,34 +273,28 @@ newEntity{ greater_ego = 1, rarity = 25, cost = 35, + combat = { - ranged_project={ - [DamageType.FIRE] = resolvers.mbonus_material(5, 2), - [DamageType.COLD] = resolvers.mbonus_material(5, 2), - [DamageType.ACID] = resolvers.mbonus_material(5, 2), - [DamageType.LIGHTNING] = resolvers.mbonus_material(5, 2), - }, - convert_damage ={ - [DamageType.FIRE] = resolvers.mbonus_material(15, 10), - [DamageType.COLD] = resolvers.mbonus_material(15, 10), - [DamageType.ACID] = resolvers.mbonus_material(15, 10), - [DamageType.LIGHTNING] = resolvers.mbonus_material(15, 10), - }, - special_on_hit = {desc="random elemental effect", fct=function(combat, who, target) - local dam = 20 + (who:combatSpellpower()/5) - local tg = {type="hit", range=10} - local elem = rng.table{ - {engine.DamageType.FIREBURN, "flame"}, - {engine.DamageType.ICE, "freeze"}, - {engine.DamageType.LIGHTNING_DAZE, "lightning_explosion"}, - {engine.DamageType.ACID_BLIND, "acid"}, - } + -- Define this here so it stays in scope + elements = { + {engine.DamageType.FIRE, "flame"}, + {engine.DamageType.COLD, "freeze"}, + {engine.DamageType.LIGHTNING, "lightning_explosion"}, + {engine.DamageType.ACID, "acid"}, + }, + special_on_hit = {desc="Random elemental explosion", fct=function(combat, who, target) + if who.turn_procs.elemental_explosion then return end + who.turn_procs.elemental_explosion = 1 + + local elem = rng.table(combat.elements) + local dam = 20 + (who:combatSpellpower() ) -- Higher because Weapon's has a wielder table + local tg = {type="ball", radius=3, range=10, selffire = false, friendlyfire=false} who:project(tg, target.x, target.y, elem[1], rng.avg(dam / 2, dam, 3), {type=elem[2]}) end}, }, } --- Fix me + newEntity{ power_source = {arcane=true}, name = "plaguebringer's ", prefix=true, instant_resolve=true, @@ -313,10 +308,13 @@ newEntity{ [DamageType.BLIGHT] = resolvers.mbonus_material(15, 5), [DamageType.ITEM_BLIGHT_DISEASE] = resolvers.mbonus_material(15, 5), }, - talent_on_hit = { [Talents.T_EPIDEMIC] = {level=1, chance=10} }, + -- Well, Brawler Gloves do this calc for on hit Talents, and the new disease egos don't do damage, so.. What could possibly go wrong? + -- SCIENCE + talent_on_hit = { [Talents.T_EPIDEMIC] = {level=resolvers.genericlast(function(e) return e.material_level end), chance=10} }, }, } +-- Update Me newEntity{ power_source = {arcane=true}, name = "sentry's ", prefix=true, instant_resolve=true, @@ -326,6 +324,8 @@ newEntity{ greater_ego = 1, cost = 6, combat = { + dam = resolvers.mbonus_material(10, 2), + apr = resolvers.mbonus_material(10, 2), ammo_regen = resolvers.mbonus_material(3, 1), capacity = resolvers.generic(function(e) return e.combat.capacity * rng.float(1.2, 1.5) end), }, @@ -334,7 +334,6 @@ newEntity{ end), } --- Pretty scary! newEntity{ power_source = {arcane=true}, name = " of corruption", suffix=true, instant_resolve=true, @@ -613,7 +612,7 @@ newEntity{ keywords = {disruption=true}, level_range = {30, 50}, greater_ego = 1, - rarity = 50, + rarity = 40, cost = 40, combat = { inc_damage_type = { @@ -632,7 +631,7 @@ newEntity{ keywords = {leech=true}, level_range = {30, 50}, greater_ego = 1, - rarity = 50, + rarity = 40, cost = 40, combat = { ranged_project={[DamageType.ITEM_NATURE_SLOW] = resolvers.mbonus_material(15, 5)}, @@ -656,10 +655,11 @@ newEntity{ name = "hateful ", prefix=true, instant_resolve=true, keywords = {hateful=true}, level_range = {1, 50}, - rarity = 10, + rarity = 30, cost = 20, + greater_ego = 1, combat = { - ranged_project={[DamageType.DARKNESS] = resolvers.mbonus_material(15, 5)}, + ranged_project={[DamageType.DARKNESS] = resolvers.mbonus_material(25, 5)}, inc_damage_type = {living=resolvers.mbonus_material(15, 5)}, }, } @@ -677,12 +677,6 @@ newEntity{ [DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(25, 10) }, }, - wielder = { - inc_stats = { - [Stats.STAT_WIL] = resolvers.mbonus_material(6, 1), - [Stats.STAT_CUN] = resolvers.mbonus_material(6, 1), - }, - }, resolvers.genericlast(function(e) e.combat.ammo_every = 6 - (e.combat.ammo_regen or 0) end), @@ -690,7 +684,7 @@ newEntity{ newEntity{ power_source = {psionic=true}, - name = " of psychokinesis", suffix=true, instant_resolve=true, + name = "psychokinetic ", prefix=true, instant_resolve=true, keywords = {kinesis=true}, level_range = {1, 50}, rarity = 5, diff --git a/game/modules/tome/data/general/objects/egos/amulets.lua b/game/modules/tome/data/general/objects/egos/amulets.lua index bfd2bfe109c2fd44d1df8b9e4a3d5b8e462e3c1b..6f53cf06813f7bc0d9297af5e055bd57b2f7f76e 100644 --- a/game/modules/tome/data/general/objects/egos/amulets.lua +++ b/game/modules/tome/data/general/objects/egos/amulets.lua @@ -238,29 +238,13 @@ newEntity{ end), } --- The rest -newEntity{ - power_source = {nature=true}, - name = " of the fish", suffix=true, - keywords = {fish=true}, - level_range = {1, 50}, - rarity = 10, - cost = 10, - wielder = { - resists={ - [DamageType.COLD] = resolvers.mbonus_material(20, 10), - }, - can_breath = {water=1}, - }, -} - newEntity{ power_source = {psionic=true}, name = " of seduction", suffix=true, instant_resolve=true, keywords = {seduction=true}, level_range = {35, 50}, greater_ego = 1, - rarity = 25, + rarity = 50, cost = 50, wielder = { inc_damage = { @@ -508,6 +492,7 @@ newEntity{ inc_stats = { [Stats.STAT_LCK] = resolvers.mbonus_material(15, 5), }, + resist_unseen = resolvers.mbonus_material(10, 10), -- Makes more sense on Precognition helm, but I didn't want to overlap with the original stat use combat_def = resolvers.mbonus_material(15, 5), combat_atk = resolvers.mbonus_material(15, 5), }, @@ -571,4 +556,32 @@ newEntity{ [DamageType.DARKNESS] = resolvers.mbonus_material(10, 5), }, }, +} + +-- Upgraded Mastery +newEntity{ + power_source = {technique=true}, + name = " of perfection (#MASTERY#)", suffix=true, + keywords = {perfection=true}, + level_range = {30, 50}, + rarity = 25, + greater_ego = 1, + cost = 2, + wielder = {}, + resolvers.generic(function(e) + local tts = {} + local p = game:getPlayer(true) + for i, def in ipairs(engine.interface.ActorTalents.talents_types_def) do + if p and def.allow_random and p:knowTalentType(def.type) or p:knowTalentType(def.type) == false then tts[#tts+1] = def.type end + end + --local tt = tts[rng.range(1, #tts)] + local tt = rng.tableRemove(tts) + local tt2 = rng.tableRemove(tts) + + e.wielder.talents_types_mastery = {} + local v = (10 + rng.mbonus(math.ceil(30 * e.material_level / 5), resolvers.current_level, 50)) / 100 + e.wielder.talents_types_mastery[tt] = v + e.wielder.talents_types_mastery[tt2] = v + e.cost = e.cost + v * 60 + end), } \ No newline at end of file diff --git a/game/modules/tome/data/general/objects/egos/armor.lua b/game/modules/tome/data/general/objects/egos/armor.lua index e02d36933c3aa8cc14c1b7ca5b52915ef3f27504..9076d3b3e0b81b7216ba841ae8fba70bf5205f35 100644 --- a/game/modules/tome/data/general/objects/egos/armor.lua +++ b/game/modules/tome/data/general/objects/egos/armor.lua @@ -345,6 +345,5 @@ newEntity{ [DamageType.NATURE] = resolvers.mbonus_material(10, 10), [DamageType.BLIGHT] = resolvers.mbonus_material(10, 10), }, - max_life = resolvers.mbonus_material(40, 20), }, } \ No newline at end of file diff --git a/game/modules/tome/data/general/objects/egos/cloak.lua b/game/modules/tome/data/general/objects/egos/cloak.lua index e952f4dce06639e8a5df843990620f9c0b143b51..229c88318720bb6f795a3beb4dd0facc469f60aa 100644 --- a/game/modules/tome/data/general/objects/egos/cloak.lua +++ b/game/modules/tome/data/general/objects/egos/cloak.lua @@ -396,7 +396,7 @@ newEntity{ greater_ego = 1, rarity = 30, cost = 60, - resolvers.charmt(Talents.T_BLINDING_SPEED, {2,3,4}, 45), + --resolvers.charmt(Talents.T_BLINDING_SPEED, {2,3,4}, 45), wielder = { combat_atk = resolvers.mbonus_material(20, 15), max_life = resolvers.mbonus_material(70, 40), @@ -404,6 +404,43 @@ newEntity{ }, } +-- Partially tested +newEntity{ + power_source = {arcane=true}, + name = " of the voidstalker", suffix=true, instant_resolve=true, + keywords = {voidstriker=true}, + level_range = {20, 50}, + greater_ego = 1, + rarity = 30, + cost = 65, + wielder = { + resist_all_on_teleport = resolvers.mbonus_material(5, 10), + defense_on_teleport = resolvers.mbonus_material(20, 10), + effect_reduction_on_teleport = resolvers.mbonus_material(20, 10), + resists={ + [DamageType.TEMPORAL] = resolvers.mbonus_material(20, 10), + [DamageType.DARKNESS] = resolvers.mbonus_material(20, 10), + }, + }, + --charm_power = resolvers.mbonus_material(80, 20), + charm_power_def = {add=5, max=10, floor=true}, + resolvers.charm("blink to a random location within 2 spaces of target hostile creature", 10, function(self, who) + local tg = {type="hit", range=8, friendlyfire = false} + local x, y = who:getTarget(tg) + if not x or not y then return nil end + local _ _, x, y = who:canProject(tg, x, y) + local target = game.level.map(x, y, engine.Map.ACTOR) + if not target then return end + + game.level.map:particleEmitter(who.x, who.y, 1, "teleport") + who:teleportRandom(target.x, target.y, 2) + game.level.map:particleEmitter(who.x, who.y, 1, "teleport") + game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true}) + return {id=true, used=true} + end), +} + + newEntity{ power_source = {technique=true}, name = " of backstabbing", suffix=true, instant_resolve=true, @@ -413,7 +450,7 @@ newEntity{ rarity = 35, cost = 70, wielder = { - combat_critical_power = resolvers.mbonus_material(30, 10), + combat_critical_power = resolvers.mbonus_material(20, 10), combat_atk = resolvers.mbonus_material(10, 5), combat_apr = resolvers.mbonus_material(10, 5), inc_stealth = resolvers.mbonus_material(10, 5), diff --git a/game/modules/tome/data/general/objects/egos/digger.lua b/game/modules/tome/data/general/objects/egos/digger.lua index 5f5fd81e5cb00a7e8d4cc9358cc4e4bb599dbae2..f17abaf06aaf86f55d27863ea0de791c80678de1 100644 --- a/game/modules/tome/data/general/objects/egos/digger.lua +++ b/game/modules/tome/data/general/objects/egos/digger.lua @@ -140,9 +140,6 @@ newEntity{ [DamageType.FIRE] = resolvers.mbonus_material(10, 5), [DamageType.MIND] = resolvers.mbonus_material(10, 5), }, - melee_project={ - [DamageType.DREAMFORGE] = resolvers.mbonus_material(10, 5), - }, combat_mentalresist = resolvers.mbonus_material(10, 5), }, resolvers.generic(function(e) e.digspeed = math.ceil(e.digspeed / 2) end), diff --git a/game/modules/tome/data/general/objects/egos/gloves.lua b/game/modules/tome/data/general/objects/egos/gloves.lua index 8c748cd00d605ea3a5b4d4f673e42bcc1350137b..2f6ba6cb62820a2edbc2106c7e6b872b879d6175 100644 --- a/game/modules/tome/data/general/objects/egos/gloves.lua +++ b/game/modules/tome/data/general/objects/egos/gloves.lua @@ -385,7 +385,6 @@ newEntity{ combat = { physcrit = resolvers.mbonus_material(10, 4), atk = resolvers.mbonus_material(10, 2), - physspeed = -0.1, talent_on_hit = { [Talents.T_SET_UP] = {level=resolvers.genericlast(function(e) return e.material_level end), chance=10} }, }, }, @@ -474,7 +473,7 @@ newEntity{ greater_ego = 1, rarity = 35, cost = 80, - resolvers.charmt(Talents.T_TRACK, 2, 30), + resolvers.charmt(Talents.T_TRACK, 2, 15), wielder = { inc_stats = { [Stats.STAT_CUN] = resolvers.mbonus_material(5, 1), @@ -508,10 +507,10 @@ newEntity{ [DamageType.PHYSICAL] = resolvers.mbonus_material(8, 4), }, inc_stats = { - [Stats.STAT_CON] = resolvers.mbonus_material(5, 1), + [Stats.STAT_CON] = resolvers.mbonus_material(10, 5), }, - combat_armor = resolvers.mbonus_material(10, 5), - combat_armor_hardiness = resolvers.mbonus_material(5, 5), + combat_armor = resolvers.mbonus_material(15, 5), + combat_armor_hardiness = resolvers.mbonus_material(10, 5), combat = { talent_on_hit = { [Talents.T_STONE_TOUCH] = {level=resolvers.genericlast(function(e) return e.material_level end), chance=5} }, }, @@ -580,7 +579,7 @@ newEntity{ keywords = {regen=true}, level_range = {30, 50}, greater_ego = 1, - rarity = 18, + rarity = 25, cost = 25, wielder = { life_regen = resolvers.mbonus_material(45, 15, function(e, v) v=v/10 return 0, v end), diff --git a/game/modules/tome/data/general/objects/egos/light-armor.lua b/game/modules/tome/data/general/objects/egos/light-armor.lua index b2ab0daee66dfa7b8a7f4924ac4855623f458104..1f762fb85929d6c3c7493d80b585f89d253c3383 100644 --- a/game/modules/tome/data/general/objects/egos/light-armor.lua +++ b/game/modules/tome/data/general/objects/egos/light-armor.lua @@ -306,11 +306,11 @@ newEntity{ cost = 35, wielder = { inc_stats = { - [Stats.STAT_STR] = resolvers.mbonus_material(4, 3), - [Stats.STAT_DEX] = resolvers.mbonus_material(4, 3), - [Stats.STAT_WIL] = resolvers.mbonus_material(4, 3), - [Stats.STAT_CUN] = resolvers.mbonus_material(4, 3), - [Stats.STAT_MAG] = resolvers.mbonus_material(4, 3), + [Stats.STAT_STR] = resolvers.mbonus_material(6, 3), + [Stats.STAT_DEX] = resolvers.mbonus_material(6, 3), + [Stats.STAT_WIL] = resolvers.mbonus_material(6, 3), + [Stats.STAT_CUN] = resolvers.mbonus_material(6, 3), + [Stats.STAT_MAG] = resolvers.mbonus_material(6, 3), }, }, } diff --git a/game/modules/tome/data/general/objects/egos/lite.lua b/game/modules/tome/data/general/objects/egos/lite.lua index bc7b9886aa75c02edbdc63a2c7a9fc54efc2868f..2c61b6183064b740bc3b9591d2c91492682afba5 100644 --- a/game/modules/tome/data/general/objects/egos/lite.lua +++ b/game/modules/tome/data/general/objects/egos/lite.lua @@ -102,7 +102,7 @@ newEntity{ cost = 20, wielder = { inc_stats = { - [Stats.STAT_CUN] = resolvers.mbonus_material(4, 3), + [Stats.STAT_CUN] = resolvers.mbonus_material(8, 3), }, lite = -10, infravision = resolvers.mbonus_material(5, 4), @@ -281,6 +281,7 @@ newEntity{ name = " of the zealot", suffix=true, instant_resolve=true, keywords = {zealot=true}, level_range = {1, 50}, + greater_ego = 1, rarity = 15, cost = 10, wielder = { diff --git a/game/modules/tome/data/general/objects/egos/ranged.lua b/game/modules/tome/data/general/objects/egos/ranged.lua index e395e765186bdd95905cd1452614d6a01b3bbe86..bcf8df4656991d9243224e1ff7918059b3c7e93a 100644 --- a/game/modules/tome/data/general/objects/egos/ranged.lua +++ b/game/modules/tome/data/general/objects/egos/ranged.lua @@ -226,7 +226,7 @@ newEntity{ keywords = {wardens=true}, level_range = {30, 50}, greater_ego = 1, - rarity = 30, + rarity = 40, cost = 40, wielder = { inc_stats = { @@ -349,7 +349,7 @@ newEntity{ }, combat = { ranged_project={ - [DamageType.ICE] = resolvers.mbonus_material(15, 5), + [DamageType.COLD] = resolvers.mbonus_material(15, 5), }, }, } @@ -431,11 +431,12 @@ newEntity{ cost = 22, greater_ego = 1, combat = { - talent_on_hit = { [Talents.T_MANA_CLASH] = {level=1, chance=20} }, + --talent_on_hit = { [Talents.T_MANA_CLASH] = {level=1, chance=20} }, }, wielder = { inc_stats = { [Stats.STAT_WIL] = resolvers.mbonus_material(6, 1), + [Stats.STAT_CUN] = resolvers.mbonus_material(6, 1), }, combat_mindpower = resolvers.mbonus_material(10, 5), talents_types_mastery = { diff --git a/game/modules/tome/data/general/objects/egos/rings.lua b/game/modules/tome/data/general/objects/egos/rings.lua index 1a96574bbd2593355fc410098ca50df1ac23605b..b68e55405add5c0eb331baedaef29daaa26a820c 100644 --- a/game/modules/tome/data/general/objects/egos/rings.lua +++ b/game/modules/tome/data/general/objects/egos/rings.lua @@ -39,6 +39,7 @@ newEntity{ wielder = { see_invisible = resolvers.mbonus_material(20, 5), see_stealth = resolvers.mbonus_material(20, 5), + infravision = resolvers.mbonus_material(3, 3), blind_immune = resolvers.mbonus_material(30, 20, function(e, v) v=v/100 return 0, v end), }, } @@ -422,8 +423,8 @@ newEntity{ -- Stolen from Doctornull's addon newEntity{ power_source = {arcane=true}, - name = "faerie's ", prefix=true, instant_resolve=true, - keywords = {faerie=true}, + name = "pixie's ", prefix=true, instant_resolve=true, + keywords = {pixie=true}, level_range = {15, 50}, greater_ego = 1, rarity = 12, @@ -487,6 +488,7 @@ newEntity{ keywords = {painweaver=true}, level_range = {30, 50}, rarity = 20, + greater_ego = true, cost = 60, wielder = { combat_spellpower = resolvers.mbonus_material(15, 5), @@ -563,11 +565,11 @@ newEntity{ resolvers.charmt(Talents.T_BLEEDING_EDGE, {2,3,4}, 20), wielder = { melee_project = { - [DamageType.BLEED] = resolvers.mbonus_material(20, 20), + [DamageType.BLEED] = resolvers.mbonus_material(20, 5), [DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(10, 10), }, ranged_project = { - [DamageType.BLEED] = resolvers.mbonus_material(20, 20), + [DamageType.BLEED] = resolvers.mbonus_material(20, 5), [DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(10, 10), }, inc_stats = { @@ -642,10 +644,10 @@ newEntity{ cost = 60, wielder = { melee_project = { - [DamageType.ITEM_LIGHT_BLIND] = resolvers.mbonus_material(35, 10), + [DamageType.ITEM_LIGHT_BLIND] = resolvers.mbonus_material(25, 10), }, ranged_project = { - [DamageType.ITEM_LIGHT_BLIND] = resolvers.mbonus_material(35, 10), + [DamageType.ITEM_LIGHT_BLIND] = resolvers.mbonus_material(25, 10), }, }, } \ No newline at end of file diff --git a/game/modules/tome/data/general/objects/egos/robe.lua b/game/modules/tome/data/general/objects/egos/robe.lua index 55bf45e1c032c1e47494830dec9a3363ff8d3b8f..4f05214d3362f4ab27448f96648973e4e9fb3eb9 100644 --- a/game/modules/tome/data/general/objects/egos/robe.lua +++ b/game/modules/tome/data/general/objects/egos/robe.lua @@ -216,9 +216,11 @@ newEntity{ rarity = 30, cost = 60, wielder = { - inc_stats = { - [Stats.STAT_WIL] = resolvers.mbonus_material(5, 3), - [Stats.STAT_CUN] = resolvers.mbonus_material(5, 3), + lucid_dreamer=1, + sleep=1, + resists={ + [DamageType.MIND] = resolvers.mbonus_material(20, 10), + [DamageType.DARKNESS] = resolvers.mbonus_material(20, 10), }, combat_physresist = resolvers.mbonus_material(10, 10), combat_spellresist = resolvers.mbonus_material(10, 10), @@ -251,39 +253,31 @@ newEntity{ -- The rest newEntity{ power_source = {arcane=true}, - name = " of the elements", suffix=true, instant_resolve=true, - keywords = {elemental=true}, + name = " of alchemy", suffix=true, instant_resolve=true, + keywords = {alchemy=true}, level_range = {20, 50}, greater_ego = 1, rarity = 20, cost = 40, wielder = { - on_melee_hit = { + inc_damage = { [DamageType.ACID] = resolvers.mbonus_material(10, 5), - [DamageType.LIGHTNING] = resolvers.mbonus_material(10, 5), + [DamageType.PHYSICAL] = resolvers.mbonus_material(10, 5), [DamageType.FIRE] = resolvers.mbonus_material(10, 5), [DamageType.COLD] = resolvers.mbonus_material(10, 5), }, - inc_damage = { - [DamageType.ACID] = resolvers.mbonus_material(5, 5), - [DamageType.LIGHTNING] = resolvers.mbonus_material(5, 5), - [DamageType.FIRE] = resolvers.mbonus_material(5, 5), - [DamageType.COLD] = resolvers.mbonus_material(5, 5), - }, resists={ - [DamageType.ACID] = resolvers.mbonus_material(4, 4), - [DamageType.LIGHTNING] = resolvers.mbonus_material(4, 4), - [DamageType.FIRE] = resolvers.mbonus_material(4, 4), - [DamageType.COLD] = resolvers.mbonus_material(4, 4), - }, - melee_project={ - [DamageType.ACID] = resolvers.mbonus_material(5, 5), - [DamageType.LIGHTNING] = resolvers.mbonus_material(5, 5), - [DamageType.FIRE] = resolvers.mbonus_material(5, 5), - [DamageType.COLD] = resolvers.mbonus_material(5, 5), + [DamageType.ACID] = resolvers.mbonus_material(10, 10), + [DamageType.PHYSICAL] = resolvers.mbonus_material(10, 10), + [DamageType.FIRE] = resolvers.mbonus_material(10, 10), + [DamageType.COLD] = resolvers.mbonus_material(10, 10), }, + talent_cd_reduction = { + [Talents.T_REFIT_GOLEM] = resolvers.mbonus_material(4, 2), + } }, } + newEntity{ power_source = {arcane=true}, name = "spellwoven ", prefix=true, instant_resolve=true, @@ -385,14 +379,7 @@ newEntity{ cost = 15, wielder = { inc_damage = { - [DamageType.ARCANE] = resolvers.mbonus_material(15, 5), - [DamageType.FIRE] = resolvers.mbonus_material(15, 5), - [DamageType.COLD] = resolvers.mbonus_material(15, 5), - [DamageType.ACID] = resolvers.mbonus_material(15, 5), - [DamageType.LIGHTNING] = resolvers.mbonus_material(15, 5), - [DamageType.NATURE] = resolvers.mbonus_material(15, 5), - [DamageType.BLIGHT] = resolvers.mbonus_material(15, 5), - [DamageType.PHYSICAL] = resolvers.mbonus_material(15, 5), + all = resolvers.mbonus_material(15, 5), }, combat_spellpower = resolvers.mbonus_material(10, 10), }, @@ -444,7 +431,7 @@ newEntity{ }, combat_armor = resolvers.mbonus_material(5, 3), combat_def = resolvers.mbonus_material(5, 3), - lite = 1, + lite = resolvers.mbonus_material(3,1), max_life=resolvers.mbonus_material(40, 30), }, } @@ -478,15 +465,12 @@ newEntity{ [DamageType.ITEM_NATURE_SLOW] = resolvers.mbonus_material(7, 3), [DamageType.ITEM_ANTIMAGIC_MANABURN] = resolvers.mbonus_material(7, 3) }, - melee_project={ - [DamageType.ITEM_NATURE_SLOW] = resolvers.mbonus_material(7, 3), - }, }, } newEntity{ power_source = {nature=true}, - name = "stormlord's ", prefix=true, instant_resolve=true, - keywords = {stormlord=true}, + name = "stormwoven ", prefix=true, instant_resolve=true, + keywords = {storm=true}, level_range = {30, 50}, greater_ego = 1, rarity = 16, @@ -520,10 +504,11 @@ newEntity{ inc_stats = { [Stats.STAT_CON] = resolvers.mbonus_material(8, 2), }, - life_regen = resolvers.mbonus_material(75, 15, function(e, v) v=v/10 return 0, v end), inc_damage = { [DamageType.NATURE] = resolvers.mbonus_material(15, 5), }, + disease_immune = resolvers.mbonus_material(30, 20, function(e, v) return 0, v/100 end), + poison_immune = resolvers.mbonus_material(30, 20, function(e, v) return 0, v/100 end), }, } newEntity{ @@ -551,10 +536,10 @@ newEntity{ inc_stats = { [Stats.STAT_CUN] = resolvers.mbonus_material(9, 1), }, - combat_mindcrit = resolvers.mbonus_material(7, 5), - combat_critical_power = resolvers.mbonus_material(30, 10), + combat_critical_power = resolvers.mbonus_material(10, 10), hate_on_crit = resolvers.mbonus_material(3, 2), - }, + psi_on_crit = resolvers.mbonus_material(4, 1), + }, } newEntity{ power_source = {psionic=true}, diff --git a/game/modules/tome/data/general/objects/egos/shield.lua b/game/modules/tome/data/general/objects/egos/shield.lua index adc5e767f33eda5e4ce87b1f6a731edb74924087..68ff1d887b350f851a5ed21b9b948851a81e3885 100644 --- a/game/modules/tome/data/general/objects/egos/shield.lua +++ b/game/modules/tome/data/general/objects/egos/shield.lua @@ -180,10 +180,10 @@ newEntity{ rarity = 8, cost = 10, special_combat = { - melee_project={[DamageType.ICE] = resolvers.mbonus_material(10, 10)}, + melee_project={[DamageType.COLD] = resolvers.mbonus_material(10, 10)}, }, wielder = { - on_melee_hit={[DamageType.COLD] = resolvers.mbonus_material(10, 10)}, + on_melee_hit={[DamageType.ICE] = resolvers.mbonus_material(10, 10)}, melee_project={ [DamageType.COLD] = resolvers.mbonus_material(5, 5), }, @@ -237,13 +237,10 @@ newEntity{ level_range = {30, 50}, rarity = 25, cost = 12, - special_combat = { - melee_project={[DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(25, 10)}, - }, wielder = { on_melee_hit={[DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(25, 10)}, melee_project={ - [DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(5, 5), + [DamageType.ITEM_MIND_GLOOM] = resolvers.mbonus_material(10, 5), }, }, } @@ -270,7 +267,7 @@ newEntity{ [Stats.STAT_STR] = resolvers.mbonus_material(5, 1), }, on_melee_hit = { - [DamageType.FIRE] = resolvers.mbonus_material(10, 10), + [DamageType.FIRE] = resolvers.mbonus_material(30, 10), }, }, } @@ -426,18 +423,24 @@ newEntity{ }, } - +-- Meh, needed to re-use Scouring, needed AM shield egos, whatever newEntity{ - power_source = {nature=true}, - name = "blood-etched ", prefix=true, instant_resolve=true, - keywords = {etched=true}, + power_source = {antimagic=true}, + name = "scouring ", prefix=true, instant_resolve=true, + keywords = {scouring=true}, level_range = {30, 50}, greater_ego = 1, - rarity = 17, + rarity = 25, cost = 30, wielder = { - life_regen = resolvers.mbonus_material(30, 10, function(e, v) v=v/10 return 0, v end), - healing_factor = resolvers.mbonus_material(20, 10, function(e, v) v=v/100 return 0, v end), + resists={ + [DamageType.ACID] = resolvers.mbonus_material(15, 5), + [DamageType.NATURE] = resolvers.mbonus_material(15, 5), + }, + on_melee_hit = { + [DamageType.ITEM_ANTIMAGIC_SCOURING] = resolvers.mbonus_material(20, 15), + [DamageType.ITEM_ANTIMAGIC_MANABURN] = resolvers.mbonus_material(20, 15), + }, inc_stats = { [Stats.STAT_CON] = resolvers.mbonus_material(4, 3), }, @@ -493,7 +496,7 @@ newEntity{ [DamageType.DARKNESS] = resolvers.mbonus_material(10, 5), }, }, - on_block = {desc = "Unleash the fury of the cosmos, dealing light and darkness damage to your attacker", fct = function(self, who, target, type, dam, eff) + on_block = {desc = "Unleash the fury of the cosmos, dealing light and darkness damage to your attackers", fct = function(self, who, target, type, dam, eff) if not target or target:attr("dead") or not target.x or not target.y then return end if who.turn_procs and who.turn_procs.shield_cosmic and who.turn_procs.shield_cosmic[target.uid] then return end @@ -578,6 +581,8 @@ newEntity{ }, } +--[[ +Killing this feels weird but there are a lot of anti-poison/disease general tools going in 1.2 and since the stats on this sucked most people hated it anyway newEntity{ power_source = {nature=true}, name = " of harmony", suffix=true, instant_resolve=true, @@ -594,6 +599,7 @@ newEntity{ healing_factor = resolvers.mbonus_material(10, 10, function(e, v) v=v/100 return 0, v end), }, } +--]] newEntity{ power_source = {arcane=true}, @@ -605,12 +611,16 @@ newEntity{ cost = 12, special_combat = { melee_project={ - [DamageType.LIGHT] = resolvers.mbonus_material(30, 10), + [DamageType.LIGHT] = resolvers.mbonus_material(10, 10), }, }, wielder = { + resists={ + [DamageType.LIGHT] = resolvers.mbonus_material(10, 10), + }, inc_stats = { [Stats.STAT_MAG] = resolvers.mbonus_material(5, 1), + [Stats.STAT_CON] = resolvers.mbonus_material(4, 3), }, on_melee_hit = { [DamageType.ITEM_LIGHT_BLIND] = resolvers.mbonus_material(30, 10), diff --git a/game/modules/tome/data/general/objects/egos/staves.lua b/game/modules/tome/data/general/objects/egos/staves.lua index 73a79003bd9e1e2c718b0ad3622f61919fbd4e6c..d9460eeea913fe587112126f1dfb042a41bbe5e9 100644 --- a/game/modules/tome/data/general/objects/egos/staves.lua +++ b/game/modules/tome/data/general/objects/egos/staves.lua @@ -256,6 +256,7 @@ newEntity{ return end local combat = weapon.combat + local explosion, particle, trail local DamageType = require "engine.DamageType" local damtype = combat.damtype @@ -281,7 +282,7 @@ newEntity{ dam = rng.range(dam, dam * damrange) dam = who:spellCrit(dam) - who:projectile(tg, x, y, damtype, dam, {type=explosion}) + who:projectile(tg, x, y, damtype, dam, {type=explosion, particle=particle, trail=trail}) game.logSeen(who, "%s fires a bolt from %s!", who.name:capitalize(), self.name) game:playSoundNear(who, "talents/arcane") diff --git a/game/modules/tome/data/general/objects/egos/torques-powers.lua b/game/modules/tome/data/general/objects/egos/torques-powers.lua index 22bee07a38121383876f78261a45a9eb90a6ad52..2eadcd06265dd3ccd805bcff6f2576afa3093443 100644 --- a/game/modules/tome/data/general/objects/egos/torques-powers.lua +++ b/game/modules/tome/data/general/objects/egos/torques-powers.lua @@ -50,7 +50,7 @@ newEntity{ rarity = 7, charm_power_def = {add=3, max=200, floor=true}, - resolvers.charm("setup a psionic shield, reducing all physical, nature, temporal and acid damage by %d for 6 turns", 20, function(self, who) + resolvers.charm("setup a psionic shield, reducing all physical, nature, temporal and acid damage by %d for 7 turns", 20, function(self, who) who:setEffect(who.EFF_PSIONIC_SHIELD, 7, {kind="kinetic", power=self:getCharmPower(who)}) game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true}) return {id=true, used=true} @@ -64,7 +64,7 @@ newEntity{ rarity = 7, charm_power_def = {add=3, max=200, floor=true}, - resolvers.charm("setup a psionic shield, reducing all fire, cold, light, and arcane damage by %d for 6 turns", 20, function(self, who) + resolvers.charm("setup a psionic shield, reducing all fire, cold, light, and arcane damage by %d for 7 turns", 20, function(self, who) who:setEffect(who.EFF_PSIONIC_SHIELD, 7, {kind="thermal", power=self:getCharmPower(who)}) game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true}) return {id=true, used=true} @@ -78,7 +78,7 @@ newEntity{ rarity = 8, charm_power_def = {add=3, max=200, floor=true}, - resolvers.charm("setup a psionic shield, reducing all lightning, blight, mind, and darkness damage by %d for 6 turns", 20, function(self, who) + resolvers.charm("setup a psionic shield, reducing all lightning, blight, mind, and darkness damage by %d for 7 turns", 20, function(self, who) who:setEffect(who.EFF_PSIONIC_SHIELD, 7, {kind="charged", power=self:getCharmPower(who)}) game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true}) return {id=true, used=true} diff --git a/game/modules/tome/data/general/objects/egos/totems-powers.lua b/game/modules/tome/data/general/objects/egos/totems-powers.lua index 79dc4b202479aeadadecbde4775e0c84c4cd2461..775709d45ed5e336874fb1fc8ea7a3b0aa1f14f3 100644 --- a/game/modules/tome/data/general/objects/egos/totems-powers.lua +++ b/game/modules/tome/data/general/objects/egos/totems-powers.lua @@ -73,7 +73,7 @@ newEntity{ rarity = 6, charm_power_def = {add=5, max=100, floor=true}, - resolvers.charm(function(self) return ("harden the skin for 6 turns increasing armour by %d and armour hardiness by %d%%%%"):format(self:getCharmPower(who), 20 + self.material_level * 10) end, 20, function(self, who) + resolvers.charm(function(self) return ("harden the skin for 7 turns increasing armour by %d and armour hardiness by %d%%%%"):format(self:getCharmPower(who), 20 + self.material_level * 10) end, 20, function(self, who) who:setEffect(who.EFF_THORNY_SKIN, 7, {ac=self:getCharmPower(who), hard=20 + self.material_level * 10}) game:playSoundNear(who, "talents/heal") game.logSeen(who, "%s uses %s!", who.name:capitalize(), self:getName{no_count=true}) @@ -88,7 +88,7 @@ newEntity{ rarity = 20, charm_power_def = {add=50, max=250, floor=true}, - resolvers.charm("heal the target for %d", 35, function(self, who) + resolvers.charm("heal the target for %d", 20, function(self, who) local tg = {default_target=who, type="hit", nowarning=true, range=6 + who:getWil(4), first_target="friend"} local x, y = who:getTarget(tg) if not x or not y then return nil end diff --git a/game/modules/tome/data/general/objects/egos/weapon.lua b/game/modules/tome/data/general/objects/egos/weapon.lua index 90d461aa3fb5df585de57b078c16208bafdc91d8..49c5e5b873cffadd17bf82b88a4e488e04cdc63d 100644 --- a/game/modules/tome/data/general/objects/egos/weapon.lua +++ b/game/modules/tome/data/general/objects/egos/weapon.lua @@ -263,14 +263,14 @@ newEntity{ newEntity{ power_source = {arcane=true}, - name = "icy ", prefix=true, instant_resolve=true, - keywords = {icy=true}, + name = "chilling ", prefix=true, instant_resolve=true, + keywords = {chilling=true}, level_range = {15, 50}, rarity = 5, cost = 10, combat = { melee_project={ - [DamageType.ICE] = resolvers.mbonus_material(15, 5) + [DamageType.COLD] = resolvers.mbonus_material(25, 5) }, }, } @@ -340,33 +340,38 @@ newEntity{ -- Greater Egos --- This keeps the damage conversion because its excellent for swapping on resistant targets --- Changed to low level because its a utility ego thats useful all game +-- Mostly flat damage because combatSpellpower is so frontloaded newEntity{ power_source = {arcane=true}, name = "elemental ", prefix=true, instant_resolve=true, keywords = {elemental=true}, - level_range = {1, 50}, + level_range = {35, 50}, greater_ego = 1, - rarity = 30, + rarity = 25, cost = 35, - combat = { - convert_damage ={ - [DamageType.FIRE] = resolvers.mbonus_material(15, 10), - [DamageType.COLD] = resolvers.mbonus_material(15, 10), - [DamageType.ACID] = resolvers.mbonus_material(15, 10), - [DamageType.LIGHTNING] = resolvers.mbonus_material(15, 10), - }, - special_on_hit = {desc="random elemental effect", fct=function(combat, who, target) - local dam = 20 + (who:combatSpellpower()/5) - local tg = {type="hit", range=1} - local elem = rng.table{ - {engine.DamageType.FIREBURN, "flame"}, - {engine.DamageType.ICE, "freeze"}, - {engine.DamageType.LIGHTNING_DAZE, "lightning_explosion"}, - {engine.DamageType.ACID_BLIND, "acid"}, - } - who:project(tg, target.x, target.y, elem[1], rng.avg(dam / 2, dam, 3), {type=elem[2]}) + wielder = { + resists_pen={ + [DamageType.ACID] = resolvers.mbonus_material(10, 7), + [DamageType.LIGHTNING] = resolvers.mbonus_material(10, 7), + [DamageType.FIRE] = resolvers.mbonus_material(10, 7), + [DamageType.COLD] = resolvers.mbonus_material(10, 7), + }, + }, + combat = { + -- Define this here so it stays in scope + elements = { + {engine.DamageType.FIRE, "flame"}, + {engine.DamageType.COLD, "freeze"}, + {engine.DamageType.LIGHTNING, "lightning_explosion"}, + {engine.DamageType.ACID, "acid"}, + }, + special_on_hit = {desc="Random elemental explosion", fct=function(combat, who, target) + if who.turn_procs.elemental_explosion then return end + who.turn_procs.elemental_explosion = 1 + local elem = rng.table(combat.elements) + local dam = 10 + (who:combatSpellpower() ) + local tg = {type="ball", radius=3, range=10, selffire = false, friendlyfire=false} + who:project(tg, target.x, target.y, elem[1], rng.avg(dam / 2, dam, 3), {type=elem[2]}) end}, }, } @@ -387,7 +392,9 @@ newEntity{ [DamageType.BLIGHT] = resolvers.mbonus_material(15, 5), [DamageType.ITEM_BLIGHT_DISEASE] = resolvers.mbonus_material(15, 5), }, - talent_on_hit = { [Talents.T_EPIDEMIC] = {level=1, chance=10} }, + -- Well, Brawler Gloves do this calc for on hit Talents, and the new disease egos don't do damage, so.. What could possibly go wrong? + -- SCIENCE + talent_on_hit = { [Talents.T_EPIDEMIC] = {level=resolvers.genericlast(function(e) return e.material_level end), chance=10} }, }, } @@ -560,7 +567,6 @@ newEntity{ }, } --- Damtype nature? newEntity{ power_source = {nature=true}, name = " of nature", suffix=true, instant_resolve=true, @@ -576,9 +582,7 @@ newEntity{ }, }, combat = { - convert_damage = { - [DamageType.NATURE] = resolvers.mbonus_material(25, 25), - }, + }, } @@ -736,7 +740,7 @@ newEntity{ keywords = {leech=true}, level_range = {10, 50}, greater_ego = 1, - rarity = 50, + rarity = 40, cost = 40, wielder = { on_melee_hit = { @@ -756,6 +760,24 @@ newEntity{ }, } +newEntity{ + power_source = {antimagic=true}, + name = " of dampening", suffix=true, instant_resolve=true, + keywords = {dampening=true}, + level_range = {1, 50}, + rarity = 18, + cost = 22, + wielder = { + resists={ + [DamageType.ACID] = resolvers.mbonus_material(10, 7), + [DamageType.LIGHTNING] = resolvers.mbonus_material(10, 7), + [DamageType.FIRE] = resolvers.mbonus_material(10, 7), + [DamageType.COLD] = resolvers.mbonus_material(10, 7), + }, + combat_spellresist = resolvers.mbonus_material(10, 5), + }, +} + ------------------------------------------------------- -- Psionic Egos: -------------------------------------- ------------------------------------------------------- @@ -779,7 +801,7 @@ newEntity{ level_range = {1, 50}, rarity = 5, cost = 15, - resolvers.charm("project an attack as mind damage doing 200%% weapon damage at range 10", 6, + resolvers.charm("project an attack as mind damage doing 150%% weapon damage at range 10", 6, function(self, who) local tg = {type="hit", range=10} local x, y = who:getTarget(tg) @@ -787,7 +809,7 @@ newEntity{ local _ _, x, y = who:canProject(tg, x, y) local target = game.level.map(x, y, engine.Map.ACTOR) if target then - who:attackTarget(target, engine.DamageType.MIND, 1, true) + who:attackTarget(target, engine.DamageType.MIND, 1.5, true) else return end diff --git a/game/modules/tome/data/general/objects/lore/misc.lua b/game/modules/tome/data/general/objects/lore/misc.lua index 26d5fe48c7da17a21a7c7d1e685da4c86e742449..074408d0e78f515eaeee49ab3182d3040087d148 100644 --- a/game/modules/tome/data/general/objects/lore/misc.lua +++ b/game/modules/tome/data/general/objects/lore/misc.lua @@ -24,6 +24,13 @@ newEntity{ base = "BASE_LORE_RANDOM", rarity = 40, } +newEntity{ base = "BASE_LORE_RANDOM", + name = "On Adventuring", lore="kestin-highfin-adventuring-notes", unique=true, + desc = [[Fragments of a fabled traveler.]], + level_range = {10, 25}, + rarity = 35, +} + newEntity{ base = "BASE_LORE_RANDOM", name = "memories of Artelia Firstborn", lore="creation-elf", unique=true, desc = [[The memories of the first elf ever to awaken.]], diff --git a/game/modules/tome/data/general/objects/random-artifacts/ammo.lua b/game/modules/tome/data/general/objects/random-artifacts/ammo.lua index 457e5bc0e4c56720911d4fc0e2d241a86965b67e..5d6a2553de8128a1d0d847d95103a4be8c782f4c 100644 --- a/game/modules/tome/data/general/objects/random-artifacts/ammo.lua +++ b/game/modules/tome/data/general/objects/random-artifacts/ammo.lua @@ -80,10 +80,12 @@ newEntity{ theme={temporal=true}, name="temporal ranged", points = 2, rarity = 2 ---------------------------------------------------------------- --Ranged damage Projection (rare) ---------------------------------------------------------------- --- Missing a greater pairing for Fire, Arcane, Physical for now newEntity{ theme={blight=true}, name="corrupted blood melee", points = 2, rarity = 20, level_range = {1, 50}, combat = { ranged_project = {[DamageType.ITEM_BLIGHT_DISEASE] = resolvers.randartmax(20, 40), }, }, } +newEntity{ theme={temporal=true}, name="temporal energize melee", points = 2, rarity = 20, level_range = {1, 50}, + combat = { ranged_project = {[DamageType.ITEM_TEMPORAL_ENERGIZE] = resolvers.randartmax(20, 40), }, }, +} newEntity{ theme={blight=true}, name="gloom mind melee", points = 2, rarity = 20, level_range = {1, 50}, combat = { ranged_project = {[DamageType.ITEM_MIND_GLOOM] = resolvers.randartmax(20, 40), }, }, } @@ -192,6 +194,7 @@ newEntity{ theme={temporal=true}, name="temporal burst (crit)", points = 6, rari ---------------------------------------------------------------- -- Slaying ---------------------------------------------------------------- +--[[ newEntity{ theme={physical=true}, name="slay humanoid", points = 1, rarity = 22, level_range = {1, 50}, combat = { inc_damage_type = {humanoid=resolvers.randartmax(5, 25),},}, } @@ -224,4 +227,5 @@ newEntity{ theme={physical=true}, name="slay insect", points = 1, rarity = 22, l } newEntity{ theme={physical=true}, name="slay spiderkin", points = 1, rarity = 22, level_range = {1, 50}, combat = { inc_damage_type = {spiderkin=resolvers.randartmax(5, 25),},}, -} \ No newline at end of file +} +--]] \ No newline at end of file diff --git a/game/modules/tome/data/general/objects/random-artifacts/generic.lua b/game/modules/tome/data/general/objects/random-artifacts/generic.lua index 011b04764adb21ec4d73843583979ffb8fb9966e..852532c80c8e42ab690a1a5ec0c46dc7659f7b18 100644 --- a/game/modules/tome/data/general/objects/random-artifacts/generic.lua +++ b/game/modules/tome/data/general/objects/random-artifacts/generic.lua @@ -64,15 +64,6 @@ newEntity{ theme={spell=true}, name="vim on crit", points = 1, rarity = 16, leve newEntity{ theme={spell=true}, name="phasing", points = 1, rarity = 16, level_range = {1, 50}, wielder = { damage_shield_penetrate = resolvers.randartmax(10, 50), }, } -newEntity{ theme={defense=true, spell=true}, name="void resist", points = 2, rarity = 16, level_range = {1, 50}, - wielder = { resist_all_on_teleport = resolvers.randartmax(2, 20), }, -} -newEntity{ theme={defense=true, spell=true}, name="void defense", points = 2, rarity = 16, level_range = {1, 50}, - wielder = { defense_on_teleport = resolvers.randartmax(5, 25), }, -} -newEntity{ theme={defense=true, spell=true}, name="void effect reduction", points = 2, rarity = 16, level_range = {1, 50}, - wielder = { effect_reduction_on_teleport = resolvers.randartmax(10, 40), }, -} ---------------------------------------------------------------- -- Mental Themes @@ -110,9 +101,6 @@ newEntity{ theme={mental=true}, name="max psi", points = 1, rarity = 16, level_r newEntity{ theme={mental=true}, name="psi on hit", points = 1, rarity = 16, level_range = {1, 50}, wielder = { psi_regen_when_hit = resolvers.randartmax(.04, 2), }, } -newEntity{ theme={mental=true}, name="psi on crit", points = 1, rarity = 16, level_range = {1, 50}, - wielder = { psi_on_crit = resolvers.randartmax(1, 5), }, -} ---------------------------------------------------------------- -- Misc @@ -177,10 +165,8 @@ newEntity{ theme={physical=true}, name="greater max encumbrance", points = 1, ra -- Defense ---------------------------------------------------------------- newEntity{ theme={defense=true}, name="def", points = 2, rarity = 8, level_range = {1, 50}, - wielder = { combat_def = resolvers.randartmax(2, 20), }, -} -newEntity{ theme={defense=true}, name="rdef", points = 1.5, rarity = 12, level_range = {1, 50}, - wielder = { combat_def_ranged = resolvers.randartmax(2, 20), }, + wielder = { combat_def = resolvers.randartmax(2, 20), + combat_def_ranged = resolvers.randartmax(2, 20), }, } newEntity{ theme={defense=true}, name="armor", points = 2, rarity = 8, level_range = {1, 50}, wielder = { combat_armor = resolvers.randartmax(2, 20), }, @@ -230,7 +216,7 @@ newEntity{ theme={defense=true}, name="immune disarm", points = 1, rarity = 11, newEntity{ theme={defense=true}, name="immune cut", points = 1, rarity = 14, level_range = {1, 50}, wielder = { cut_immune = resolvers.randartmax(0.05, 0.5), }, } -newEntity{ theme={defense=true}, name="immune teleport", points = 1, rarity = 14, level_range = {1, 50}, +newEntity{ theme={defense=true}, name="immune teleport", points = 1, rarity = 20, level_range = {1, 50}, wielder = { teleport_immune = resolvers.randartmax(0.05, 0.5), }, } -------------------------------------------------------------- @@ -474,9 +460,6 @@ newEntity{ theme={misc=true, darkness=true}, name="infravision radius", points = newEntity{ theme={misc=true, light=true}, name="lite radius", points = 1, rarity = 14, level_range = {1, 50}, wielder = { lite = resolvers.randartmax(1, 3), }, } -newEntity{ theme={misc=true}, name="water breathing", points = 2, rarity = 30, level_range = {1, 50}, - wielder = { can_breath = {water=1}, }, -} newEntity{ theme={misc=true, mental=true}, name="telepathy", points = 60, rarity = 100, level_range = {1, 50}, wielder = { esp_all = 1 }, } @@ -494,32 +477,59 @@ newEntity{ theme={misc=true, mental=true}, name="demon telepathy", points = 2, r -- Melee damage Projection (rare) ---------------------------------------------------------------- newEntity{ theme={blight=true}, name="corrupted blood melee", points = 2, rarity = 25, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_BLIGHT_DISEASE] = resolvers.randartmax(10, 30), }, }, + wielder = { + melee_project = {[DamageType.ITEM_BLIGHT_DISEASE] = resolvers.randartmax(10, 30), }, + --ranged_project = {[DamageType.ITEM_BLIGHT_DISEASE] = resolvers.randartmax(10, 30), }, + } } + newEntity{ theme={acid=true}, name="acid corrode melee", points = 2, rarity = 20, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_ACID_CORRODE] = resolvers.randartmax(15, 40), }, }, -} + wielder = { melee_project = {[DamageType.ITEM_ACID_CORRODE] = resolvers.randartmax(15, 40), }, + --ranged_project = {[DamageType.ITEM_ACID_CORRODE] = resolvers.randartmax(15, 40), }, + } + } newEntity{ theme={light=true}, name="light blind melee", points = 2, rarity = 20, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_LIGHT_BLIND] = resolvers.randartmax(15, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_LIGHT_BLIND] = resolvers.randartmax(15, 40), }, + --ranged_project = {[DamageType.ITEM_LIGHT_BLIND] = resolvers.randartmax(15, 40), }, + }, } newEntity{ theme={temporal=true}, name="temporal energize melee", points = 2, rarity = 20, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_TEMPORAL_ENERGIZE] = resolvers.randartmax(10, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_TEMPORAL_ENERGIZE] = resolvers.randartmax(10, 40), }, + --ranged_project = {[DamageType.ITEM_TEMPORAL_ENERGIZE] = resolvers.randartmax(10, 40), }, + }, } newEntity{ theme={lightning=true}, name="lightning daze melee", points = 2, rarity = 20, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_LIGHTNING_DAZE] = resolvers.randartmax(15, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_LIGHTNING_DAZE] = resolvers.randartmax(15, 40), }, + --ranged_project = {[DamageType.ITEM_LIGHTNING_DAZE] = resolvers.randartmax(15, 40), }, + + }, } newEntity{ theme={antimagic=true}, name="manaburn melee", points = 2, rarity = 18, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_ANTIMAGIC_MANABURN] = resolvers.randartmax(10, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_ANTIMAGIC_MANABURN] = resolvers.randartmax(10, 40), }, + --ranged_project = {[DamageType.ITEM_ANTIMAGIC_MANABURN] = resolvers.randartmax(10, 40), }, + }, } newEntity{ theme={nature=true, antimagic=true}, name="slime melee", points = 2, rarity = 18, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_NATURE_SLOW] = resolvers.randartmax(15, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_NATURE_SLOW] = resolvers.randartmax(15, 40), }, + --ranged_project = {[DamageType.ITEM_NATURE_SLOW] = resolvers.randartmax(15, 40), }, + + }, } newEntity{ theme={dark=true}, name="dark numbing melee", points = 2, rarity = 24, level_range = {1, 50}, - wielder = { melee_project = {[DamageType.ITEM_DARKNESS_NUMBING] = resolvers.randartmax(15, 40), }, }, + wielder = { + melee_project = {[DamageType.ITEM_DARKNESS_NUMBING] = resolvers.randartmax(15, 40), }, + --ranged_project = {[DamageType.ITEM_DARKNESS_NUMBING] = resolvers.randartmax(15, 40), }, + }, + } ---------------------------------------------------------------- --- High level +-- High level -- Hesitant to put an offensive ones here because of how good this set is for offense already ---------------------------------------------------------------- -- The ultimate Ghoul buff @@ -531,32 +541,26 @@ newEntity{ theme={physical = true, misc = true, defense=true}, name="ignore crit wielder = { ignore_direct_crits = resolvers.randartmax(5, 15), }, } +-- High level partly for power but mostly because you need to assemble some tools before this is useful +newEntity{ theme={defense=true, spell=true}, name="void", points = 2, rarity = 16, level_range = {20, 50}, + wielder = { defense_on_teleport = resolvers.randartmax(5, 15), + resist_all_on_teleport = resolvers.randartmax(2, 15), + effect_reduction_on_teleport = resolvers.randartmax(10, 25) + }, +} + + -- These save powers are a somewhat hacky way to help player resists continue scaling in higher difficulty/ID/whatever -- With a min level of 30 and high rarity they won't have a dramatic impact on normal -newEntity{ theme={defense=true, physical=true}, name="save physical", points = 1, rarity = 18, level_range = {40, 50}, +newEntity{ theme={defense=true, physical=true}, name="save physical", points = 1, rarity = 18, level_range = {30, 50}, wielder = { combat_physresist = resolvers.randartmax(10, 25), }, } -newEntity{ theme={defense=true, spell=true, antimagic=true}, name="save spell", points = 1, rarity = 18, level_range = {40, 50}, +newEntity{ theme={defense=true, spell=true, antimagic=true}, name="save spell", points = 1, rarity = 18, level_range = {30, 50}, wielder = { combat_spellresist = resolvers.randartmax(10, 25), }, } -newEntity{ theme={defense=true, mental=true}, name="save mental", points = 1, rarity = 18, level_range = {40, 50}, +newEntity{ theme={defense=true, mental=true}, name="save mental", points = 1, rarity = 18, level_range = {30, 50}, wielder = { combat_mentalresist = resolvers.randartmax(10, 25), }, } ---[[ Doesn't work, power system only supports integers, or something -newEntity{ theme={spell=true}, name="spell speed greater", points = 1, rarity = 20, level_range = {20, 50}, - wielder = { combat_spellspeed = resolvers.randartmax(0.05, 0.1), }, -} - -newEntity{ theme={mental=true}, name="mind speed greater", points = 1, rarity = 20, level_range = {20, 50}, - wielder = { combat_mindspeed = resolvers.randartmax(0.05, 0.1), }, -} - -newEntity{ theme={misc = true, physical=true}, name="move speed greater", points = 1, rarity = 20, level_range = {20, 50}, - wielder = { move_speed = resolvers.randartmax(0.05, 0.1), }, -} ---]] - - diff --git a/game/modules/tome/data/general/objects/random-artifacts/melee.lua b/game/modules/tome/data/general/objects/random-artifacts/melee.lua index 23870c4b8029cd111ecc564fd3c357858b63228c..b9b40f35445aaebc4c7f4d97dda777b1017f4824 100644 --- a/game/modules/tome/data/general/objects/random-artifacts/melee.lua +++ b/game/modules/tome/data/general/objects/random-artifacts/melee.lua @@ -192,6 +192,7 @@ newEntity{ theme={temporal=true}, name="temporal burst (crit)", points = 6, rari ---------------------------------------------------------------- -- Slaying ---------------------------------------------------------------- +--[[ newEntity{ theme={physical=true}, name="slay humanoid", points = 1, rarity = 22, level_range = {1, 50}, combat = { inc_damage_type = {humanoid=resolvers.randartmax(5, 25),},}, } @@ -224,4 +225,5 @@ newEntity{ theme={physical=true}, name="slay insect", points = 1, rarity = 22, l } newEntity{ theme={physical=true}, name="slay spiderkin", points = 1, rarity = 22, level_range = {1, 50}, combat = { inc_damage_type = {spiderkin=resolvers.randartmax(5, 25),},}, -} \ No newline at end of file +} +--]] \ No newline at end of file diff --git a/game/modules/tome/data/general/objects/random-artifacts/ranged.lua b/game/modules/tome/data/general/objects/random-artifacts/ranged.lua index 62a93db1a903ae8593c0a2828e4545d13cc2f5e0..65a7421790fd8d3d2aa75eb16194e22970b312ad 100644 --- a/game/modules/tome/data/general/objects/random-artifacts/ranged.lua +++ b/game/modules/tome/data/general/objects/random-artifacts/ranged.lua @@ -96,27 +96,16 @@ newEntity{ theme={mental=true}, name="equilibrium on hit", points = 1, rarity = newEntity{ theme={mental=true}, name="max hate", points = 1, rarity = 16, level_range = {1, 50}, wielder = { max_hate = resolvers.randartmax(2, 10), }, } -newEntity{ theme={mental=true}, name="hate per kill", points = 1, rarity = 16, level_range = {1, 50}, - wielder = { hate_per_kill = resolvers.randartmax(1, 5), }, -} newEntity{ theme={mental=true}, name="hate on crit", points = 1, rarity = 16, level_range = {1, 50}, wielder = { hate_on_crit = resolvers.randartmax(1, 5), }, } newEntity{ theme={mental=true}, name="max psi", points = 1, rarity = 16, level_range = {1, 50}, wielder = { max_psi = resolvers.randartmax(10, 50), }, } -newEntity{ theme={mental=true}, name="psi per kill", points = 1, rarity = 16, level_range = {1, 50}, - wielder = { psi_per_kill = resolvers.randartmax(1, 5), }, -} newEntity{ theme={mental=true}, name="psi on hit", points = 1, rarity = 16, level_range = {1, 50}, wielder = { psi_regen_when_hit = resolvers.randartmax(.04, 2), }, } -newEntity{ theme={mental=true}, name="psi on crit", points = 1, rarity = 16, level_range = {1, 50}, - wielder = { psi_on_crit = resolvers.randartmax(1, 5), }, -} -newEntity{ theme={mental=true}, name="psi regen", points = 1, rarity = 16, level_range = {1, 50}, - wielder = { psi_regen = resolvers.randartmax(.1, 1), }, -} + ---------------------------------------------------------------- -- Misc ---------------------------------------------------------------- @@ -283,6 +272,7 @@ newEntity{ theme={defense=true, antimagic=true, temporal=true}, name="resist tem ---------------------------------------------------------------- -- Elemental Projection ---------------------------------------------------------------- +--[[[] newEntity{ theme={physical=true}, name="physical melee", points = 1, rarity = 18, level_range = {1, 50}, wielder = { ranged_project = {[DamageType.PHYSICAL] = resolvers.randartmax(2, 20), }, }, } @@ -319,6 +309,7 @@ newEntity{ theme={arcane=true, spell=true}, name="arcane melee", points = 2, rar newEntity{ theme={temporal=true}, name="temporal melee", points = 2, rarity = 24, level_range = {1, 50}, wielder = { ranged_project = {[DamageType.TEMPORAL] = resolvers.randartmax(2, 20), }, }, } +--]] ---------------------------------------------------------------- -- ranged damage Projection (rare) ---------------------------------------------------------------- @@ -432,45 +423,6 @@ newEntity{ theme={temporal=true}, name="temporal burst (crit)", points = 6, rari -- damage conversion ---------------------------------------------------------------- -- Removed due to essentially being downsides more often than not, double dipping defenses and creating massive log spam ----------------------------------------------------------------- --- Elemental Retribution ----------------------------------------------------------------- -newEntity{ theme={physical=true}, name="physical retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.PHYSICAL] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={mind=true, mental=true}, name="mind retribution", points = 1, rarity = 24, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.MIND] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={acid=true}, name="acid retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.ACID] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={lightning=true}, name="lightning retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.LIGHTNING] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={fire=true}, name="fire retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.FIRE] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={cold=true}, name="cold retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.COLD] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={light=true}, name="light retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.LIGHT] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={dark=true}, name="dark retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.DARKNESS] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={blight=true, spell=true}, name="blight retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.BLIGHT] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={nature=true}, name="nature retribution", points = 1, rarity = 18, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.NATURE] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={arcane=true, spell=true}, name="arcane retribution", points = 2, rarity = 24, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.ARCANE] = resolvers.randartmax(4, 20), }, }, -} -newEntity{ theme={temporal=true}, name="temporal retribution", points = 2, rarity = 24, level_range = {1, 50}, - wielder = { on_melee_hit = {[DamageType.TEMPORAL] = resolvers.randartmax(4, 20), }, }, -} ---------------------------------------------------------------- -- Damage % @@ -588,9 +540,6 @@ newEntity{ theme={misc=true, darkness=true}, name="infravision radius", points = newEntity{ theme={misc=true, light=true}, name="lite radius", points = 1, rarity = 14, level_range = {1, 50}, wielder = { lite = resolvers.randartmax(1, 3), }, } -newEntity{ theme={misc=true}, name="water breathing", points = 10, rarity = 15, level_range = {1, 50}, - wielder = { can_breath = {water=1}, }, -} newEntity{ theme={misc=true, mental=true}, name="telepathy", points = 60, rarity = 100, level_range = {1, 50}, wielder = { esp_all = 1 }, } diff --git a/game/modules/tome/data/general/objects/scrolls.lua b/game/modules/tome/data/general/objects/scrolls.lua index 768c3b35712bcc1f4e7dd37c22e250b2053477d3..4f10d702759220a69755597f66d873332ce082c3 100644 --- a/game/modules/tome/data/general/objects/scrolls.lua +++ b/game/modules/tome/data/general/objects/scrolls.lua @@ -120,6 +120,8 @@ newEntity{ ----------------------------------------------------------- -- Infusions ----------------------------------------------------------- +-- Pros: Instant cast, clears 2 average/lesser debuff types, which makes other cleanses also more consistent +-- Cons: Significantly less healing outputper cast than Regeneration newEntity{ base = "BASE_INFUSION", name = "healing infusion", level_range = {7, 50}, @@ -129,9 +131,9 @@ newEntity{ base = "BASE_INFUSION", inscription_kind = "heal", inscription_data = { - cooldown = resolvers.rngrange(12, 17), - heal = resolvers.mbonus_level(400, 40, function(e, v) return v * 0.06 end), - use_stat_mod = 2.7, + cooldown = resolvers.rngrange(10, 16), + heal = resolvers.mbonus_level(80, 20, function(e, v) return v * 0.06 end), + use_stat_mod = 2, }, inscription_talent = "INFUSION:_HEALING", } @@ -193,7 +195,7 @@ newEntity{ base = "BASE_INFUSION", inscription_data = { cooldown = resolvers.rngrange(13, 20), dur = resolvers.mbonus_level(5, 4, function(e, v) return v * 1 end), - speed = resolvers.mbonus_level(700, 500, function(e, v) return v * 0.001 end), + speed = resolvers.mbonus_level(500, 300, function(e, v) return v * 0.001 end), use_stat_mod = 3, }, inscription_talent = "INFUSION:_MOVEMENT", diff --git a/game/modules/tome/data/general/objects/world-artifacts-maj-eyal.lua b/game/modules/tome/data/general/objects/world-artifacts-maj-eyal.lua index 06ff8e6dba9f98d3ca15acfb7b665d0e76ff199b..fa250f37c5f3f5b61c94cb4255052ca5203d03c0 100644 --- a/game/modules/tome/data/general/objects/world-artifacts-maj-eyal.lua +++ b/game/modules/tome/data/general/objects/world-artifacts-maj-eyal.lua @@ -841,7 +841,7 @@ newEntity{ base = "BASE_MASSIVE_ARMOR", }, max_stamina = 60, combat_def = 15, - combat_armor = 20, + combat_armor = 30, stun_immune = 0.3, knockback_immune = 0.3, combat_mentalresist = 25, @@ -1107,7 +1107,7 @@ newEntity{ base = "BASE_MASSIVE_ARMOR", -- Thanks SageAcrin! metallic=false, wielder = { inc_stats = { [Stats.STAT_WIL] = 3, [Stats.STAT_DEX] = 3, [Stats.STAT_CON] = 3,}, - combat_armor = 10, + combat_armor = 12, combat_def = 4, fatigue = 14, resists = { diff --git a/game/modules/tome/data/general/objects/world-artifacts.lua b/game/modules/tome/data/general/objects/world-artifacts.lua index df9ea81d3aef7c409ae0cfc53254ebd2d7483a77..93bb836412bfa2f3acdebc991abe6f2bc5bfc76e 100644 --- a/game/modules/tome/data/general/objects/world-artifacts.lua +++ b/game/modules/tome/data/general/objects/world-artifacts.lua @@ -822,6 +822,8 @@ newEntity{ base = "BASE_GREATMAUL", pin_immune = 1, knockback_immune = 1, }, + max_power = 18, power_regen = 1, + use_talent = { id = Talents.T_FEARLESS_CLEAVE, level = 3, power = 18 }, } newEntity{ base = "BASE_MACE", @@ -1495,7 +1497,7 @@ newEntity{ base = "BASE_HEAVY_ARMOR", define_as = "SCALE_MAIL_KROLTAR", }, max_life=120, combat_def = 10, - combat_armor = 14, + combat_armor = 18, fatigue = 16, }, max_power = 80, power_regen = 1, @@ -1527,7 +1529,7 @@ newEntity{ base = "BASE_MASSIVE_ARMOR", [DamageType.DARKNESS] = 25, }, combat_def = 20, - combat_armor = 29, + combat_armor = 32, combat_armor_hardiness = 10, stun_immune = 0.4, knockback_immune = 0.4, @@ -1553,7 +1555,7 @@ newEntity{ base = "BASE_GREATSWORD", name = "Golden Three-Edged Sword 'The Truth'", image = "object/artifact/golden_3_edged_sword.png", unided_name = "three-edged sword", desc = [[The wise ones say that truth is a three-edged sword. And sometimes, the truth hurts.]], - level_range = {25, 32}, + level_range = {27, 36}, require = { stat = { str=18, wil=18, cun=18 }, }, color = colors.GOLD, encumber = 12, @@ -1563,10 +1565,10 @@ newEntity{ base = "BASE_GREATSWORD", moddable_tile = "special/golden_sword_right", moddable_tile_big = true, combat = { - dam = 40, - apr = 1, - physcrit = 7, - dammod = {str=1.2}, + dam = 49, + apr = 9, + physcrit = 9, + dammod = {str=1.29}, special_on_hit = {desc="9% chance to stun or confuse the target", fct=function(combat, who, target) if not rng.percent(9) then return end local eff = rng.table{"stun", "confusion"} @@ -1576,7 +1578,7 @@ newEntity{ base = "BASE_GREATSWORD", elseif eff == "confusion" then target:setEffect(target.EFF_CONFUSED, 3, {power=75}) end end}, - melee_project={[DamageType.LIGHT] = 40, [DamageType.DARKNESS] = 40}, + melee_project={[DamageType.LIGHT] = 49, [DamageType.DARKNESS] = 49}, }, } @@ -1901,7 +1903,7 @@ newEntity{ base = "BASE_ARROW", material_level = 4, require = { stat = { dex=24 }, }, combat = { - capacity = 18, + capacity = 25, tg_type = "beam", travel_speed = 3, dam = 34, @@ -1925,7 +1927,7 @@ newEntity{ base = "BASE_ARROW", material_level = 4, require = { stat = { dex=24 }, }, combat = { - capacity = 14, + capacity = 20, dam = 24, apr = 8, physcrit = 2, @@ -1934,7 +1936,8 @@ newEntity{ base = "BASE_ARROW", special_on_crit = {desc="dominate the target", fct=function(combat, who, target) if not target or target == self then return end if target:canBe("instakill") then - target:setEffect(target.EFF_DOMINATE_ENTHRALL, 3, {src=who, apply_power=who:combatMindpower()}) + local check = math.max(src:combatSpellpower(), src:combatMindpower(), src:combatAttack()) + target:setEffect(target.EFF_DOMINATE_ENTHRALL, 3, {src=who, apply_power=check()}) end end}, }, @@ -2631,7 +2634,7 @@ newEntity{ base = "BASE_SHOT", material_level = 4, require = { stat = { dex=28 }, }, combat = { - capacity = 18, + capacity = 25, dam = 32, apr = 15, physcrit = 10, @@ -2956,7 +2959,7 @@ newEntity{ base = "BASE_LONGSWORD", define_as="CORPUS", o.cut=nil o.combat.physcrit=6 o.wielder.combat_critical_power = 0 - game.logSeen(who, "Corpus bursts open, unleashing a horrific mass!") + game.logSeen(who, "Corpathus bursts open, unleashing a horrific mass!") local x, y = util.findFreeGrid(who.x, who.y, 5, true, {[engine.Map.ACTOR]=true}) local NPC = require "mod.class.NPC" local m = NPC.new{ @@ -3636,7 +3639,7 @@ newEntity{ base = "BASE_LEATHER_BOOT", --Thanks Grayswandir! use_power = { name = "phase door in range 6, radius 2", power = 24, use = function(self, who) local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=6, radius=2, requires_knowledge=false} - x, y = who:getTarget(tg) + local x, y = who:getTarget(tg) if not x then return nil end -- Target code does not restrict the target coordinates to the range, it lets the project function do it -- but we cant ... @@ -3737,19 +3740,19 @@ newEntity{ base = "BASE_ARROW", --Thanks Grayswandir! unided_name = "sting tipped arrows", desc = [[A vile poison drips from the tips of these arrows.]], color = colors.BLUE, - level_range = {10, 20}, + level_range = {15, 25}, rarity = 240, cost = 100, material_level = 2, require = { stat = { dex=18 }, }, combat = { capacity = 20, - dam = 20, + dam = 18, apr = 10, physcrit = 5, dammod = {dex=0.7, str=0.5}, ranged_project={ - [DamageType.CRIPPLING_POISON] = 15, + [DamageType.CRIPPLING_POISON] = 45, }, }, } @@ -4338,6 +4341,9 @@ newEntity{ base = "BASE_GREATSWORD", --Thanks Grayswandir! physcrit = 3, dammod = {str=1.2}, melee_project={[DamageType.ARCANE] = 10,}, + burst_on_crit = { + [DamageType.ARCANE_SILENCE] = 30, + }, }, wielder = { blind_fight = 1, @@ -5074,9 +5080,10 @@ newEntity{ base = "BASE_CLOAK", resists_cap = { [DamageType.LIGHT] = 10, }, resists = { [DamageType.LIGHT] = 20, [DamageType.DARKNESS] = 20, }, talents_types_mastery = { - ["celestial/light"] = 0.1, - ["celestial/sun"] = 0.1, - ["spell/phantasm"] = 0.1, + ["celestial/light"] = 0.2, + ["celestial/sun"] = 0.2, + ["spell/phantasm"] = 0.2, + ["celestial/radiance"] = 0.2, }, on_melee_hit={[DamageType.LIGHT_BLIND] = 30}, }, @@ -5337,8 +5344,8 @@ The heart which wishes that it be unseen.]], inc_damage = { all = 4 }, resists = {[DamageType.DARKNESS] = 10, [DamageType.MIND] = 10,}, talents_types_mastery = { - ["cursed/gloom"] = 0.1, - ["cursed/darkness"] = 0.1, + ["cursed/gloom"] = 0.2, + ["cursed/darkness"] = 0.2, }, on_melee_hit={[DamageType.MIND] = 30}, }, @@ -5521,7 +5528,7 @@ newEntity{ base = "BASE_GREATSWORD", apr = 22, physcrit = 10, dammod = {str=1.2}, - special_on_hit = {desc="25% chance to strike the target again", fct=function(combat, who, target) + special_on_hit = {desc="25% chance to strike the target again.", fct=function(combat, who, target) local o, item, inven_id = who:findInAllInventoriesBy("define_as", "DOUBLESWORD") if not o or not who:getInven(inven_id).worn then return end if o.running == true then return end @@ -5543,7 +5550,7 @@ newEntity{ base = "BASE_LONGSWORD", power_source = {technique=true, psionic=true}, define_as = "BUTCHER", name = "Butcher", unique=true, image="object/artifact/butcher.png", unided_name = "blood drenched shortsword", color=colors.CRIMSON, - desc = [["Be it corruption, madness or eccentric boredom, the halfling butcher by the name of Caleb once took to eating his kin instead of cattle. His spree was never ended and nobody knows where he disappeared to. Only the blade remained, stuck fast in bloodied block. Beneath, a carving said "This was fun, let's do it again some time."]], + desc = [[Be it corruption, madness or eccentric boredom, the halfling butcher by the name of Caleb once took to eating his kin instead of cattle. His spree was never ended and nobody knows where he disappeared to. Only the blade remained, stuck fast in bloodied block. Beneath, a carving said "This was fun, let's do it again some time."]], require = { stat = { str=40 }, }, level_range = {36, 48}, rarity = 250, @@ -6146,8 +6153,8 @@ newEntity{ base = "BASE_SHIELD", unique = true, name = "Shieldsmaiden", image = "object/artifact/shieldmaiden.png", unided_name = "icy shield", - desc = [["Myths tell of shieldsmaidens, a tribe of warrior women from the northern wastes of Maj'Eyal. Their martial prowess and beauty drew the fascination of swaths of admirers, yet all unrequited. So began the saying, that a shieldsmaiden's heart is as cold and unbreakable as her shield."]], - color = colors.BROWN, + desc = [[Myths tell of shieldsmaidens, a tribe of warrior women from the northern wastes of Maj'Eyal. Their martial prowess and beauty drew the fascination of swaths of admirers, yet all unrequited. So began the saying, that a shieldsmaiden's heart is as cold and unbreakable as her shield.]], + color = colors.BLUE, level_range = {36, 48}, rarity = 270, require = { stat = { str=28 }, }, @@ -6191,11 +6198,11 @@ newEntity{ base = "BASE_GREATMAUL", level_range = {1, 30}, rarity = 280, combat = { - dam = 10, - apr = 7, - physcrit = 4, + dam = 32, + apr = 6, + physcrit = 8, damrange=1.3, - dammod = {str=1.2}, + dammod = {str=1.2, mag=0.1}, }, max_power = 1, power_regen = 1, use_power = { name = "imbue the hammer with a gem of your choice", power = 0, @@ -6223,10 +6230,10 @@ newEntity{ base = "BASE_GREATMAUL", if gem then - -- The Blank Slate. This is a horrible method of changing modes, but it is the easiest to avoid fucking up. This doesn't do much better than just making a static table for every element but its much easier to work with. + -- The Blank Slate. self.Gem = nil self.Gem = gem - self.gemDesc = "Describe all the goddamn colors. NOW." + self.gemDesc = "something has gone wrong" self.sentient = false self.act = mod.class.Object.act @@ -6237,10 +6244,10 @@ newEntity{ base = "BASE_GREATMAUL", local scalingFactor = self.material_level self.combat = { - dam = (14 * scalingFactor), + dam = 8 + (12 * scalingFactor), apr = (3 * scalingFactor), - physcrit = (2.5 * scalingFactor), - dammod = {str=1.2}, + physcrit = 4 + (2 * scalingFactor), + dammod = {str=1.2, mag=0.1}, damrange = 1.3, } @@ -6369,7 +6376,7 @@ newEntity{ base = "BASE_GLOVES", define_as = "SET_GLOVE_DESTROYER", unique = true, name = "Fist of the Destroyer", color = colors.RED, image = "object/artifact/fist_of_the_destroyer.png", unided_name = "vile gauntlets", - desc = [[These terrible looking gloves glow with untold power.]], + desc = [[These fell looking gloves glow with untold power.]], level_range = {40, 50}, rarity = 300, cost = 800, @@ -6460,7 +6467,7 @@ newEntity{ base = "BASE_GREATMAUL", unique = true, name = "Obliterator", color = colors.UMBER, image = "object/artifact/obliterator.png", unided_name = "titanic maul", - desc = [[This massive hammer strikes with an impact that could shatter bones.]], + desc = [[This massive hammer strikes with deadly force. Bones crunch, splinter and grind to dust under its impact.]], level_range = {23, 30}, rarity = 270, require = { stat = { str=40 }, }, @@ -6509,6 +6516,272 @@ newEntity{ base = "BASE_HELM", blind_fight = 1, }, } + +newEntity{ base = "BASE_GREATSWORD", + power_source = {technique=true, arcane=true}, + name = "Champion's Will", unique=true, image = "object/artifact/champions_will.png", + unided_name = "blindingly bright sword", color=colors.YELLOW, + desc = [[This impressive looking sword features a golden engraving of a sun in its hilt. Etched into its blade are a series of runes claiming that only one who has mastered both their body and mind may wield this sword effectively.]], + require = { stat = { str=35 }, }, + level_range = {40, 50}, + rarity = 240, + cost = 280, + material_level = 5, + special_desc = function(self) return "Increases the damage of Sun Beam by 15%." end, + combat = { + dam = 67, + apr = 22, + physcrit = 12, + dammod = {str=1.15, con = 0.2}, + special_on_hit = {desc="releases a burst of light, dealing damage equal to your spellpower in a 3 radius cone.", on_kill=1, fct=function(combat, who, target) + who.turn_procs.champion_will = (who.turn_procs.champion_will or 0) + 1 + local tg = {type="cone", range=10, radius=3, force_target=target, selffire=false} + local grids = who:project(tg, target.x, target.y, engine.DamageType.LIGHT, who:combatSpellpower() / (who.turn_procs.champion_will)) + game.level.map:particleEmitter(target.x, target.y, tg.radius, "light_cone", {radius=tg.radius, tx=target.x-who.x, ty=target.y-who.y}) + who.turn_procs.champion_will = (who.turn_procs.champion_will or 0) + 1 + end}, + }, + wielder = { + inc_stats = { [Stats.STAT_STR] = 12, [Stats.STAT_MAG] = 6, [Stats.STAT_CON] = 7}, + talents_types_mastery = { + ["celestial/crusader"] = 0.2, + ["celestial/sun"] = 0.2, + ["celestial/radiance"] = 0.1, + }, + talent_cd_reduction= { + [Talents.T_ABSORPTION_STRIKE] = 1, + [Talents.T_SUN_BEAM] = 1, + [Talents.T_FLASH_OF_THE_BLADE] = 1, + }, + amplify_sun_beam = 15, + }, + max_power = 30, power_regen = 1, + use_power = { name = "strike with your weapon as 100% light damage, up to 4 spaces away, healing for 50% of the damage dealt", power = 30, + use = function(self, who) + local tg = {type="beam", range=4} + local x, y = who:getTarget(tg) + if not x or not y then return nil end + local _ _, x, y = who:canProject(tg, x, y) + who:attr("lifesteal", 50) + who:project(tg, x, y, function(px, py) + local target = game.level.map(px, py, engine.Map.ACTOR) + if not target then return end + who:attackTarget(target, engine.DamageType.LIGHT, 1, true) + end) + who:attr("lifesteal", -50) + game.level.map:particleEmitter(who.x, who.y, tg.radius, "light_beam", {tx=x-who.x, ty=y-who.y}) + game:playSoundNear(self, "talents/lightning") + return {id=true, used=true} + end + }, +} + +newEntity{ base = "BASE_MASSIVE_ARMOR", + power_source = {technique=true}, + unique = true, + name = "Tarrasca", image = "object/artifact/terrasca.png", + unided_name = "absurdly large armor", + desc = [[This massive suit of plate boasts an enormous bulk and overbearing weight. Said to belong to a nameless soldier who safeguarded a passage across the bridge to his village, in defiance to the cohorts of invading orcs. After days of assault failed to fell him, the orcs turned back. The man however, fell dead on the spot - from exhaustion. The armor had finally claimed his life.]], + color = colors.RED, + level_range = {30, 40}, + rarity = 320, + require = { stat = { str=52 }, }, + cost = 500, + material_level = 4, + special_desc = function(self) return ("When your effective movement speed (global speed times movement speed) is less than 100%%, reduces all incoming damage equal to the speed detriment, but never to less than 30%% of the original damage.\nCurrent Resistance: %d%%"):format(100*(1-(util.bound(game.player.global_speed * game.player.movement_speed, 0.3, 1)))) end, + wielder = { + inc_stats = { [Stats.STAT_CON] = 15, }, + combat_armor = 50, + combat_armor_hardiness = 15, + knockback_immune = 1, + combat_physresist = 45, + fatigue = 35, + speed_resist=1, + }, + max_power = 25, power_regen = 1, + use_power = { name = "slow all units within 5 spaces (including yourself) by 40%", power = 25, + use = function(self, who) + who:project({type="ball", range=0, radius=5}, who.x, who.y, function(px, py) + local target = game.level.map(px, py, engine.Map.ACTOR) + if not target then return end + target:setEffect(target.EFF_SLOW_MOVE, 3, {power=0.4, no_ct_effect=true, }) + end) + game.logSeen(who, "%s thinks things really need to slow down for a bit.", who.name:capitalize()) + return {id=true, used=true} + end + }, +} + +newEntity{ base = "BASE_LEATHER_CAP", + power_source = {unknown=true}, + unique = true, + name = "The Face of Fear", + unided_name = "bone mask", image = "object/artifact/the_face_of_fear.png", + level_range = {24, 32}, + color=colors.GREEN, + moddable_tile = "special/the_face_of_fear", + moddable_tile_big = true, + encumber = 2, + rarity = 200, + desc = [[This mask appears to be carved out of the skull of a creature that never should have existed, malformed and distorted. You shiver as you look upon it, and it's hollow eye sockets seem to stare back into you.]], + cost = 200, + material_level=3, + wielder = { + combat_def=8, + fear_immune = 0.6, + inc_stats = { [Stats.STAT_WIL] = 8, [Stats.STAT_CUN] = 6, }, + combat_mindpower = 16, + talents_types_mastery = { ["cursed/fears"] = 0.2,}, + }, + max_power = 45, power_regen = 1, + use_talent = { id = Talents.T_INSTILL_FEAR, level = 2, power = 18 }, +} + +newEntity{ base = "BASE_LEATHER_BOOT", + power_source = {arcane=true}, + unided_name = "flame coated sandals", + name = "Cinderfeet", unique=true, image = "object/artifact/cinderfeet.png", + desc = [[A cautionary tale tells of the ancient warlock by the name of Caim, who fancied himself daily walks through Goedalath, both to test himself and the harsh demonic wastes. He was careful to never bring anything back with him, lest it provide a beacon for the demons to find him. Unfortunately, over time, his sandals drenched in the soot and ashes of the fearscape and the fire followed his footsteps outside, drawing in the conclusion of his grim fate.]], + require = { stat = { dex=10 }, }, + level_range = {28, 38}, + material_level = 4, + rarity = 195, + cost = 40, + sentient=true, + oldx=0, + oldy=0, + wielder = { + lite = 2, + combat_armor = 5, + combat_def = 3, + fatigue = 6, + inc_damage = { + [DamageType.FIRE] = 18, + }, + resists = { + [DamageType.COLD] = 20, + }, + inc_stats = { [Stats.STAT_MAG] = 4, [Stats.STAT_CUN] = 4, }, + }, + special_desc = function(self) return "Trails fire behind you, dealing damage based on spellpower." end, + on_wear = function(self, who) + self.worn_by = who + self.oldx=who.x + self.oldy=who.y + end, + on_takeoff = function(self, who) + self.worn_by = nil + end, + act = function(self) + self:useEnergy() + self:regenPower() + + local who=self.worn_by --Make sure you can actually act! + if not self.worn_by then return end + if game.level and not game.level:hasEntity(self.worn_by) and not self.worn_by.player then self.worn_by = nil return end + if self.worn_by:attr("dead") then return end + if self.oldx ~= who.x or self.oldy ~= who.y then + local DamageType = require "engine.DamageType" + local duration = 6 + local radius = 0 + local dam = who:combatSpellpower() + -- Add a lasting map effect + game.level.map:addEffect(who, + who.x, who.y, duration, + DamageType.FIRE, dam, + radius, + 5, nil, + {type="inferno"}, + function(e) + e.radius = e.radius + return true + end, + false + ) + end + self.oldx=who.x + self.oldy=who.y + return + end +} + +newEntity{ base = "BASE_MASSIVE_ARMOR", + power_source = {arcane=true}, + unique = true, + name = "Cuirass of the Dark Lord", image = "object/artifact/dg_casual_outfit.png", + unided_name = "black, spiked armor", + desc = [[Worn by a villain long forgotten, this armor was powered by the blood of thousands of innocents. Decrepit and old, the dark lord died in solitude, his dominion crumbled, his subjects gone. Only the plate remained, dying to finally taste fresh blood again.]], + color = colors.RED, + level_range = {40, 50}, + rarity = 320, + require = { stat = { str=52 }, }, + cost = 500, + material_level = 5, + sentient=true, + blood_charge=0, + blood_dur=0, + wielder = { + inc_stats = { [Stats.STAT_STR] = 10, [Stats.STAT_CON] = 10, }, + combat_armor = 40, + combat_dam=10, + combat_physresist = 15, + fatigue = 25, + life_regen=0, + on_melee_hit={[DamageType.PHYSICAL] = 30}, + resists={[DamageType.PHYSICAL] = 20}, + }, + max_power = 25, power_regen = 1, + use_power = { name = "drain blood from all units within 5 spaces, causing them to bleed for 120 physical damage over 4 turns. For every unit (up to 10) drained, the armor's stats increase, but decrease over 10 turns until back to normal", power = 25, + use = function(self, who) + who:project({type="ball", range=0, radius=5, selffire=false}, who.x, who.y, function(px, py) + local target = game.level.map(px, py, engine.Map.ACTOR) + if not target then return end + self.blood_charge=self.blood_charge + 1 + target:setEffect(target.EFF_CUT, 4, {power=30, no_ct_effect=true, src = who}) + end) + if self.blood_charge > 10 then self.blood_charge = 10 end + self.blood_dur = 10 + game.logSeen(who, "%s revels in blood!", self.name:capitalize()) + return {id=true, used=true} + end + }, + on_wear = function(self, who) + self.worn_by = who + end, + on_takeoff = function(self, who) + self.worn_by = nil + end, + act = function(self) + self:useEnergy() + self:regenPower() + + local who=self.worn_by --Make sure you can actually act! + if not self.worn_by then return end + if game.level and not game.level:hasEntity(self.worn_by) and not self.worn_by.player then self.worn_by = nil return end + local boost = self.blood_charge + local dur = self.blood_dur + local storepower=self.power + who:onTakeoff(self, true) + + self.wielder = { + inc_stats = { [Stats.STAT_STR] = math.ceil(10 + boost * dur/5), [Stats.STAT_CON] = math.ceil(10 + boost * dur/5), }, + combat_armor = math.ceil(30 + boost * dur * 0.4), + combat_dam = math.ceil(10 + boost/5 * dur), + combat_physresist = math.ceil(15 + boost/5 * dur), + fatigue = math.ceil(25 - boost/5 * dur), + life_regen= math.ceil(boost/2 * dur), + on_melee_hit={[DamageType.PHYSICAL] = math.ceil(30 + boost * dur * 0.8)}, + resists={[DamageType.PHYSICAL] = math.ceil(20 + boost/5 * dur)}, + } + who:onWear(self, true) + self.power = storepower + if self.blood_dur > 0 then + self.blood_dur = self.blood_dur - 1 + end + return + end +} + --[=[ newEntity{ unique = true, diff --git a/game/modules/tome/data/gfx/particles/light_cone.lua b/game/modules/tome/data/gfx/particles/light_cone.lua new file mode 100644 index 0000000000000000000000000000000000000000..30176ce7c4e266ed3ace8b17b312aca48e04471f --- /dev/null +++ b/game/modules/tome/data/gfx/particles/light_cone.lua @@ -0,0 +1,62 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 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 nb = 12 +local dir = 0 +local spread = spread or 55/2 +local radius = radius or 6 + +dir = math.deg(math.atan2(ty, tx)) + +return { generator = function() + local sradius = (radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2 + local ad = rng.float(dir - spread, dir + spread) + local a = math.rad(ad) + local r = 0 + local x = r * math.cos(a) + local y = r * math.sin(a) + local static = rng.percent(40) + local vel = sradius * ((24 - nb * 1.4) / 24) / 12 + + return { + trail = 1, + life = 12, + size = 12 - (12 - nb) * 0.7, sizev = 0, sizea = 0, + + x = x, xv = 0, xa = 0, + y = y, yv = 0, ya = 0, + dir = a, dirv = 0, dira = 0, + vel = rng.float(vel * 0.6, vel * 1.2), velv = 0, vela = 0, + + r = rng.range(215, 255)/255, rv = 0, ra = 0, + g = rng.range(200, 240)/255, gv = 0, ga = 0, + b = rng.range(0, 40)/255, bv = 0, ba = 0, + a = 1, av = 0, aa = 0, + } +end, }, +function(self) + if nb > 0 then + local i = math.min(nb, 6) + i = (i * i) * radius + self.ps:emit(i) + nb = nb - 1 + end +end, +30*radius*7*12, +"particle_cloud" diff --git a/game/modules/tome/data/gfx/shockbolt/object/artifact/champions_will.png b/game/modules/tome/data/gfx/shockbolt/object/artifact/champions_will.png new file mode 100644 index 0000000000000000000000000000000000000000..3bee1ee44e5ebf9d98c9be84384936562984e52a Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/object/artifact/champions_will.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/object/artifact/cinderfeet.png b/game/modules/tome/data/gfx/shockbolt/object/artifact/cinderfeet.png new file mode 100644 index 0000000000000000000000000000000000000000..e5b3e783fc53649f1a443ea6d54b7fb805dc3381 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/object/artifact/cinderfeet.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/object/artifact/dg_casual_outfit.png b/game/modules/tome/data/gfx/shockbolt/object/artifact/dg_casual_outfit.png new file mode 100644 index 0000000000000000000000000000000000000000..5a48d67af02a151235965bf8818d0537857b0c3f Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/object/artifact/dg_casual_outfit.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/object/artifact/terrasca.png b/game/modules/tome/data/gfx/shockbolt/object/artifact/terrasca.png new file mode 100644 index 0000000000000000000000000000000000000000..36b7ada8019b3a667f6ee86c90d83cf38edf4961 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/object/artifact/terrasca.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/object/artifact/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/object/artifact/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..66b1d7b4f3f800316dc32944b190e8e6d25e3a5b Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/object/artifact/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/dwarf_female/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/dwarf_female/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..bb69c1d5585d6c929506e5776260709d8b68addd Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/dwarf_female/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/dwarf_male/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/dwarf_male/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..bb69c1d5585d6c929506e5776260709d8b68addd Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/dwarf_male/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/elf_female/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/elf_female/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..64d21ff00d09306a7df82201b6300c0e907960c7 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/elf_female/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/elf_male/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/elf_male/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..49a27d309613f74ab5b99c0103e83d4ad285c40e Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/elf_male/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/ghoul/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/ghoul/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..b59fa3003d00fe7daf07d02a39b5e0a583107497 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/ghoul/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/halfling_female/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/halfling_female/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..421744c9e3ae89478f78d3bf946c08e7a82add4a Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/halfling_female/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/halfling_male/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/halfling_male/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..421744c9e3ae89478f78d3bf946c08e7a82add4a Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/halfling_male/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/human_female/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/human_female/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..64d21ff00d09306a7df82201b6300c0e907960c7 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/human_female/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/human_male/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/human_male/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..a756de43084ef7f283890e88de4ab4fb31a0a64c Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/human_male/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/orc/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/orc/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..8836deedbfb28e4571b2f14fe68290ffffac01c4 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/orc/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/runic_golem/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/runic_golem/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..599b6fd3f4f02d7bc1565157b5524bfb0147c233 Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/runic_golem/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/skeleton/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/skeleton/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..a756de43084ef7f283890e88de4ab4fb31a0a64c Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/skeleton/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/gfx/shockbolt/player/yeek/special/the_face_of_fear.png b/game/modules/tome/data/gfx/shockbolt/player/yeek/special/the_face_of_fear.png new file mode 100644 index 0000000000000000000000000000000000000000..b66455cd6e06936db86bc4686ac4e76e960c582d Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/player/yeek/special/the_face_of_fear.png differ diff --git a/game/modules/tome/data/lore/misc.lua b/game/modules/tome/data/lore/misc.lua index a361614204e4b4e2a55e9e5d2fe4b91b58014734..92964d5b725e765e4c259c6c540b9247eff2f602 100644 --- a/game/modules/tome/data/lore/misc.lua +++ b/game/modules/tome/data/lore/misc.lua @@ -635,6 +635,25 @@ newLore{ Eyal is a torn world, and the forces of nature can react strongly to the arcane energies that seek to manipulate them. Some items and areas are imbued with anti-magic, a natural energy that disrupts magical abilities and effects. There are even those who have learned to harness anti-magic into their own wild abilities, and who use them to hunt down and destroy those who practise magic. So beware, caster! It is a hostile world ye wander in.]], } +newLore{ + id = "kestin-highfin-adventuring-notes", + category = "highfin", + name = "On Adventuring", + lore = [[ I must say, as time grows, I feel so do I grow more and more inclined to distance myself from the calling of an 'adventurer', like so many you can find roaming the countryside. I feel like the myth of a wandering hero has blinded too many with promise of easy fame and riches, with no eye for the other kind of fortune. + +Hear me out on this. + +Nowadays most don't really recognize how fascinating the world we live in truly is. It is vast, more than you can imagine. I can safely promise, any wild thought you can muster up, dear reader, will not come close to the truth. Such is the breadth of wonders, I would probably dismiss most of what I have seen as myth, be I not there myself. And even then sometimes, I had to wonder whether I could trust my eyes. + +Perhaps I'm being too vague, or maybe these promises leave much to be desired. After all, adventuring is not all fun and exotics, it is before all danger and a constant threat of death, or worse. So then if you wish me to be more concrete, think of derelict, crumbling crypts, cults and demons, hungry forests full of monsters and forces beyond time and place. True, there is overwhelming awe, thrill even, but the reason that so little detail reaches you, is because so little live to tell. + +What does reach us then, are not people, but objects. Artifacts of great power, legacy of the past. Surely, any drunkard might like to tell tales after a pint or two, but a magical sword is a proof of its own and it keeps quiet of what it has seen. So, a great hero is usually easy to recognize, being practically a walking history book. Clad in half the age of important events which he probably has no idea about. + +It is important to remember, that every artifact has a meaning, beings of great power and importance behind them. Stories, that now slowly wane into nothing. This is why it is not artifacts that make an adventurer. It is his great deeds, the will to dare where nobody did before. It is not important if you get known in the process or not, after all, if you were truly great, maybe you will leave behind a legacy of your own. + +-#{italic}#Kestin Highfin#{normal}#]] +} + -------------------------------------------------------------- -- Misc bosses diff --git a/game/modules/tome/data/talents/celestial/crusader.lua b/game/modules/tome/data/talents/celestial/crusader.lua index 833355d96a6302b31fbd621a1c2cff2dfaf62381..08dcb17ddf68b09eba74099c419b5c0ab8ed250c 100644 --- a/game/modules/tome/data/talents/celestial/crusader.lua +++ b/game/modules/tome/data/talents/celestial/crusader.lua @@ -57,7 +57,7 @@ newTalent{ info = function(self, t) local damage = t.getDamage(self, t) return ([[You strike your foe with your two handed weapon, dealing %d%% weapon damage. - If the attack hits all foes in radius 2 will have their light resistance reduced by %d%% and their damage reduced by %d%% for 5 turns.]]): + If the attack hits, all foes in radius 2 will have their light resistance reduced by %d%% and their damage reduced by %d%% for 5 turns.]]): format(100 * damage, t.getWeakness(self, t), t.getNumb(self, t)) end, } @@ -176,7 +176,7 @@ newTalent{ return ([[Infuse your two handed weapon with light while spinning around. All creatures in radius one take %d%% weapon damage. In addition while spinning your weapon shines so much it deals %d%% light weapon damage to all foes in radius 2. - At level 4 your mystical, manly display of spinning around creates a manly shield that blocks all damage for 1 turn.]]): + At level 4 your spinning blade creates a shield that blocks all damage for 1 turn.]]): format(t.get1Damage(self, t) * 100, t.get2Damage(self, t) * 100) end, } diff --git a/game/modules/tome/data/talents/celestial/light.lua b/game/modules/tome/data/talents/celestial/light.lua index 36d3169f59999e5b90b1072e448a822babc22ed2..b13d54772a16fc96443a9929d59d7afcf3a24975 100644 --- a/game/modules/tome/data/talents/celestial/light.lua +++ b/game/modules/tome/data/talents/celestial/light.lua @@ -41,7 +41,7 @@ newTalent{ end, info = function(self, t) local heal = t.getHeal(self, t) - return ([[An invigorating ray of Sunlight shines on you, healing your body for %d life. + return ([[An invigorating ray of Sunlight shines upon you, healing your body for %d life. The amount healed will increase with your Spellpower.]]): format(heal) end, @@ -82,7 +82,7 @@ newTalent{ local radius = self:getTalentRadius(t) local heal = t.getHeal(self, t) local duration = t.getDuration(self, t) - return ([[A magical zone of Sunlight appears around you, healing and shielding all within radius %d for %0.2f per turn and increasing healing effects on everyone within by %d%%. The effect lasts for %d turns. + return ([[A magical zone of Sunlight appears around you, healing and shielding all within a radius of %d for %0.2f per turn and increasing healing effects on everyone within by %d%%. The effect lasts for %d turns. It also lights up the affected zone. The amount healed will increase with the Magic stat]]): format(radius, heal, heal / 2, duration) diff --git a/game/modules/tome/data/talents/celestial/radiance.lua b/game/modules/tome/data/talents/celestial/radiance.lua index 45d684c6f73dffa808bcf3bc92417fa543368a11..261e55cdfbeec8efdc9ff995f4aa82479a0e209c 100644 --- a/game/modules/tome/data/talents/celestial/radiance.lua +++ b/game/modules/tome/data/talents/celestial/radiance.lua @@ -165,7 +165,7 @@ newTalent{ return true end, info = function(self, t) - return ([[Fire a glowing orb of light at each enemy within your Radiance. Each orb will slowly follow its target until it connects dealing %d light damage to anything else it contacts along the way. When the target is reached the orb will explode dealing %d light damage and healing you for 50%% of the damage dealt. This powerful ability will dim your Radiance reducing its radius to 1 for 5 turns.]]): + return ([[Fire a glowing orb of light at each enemy within your Radiance. Each orb will slowly follow its target until it connects dealing %d light damage to anything else it contacts along the way. When the target is reached the orb will explode dealing %d light damage and healing you for 50%% of the damage dealt. This powerful ability will dim your Radiance, reducing its radius to 1 for 5 turns.]]): format(t.getMoveDamage(self, t), t.getExplosionDamage(self, t)) end, } diff --git a/game/modules/tome/data/talents/celestial/sun.lua b/game/modules/tome/data/talents/celestial/sun.lua index d7e45acee1571716d738eeb8e8f1f1993fb52779..74892f4e1b0e5265ff7807e8cc3cca5350519094 100644 --- a/game/modules/tome/data/talents/celestial/sun.lua +++ b/game/modules/tome/data/talents/celestial/sun.lua @@ -78,7 +78,7 @@ newTalent{ type = {"celestial/sun", 2}, require = divi_req2, points = 5, - cooldown = 20, + cooldown = 15, -- 20 was accounting for it buffing itself fixed_cooldown = true, positive = -15, tactical = { BUFF = 2 }, @@ -87,7 +87,7 @@ newTalent{ requires_target = true, range = 10, getCap = function(self, t) return math.max(50, 100 - self:getTalentLevelRaw(t) * 10) end, - getHaste = function(self, t) return math.min(0.9, self:combatTalentSpellDamage(t, 0.2, 0.7)) end, + getHaste = function(self, t) return math.min(0.5, self:combatTalentSpellDamage(t, 0.1, 0.4)) end, getCD = function(self, t) return math.min(0.5, self:combatTalentSpellDamage(t, 5, 450) / 1000) end, action = function(self, t) self:setEffect(self.EFF_SUNCLOAK, 6, {cap=t.getCap(self, t), haste=t.getHaste(self, t), cd=t.getCD(self, t)}) @@ -133,7 +133,7 @@ newTalent{ local chance = t.getProcChance(self, t) return ([[Infuse yourself with the raging fury of the Sun, increasing your physical and spell critical chance by %d%%. Each time you crit with a physical attack or a spell you have %d%% chance to gain Sun's Vengeance for 2 turns. - While affected your Sun Beam will take no turn to use and deal 25%% more damage. + While affected by Sun's Vengeance your Sun Beam will take no turn to use and deal 25%% more damage. If Sun Beam was on cooldown, the remaining turns are reduced by one instead. This effect can only happen once per turn.]]): format(crit, chance) diff --git a/game/modules/tome/data/talents/celestial/twilight.lua b/game/modules/tome/data/talents/celestial/twilight.lua index 4fa2205251ac82b87be75bacc05f6ff43257dadb..d8b788cec62dc6cb694637e91fd239d3b226ca27 100644 --- a/game/modules/tome/data/talents/celestial/twilight.lua +++ b/game/modules/tome/data/talents/celestial/twilight.lua @@ -216,7 +216,7 @@ newTalent{ return end - allowed = 2 + math.ceil(self:getTalentLevelRaw(t) / 2 ) + local allowed = 2 + math.ceil(self:getTalentLevelRaw(t) / 2 ) if target.rank >= 3.5 or -- No boss target:reactionToward(self) >= 0 or -- No friends diff --git a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua index a95babc6f97c490f3484688ebb586b86a9271471..3fbf1fb201d71259fd72bfe7d4379547e186ffea 100644 --- a/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua +++ b/game/modules/tome/data/talents/chronomancy/spacetime-weaving.lua @@ -184,7 +184,7 @@ newTalent{ end if #poss == 0 then game.logPlayer(self, "No exit location could be found.") return false end local pos = poss[rng.range(1, #poss)] - exit_x, exit_y = pos[1], pos[2] + local exit_x, exit_y = pos[1], pos[2] print("[[wormhole]] entrance ", entrance_x, " :: ", entrance_y) print("[[wormhole]] exit ", exit_x, " :: ", exit_y) diff --git a/game/modules/tome/data/talents/chronomancy/timeline-threading.lua b/game/modules/tome/data/talents/chronomancy/timeline-threading.lua index 932f2aeb30cf4f17d2bb0f5ebccf93aad95afad4..c31541d716163bf433ff6d7016f1e79fd4a0023b 100644 --- a/game/modules/tome/data/talents/chronomancy/timeline-threading.lua +++ b/game/modules/tome/data/talents/chronomancy/timeline-threading.lua @@ -108,7 +108,7 @@ newTalent{ return end - allowed = t.getSize(self, t) + local allowed = t.getSize(self, t) if target.rank >= 3.5 or -- No boss target:reactionToward(self) >= 0 or -- No friends diff --git a/game/modules/tome/data/talents/corruptions/plague.lua b/game/modules/tome/data/talents/corruptions/plague.lua index e943f6934a5fa0d10920fcc1ef9bfe1a77e9789b..80af80bbb786ced8b308f5403f045b82d07e8efd 100644 --- a/game/modules/tome/data/talents/corruptions/plague.lua +++ b/game/modules/tome/data/talents/corruptions/plague.lua @@ -28,7 +28,7 @@ newTalent{ tactical = { ATTACK = {BLIGHT = 2} }, requires_target = true, no_energy = true, - range = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9)) end, + range = function(self, t) return 5 end, -- Instant cast should not do thousands of damage at long range. This is still too powerful, though action = function(self, t) local tg = {type="bolt", range=self:getTalentRange(t)} local x, y = self:getTarget(tg) @@ -52,7 +52,7 @@ newTalent{ disease = {self.EFF_ROTTING_DISEASE, "con"} end - target:setEffect(disease[1], 6, {src=self, dam=self:spellCrit(7 + self:combatTalentSpellDamage(t, 6, 65)), [disease[2]]=self:combatTalentSpellDamage(t, 5, 35), apply_power=self:combatSpellpower()}) + target:setEffect(disease[1], 6, {src=self, dam=self:spellCrit(7 + self:combatTalentSpellDamage(t, 6, 45)), [disease[2]]=self:combatTalentSpellDamage(t, 5, 35), apply_power=self:combatSpellpower()}) else game.logSeen(target, "%s resists the disease!", target.name:capitalize()) end @@ -77,7 +77,7 @@ newTalent{ points = 5, vim = 18, cooldown = 9, - range = 7, + range = 8, radius = function(self, t) return math.floor(self:combatTalentScale(t, 1.5, 3.5)) end, tactical = { ATTACK = function(self, t, target) -- Count the number of diseases on the target @@ -155,7 +155,7 @@ newTalent{ points = 5, vim = 20, cooldown = 15, - range = 6, + range = 8, tactical = { DISABLE = function(self, t, target) -- Make sure the target has a disease for eff_id, p in pairs(target.tmp) do @@ -224,7 +224,7 @@ newTalent{ points = 5, vim = 20, cooldown = 13, - range = 6, + range = 8, radius = 2, tactical = { ATTACK = {BLIGHT = 2} }, requires_target = true, diff --git a/game/modules/tome/data/talents/cunning/called-shots.lua b/game/modules/tome/data/talents/cunning/called-shots.lua index 443adc1f919a70976e65836c77c773071387d3c7..dc985affe62badd8a37e13ec47d54115f5e55c25 100644 --- a/game/modules/tome/data/talents/cunning/called-shots.lua +++ b/game/modules/tome/data/talents/cunning/called-shots.lua @@ -30,11 +30,11 @@ local sniper_bonuses = function(self, calc_all) local level = self:getTalentLevel(t) if level > 0 or calc_all then - bonuses.crit_chance = level * 5 - bonuses.crit_power = level * 0.1 + bonuses.crit_chance = math.min(25, self:combatTalentScale(t, 1, 10)) + bonuses.crit_power = math.min(.5, self:combatTalentScale(t, 0.1, 0.2)) end if level >= 5 or calc_all then - local resists_pen = math.min(50, level * 3 + self:getDex(30, true) + self:getCun(30, true)) + local resists_pen = math.min(30, self:combatStatScale("cun", 1, 20)) bonuses.resists_pen = {[DamageType.PHYSICAL] = resists_pen} end return bonuses @@ -49,14 +49,16 @@ end -- The action for each of the shots. local fire_shot = function(self, t) - local targets = self:archeryAcquireTargets(nil, table.clone(t.archery_target_parameters)) + local tg = {type = "hit"} + + local targets = self:archeryAcquireTargets(tg, table.clone(t.archery_target_parameters)) if not targets then return end local bonuses = sniper_bonuses(self) local params = {mult = t.damage_multiplier(self, t)} if bonuses.crit_chance then params.crit_chance = bonuses.crit_chance end if bonuses.crit_power then params.crit_power = bonuses.crit_power end if bonuses.resists_pen then params.resists_pen = bonuses.resists_pen end - self:archeryShoot(targets, t, nil, params) + self:archeryShoot(targets, t, {type = "hit", speed = 200}, params) -- Projectile speed because using "hit" with slow projectiles is infuriating return true end @@ -115,7 +117,8 @@ newTalent { end, action = fire_shot, info = function(self, t) - return ([[Nail your opponent in the knee for %d%% weapon damage, knocking them down (%d turn pin) and slowing their movement by %d%% for %d turns afterwards.]]) + return ([[Nail your opponent in the knee for %d%% weapon damage, knocking them down (%d turn pin) and slowing their movement by %d%% for %d turns afterwards. + This shot will pass through enemies to reach its target.]]) :format(t.damage_multiplier(self, t) * 100, t.pin_duration(self, t), t.slow_power(self, t) * 100, @@ -123,42 +126,68 @@ newTalent { end, } +-- This serves two primary roles +-- 1. Core high damage shot +-- 2. Sniping off-targets like casters in any situation in potentially one shot newTalent { short_name = "SKIRMISHER_THROAT_SMASHER", - name = "Throat Smasher", + name = "Kill Shot", type = {"cunning/called-shots", 2}, require = techs_cun_req2, points = 5, no_energy = "fake", random_ego = "attack", - tactical = {ATTACK = {weapon = 2}, DISABLE = {silence = 2}}, - stamina = 10, + tactical = {ATTACK = {weapon = 2}}, + stamina = 35, cooldown = shot_cooldown, + no_npc_use = true, -- Numbers overtuned to make sure the class has a satisfying high damage shot requires_target = true, range = archery_range, on_pre_use = function(self, t, silent) return sling_equipped(self, silent) end, - silence_duration = function(self, t) - return math.floor(3 + self:getTalentLevel(t) * 0.5) + getDistanceBonus = function(self, t) + return 0.3 + end, + getDamage = function(self, t) + return 1 end, damage_multiplier = function(self, t) - return self:combatTalentWeaponDamage(t, 1.5, 1.9) + return self:combatTalentWeaponDamage(t, 0.3, 1.5) end, archery_onreach = pen_on, archery_onmiss = pen_off, archery_onhit = function(self, t, target, x, y) - if target:canBe("silence") then - target:setEffect(target.EFF_SILENCED, t.silence_duration(self, t), {apply_power = self:combatAttack()}) - else - game.logSeen(target, "%s resists the throat smasher!", target.name:capitalize()) - end pen_off(self, t, target, x, y) end, archery_target_parameters = {one_shot = true}, - action = fire_shot, + action = function(self, t) + local tg = {type = "hit"} + + local targets = self:archeryAcquireTargets(tg, table.clone(t.archery_target_parameters)) + if not targets then return end + + -- THIS IS WHY I HATE YOUR CODE STRUCTURE GRAYSWANDIR + local bonuses = sniper_bonuses(self) + local dist = core.fov.distance(self.x, self.y, targets[1].x, targets[1].y) + local damage = t.damage_multiplier(self, t) + ( t.getDistanceBonus(self, t) * dist ) + + local target = game.level.map(targets[1].x, targets[1].y, engine.Map.ACTOR) + if not target then return end + game.logSeen(self, "#DARK_ORCHID#%s snipes %s for %d%% weapon damage (+%d%% range bonus)!#LAST#", self.name:capitalize(), target.name:capitalize(), damage*100, t.getDistanceBonus(self, t) * dist * 100 ) + + + local params = {mult = damage} + if bonuses.crit_chance then params.crit_chance = bonuses.crit_chance end + if bonuses.crit_power then params.crit_power = bonuses.crit_power end + if bonuses.resists_pen then params.resists_pen = bonuses.resists_pen end + self:archeryShoot(targets, t, {type = "hit", speed = 200}, params) + + return true + end, info = function(self, t) - return ([[Something in your throat? Silences an enemy for %d turns and does %d%% damage.]]) - :format(t.silence_duration(self, t), - t.damage_multiplier(self, t) * 100) + return ([[Snipe a target at long range dealing %d%% damage increased by %d%% for each tile between you and the target. + This shot will pass through enemies to reach its target.]]) + :format(t.damage_multiplier(self, t) * 100, t.getDistanceBonus(self, t)*100 + ) end, } @@ -173,10 +202,10 @@ newTalent { stamina = 15, cooldown = shot_cooldown, requires_target = true, - range = argery_range, + range = archery_range, on_pre_use = function(self, t, silent) return sling_equipped(self, silent) end, damage_multiplier = function(self, t) - return self:combatTalentWeaponDamage(t, 0.5, 0.75) + return self:combatTalentWeaponDamage(t, 0.3, 0.75) end, archery_onreach = pen_on, archery_onmiss = pen_off, @@ -191,7 +220,8 @@ newTalent { archery_target_parameters = {limit_shots = 1, multishots = 3}, action = fire_shot, info = function(self, t) - return ([[Apply directly to the forehead! Shoot 3 quick sling bullets for %d%% damage in succession into your opponent’s brow. Each bullet will increase the target's stun duration by 1.]]) + return ([[Apply directly to the forehead! Shoot 3 quick sling bullets for %d%% damage in succession into your opponent’s brow. Each bullet will try to stun or increase the target's stun duration by 1. + This shot will pass through enemies to reach its target.]]) :format(t.damage_multiplier(self, t) * 100) end, } @@ -205,7 +235,7 @@ newTalent { no_energy = "fake", mode = "passive", info = function(self, t) - bonuses = sniper_bonuses(self, true) + local bonuses = sniper_bonuses(self, true) return ([[Your mastery of called shots is unparalleled. Gain %d%% bonus critical chance and %d%% critical damage on your Called Shots. At rank 3 lowers the cooldowns of your Called Shots by 2 each. At rank 5 gain %d%% physical resist piercing with all Called Shot attacks.]]) :format(bonuses.crit_chance, bonuses.crit_power * 100, diff --git a/game/modules/tome/data/talents/cunning/stealth.lua b/game/modules/tome/data/talents/cunning/stealth.lua index 03f7c6dfec9b443260c94cbdb62fc727d32241dc..ff93639cd76aa15e2606cd80db8c085d0bd7a7c5 100644 --- a/game/modules/tome/data/talents/cunning/stealth.lua +++ b/game/modules/tome/data/talents/cunning/stealth.lua @@ -100,11 +100,23 @@ newTalent{ require = cuns_req2, mode = "passive", points = 5, + checkWeapon = function(self, t) + if self:hasArcheryWeapon() or not self:hasDualWeapon() then + print("[SHADOWSTRIKE]", self.name or "", "rejected for weapon type") + + return false + else + return true + end + end, + getMultiplier = function(self, t) return self:combatTalentScale(t, 1/7, 5/7) end, info = function(self, t) local multiplier = t.getMultiplier(self, t) - return ([[When striking from stealth, hits are automatically criticals if the target does not notice you just before you land the blow. - Shadowstrikes do +%.02f%% damage versus a normal critical hit.]]): + return ([[When striking from stealth, melee hits are automatically criticals if the target does not notice you just before you land the blow. + Shadowstrikes do +%.02f%% damage versus a normal critical hit. + These bonuses are guaranteed for spell and mind crits even if the target can see you before it hits. + You must be wielding 2 melee weapons for this talent to trigger.]]): format(multiplier * 100) end, } diff --git a/game/modules/tome/data/talents/cunning/tactical.lua b/game/modules/tome/data/talents/cunning/tactical.lua index 942b0d697310dfc6aefb7c622c583b996af94015..1a985f3e33270808d0033f51b551505a921a2bbf 100644 --- a/game/modules/tome/data/talents/cunning/tactical.lua +++ b/game/modules/tome/data/talents/cunning/tactical.lua @@ -50,7 +50,7 @@ newTalent{ else defense = t.getMaximum(self, t) end - + print("[Tactical Expert] returning ", defense) return defense end, info = function(self, t) diff --git a/game/modules/tome/data/talents/cursed/endless-hunt.lua b/game/modules/tome/data/talents/cursed/endless-hunt.lua index b2ded74824324502c5a086cf47072ae0b39dfe44..b9e62c77b27165a068c5f6e859037eab99b60df0 100644 --- a/game/modules/tome/data/talents/cursed/endless-hunt.lua +++ b/game/modules/tome/data/talents/cursed/endless-hunt.lua @@ -41,7 +41,8 @@ newTalent{ getDuration = function(self, t) return 40 end, - getHitHateChange = function(self, t, bonus)Patbonus = math.min(bonus, 3) + getHitHateChange = function(self, t, bonus) + bonus = math.min(bonus, 3) return 0.5 * bonus end, getAttackChange = function(self, t, bonus) diff --git a/game/modules/tome/data/talents/cursed/gloom.lua b/game/modules/tome/data/talents/cursed/gloom.lua index 68cd723749dfcb16de52324ba84a57901117fdcb..ca1913455f86c8e6e2a1a8dddb75b643f5a75251 100644 --- a/game/modules/tome/data/talents/cursed/gloom.lua +++ b/game/modules/tome/data/talents/cursed/gloom.lua @@ -87,19 +87,16 @@ newTalent{ -- confusion if target:canBe("confusion") and not target:hasEffect(target.EFF_GLOOM_CONFUSED) then target:setEffect(target.EFF_GLOOM_CONFUSED, 2, {power=70}) - hit = true end elseif effect == 2 then -- stun if target:canBe("stun") and not target:hasEffect(target.EFF_GLOOM_STUNNED) then target:setEffect(target.EFF_GLOOM_STUNNED, 2, {}) - hit = true end elseif effect == 3 then -- slow if target:canBe("slow") and not target:hasEffect(target.EFF_GLOOM_SLOW) then target:setEffect(target.EFF_GLOOM_SLOW, 2, {power=0.3}) - hit = true end end end @@ -111,7 +108,6 @@ newTalent{ local incDamageChange = tWeakness.getIncDamageChange(self, tWeakness) local hateBonus = tWeakness.getHateBonus(self, tWeakness) target:setEffect(target.EFF_GLOOM_WEAKNESS, duration, {incDamageChange=incDamageChange,hateBonus=hateBonus}) - hit = true end end diff --git a/game/modules/tome/data/talents/cursed/punishments.lua b/game/modules/tome/data/talents/cursed/punishments.lua index 85f09c5075863ed769b777c77a76ee945a6b0791..c19b7fc4667f8350fbb5ebdde7d691035a3a844e 100644 --- a/game/modules/tome/data/talents/cursed/punishments.lua +++ b/game/modules/tome/data/talents/cursed/punishments.lua @@ -322,19 +322,16 @@ newTalent{ -- confusion if target:canBe("confusion") and not target:hasEffect(target.EFF_MADNESS_CONFUSED) then target:setEffect(target.EFF_MADNESS_CONFUSED, 3, {power=50, mindResistChange=mindResistChange}) -- Consistent with other confusion - hit = true end elseif effect == 2 then -- stun if target:canBe("stun") and not target:hasEffect(target.EFF_MADNESS_STUNNED) then target:setEffect(target.EFF_MADNESS_STUNNED, 3, {mindResistChange=mindResistChange}) - hit = true end elseif effect == 3 then -- slow if target:canBe("slow") and not target:hasEffect(target.EFF_MADNESS_SLOW) then target:setEffect(target.EFF_MADNESS_SLOW, 3, {power=0.3, mindResistChange=mindResistChange}) - hit = true end end end diff --git a/game/modules/tome/data/talents/cursed/shadows.lua b/game/modules/tome/data/talents/cursed/shadows.lua index 2dd35a1ebf328b81934027ee6af847f50ded0522..f36b4799d083abc0c16845eda2a1c25d66d9735d 100644 --- a/game/modules/tome/data/talents/cursed/shadows.lua +++ b/game/modules/tome/data/talents/cursed/shadows.lua @@ -391,7 +391,7 @@ newTalent{ end self:incHate(-6) - level = t.getLevel(self, t) + local level = t.getLevel(self, t) local tShadowWarriors = self:knowTalent(self.T_SHADOW_WARRIORS) and self:getTalentFromId(self.T_SHADOW_WARRIORS) or nil local tShadowMages = self:knowTalent(self.T_SHADOW_MAGES) and self:getTalentFromId(self.T_SHADOW_MAGES) or nil diff --git a/game/modules/tome/data/talents/cursed/slaughter.lua b/game/modules/tome/data/talents/cursed/slaughter.lua index 0ae43c5210475163a38382d656e2ff448373a964..65968402248b4f331e3b4417ee8950396f154fef 100644 --- a/game/modules/tome/data/talents/cursed/slaughter.lua +++ b/game/modules/tome/data/talents/cursed/slaughter.lua @@ -329,8 +329,8 @@ newTalent{ return true end, on_attackTarget = function(self, t, target) - if inCleave then return end - inCleave = true + if self.inCleave then return end + self.inCleave = true local chance = t.getChance(self, t) if rng.percent(chance) then @@ -343,12 +343,12 @@ newTalent{ local damageMultiplier = t.getDamageMultiplier(self, t) self:logCombat(secondTarget, "#Source# cleaves through #Target#!") self:attackTarget(secondTarget, nil, damageMultiplier, true) - inCleave = false + self.inCleave = false return end end end - inCleave = false + self.inCleave = false end, info = function(self, t) local chance = t.getChance(self, t, 0) diff --git a/game/modules/tome/data/talents/gifts/mucus.lua b/game/modules/tome/data/talents/gifts/mucus.lua index 0d8dade30d4504f92b912f7ce09b78affde96cdb..a4b97c331a6f33ab3d1a8c8b6546e141f50e6ef1 100644 --- a/game/modules/tome/data/talents/gifts/mucus.lua +++ b/game/modules/tome/data/talents/gifts/mucus.lua @@ -285,7 +285,7 @@ newTalent{ end, action = function(self, t) local tg = {type="hit", nolock=true, pass_terrain=true, nowarning=true, range=self:getTalentRange(t), requires_knowledge=false} - x, y = self:getTarget(tg) + local x, y = self:getTarget(tg) if not x then return nil end -- Target code does not restrict the target coordinates to the range, it lets the project function do it -- but we cant ... diff --git a/game/modules/tome/data/talents/gifts/slime.lua b/game/modules/tome/data/talents/gifts/slime.lua index 537667ea63cb63acd8f2506384100dd692225903..496017694468d95484ae89b441724d6a474c8eca 100644 --- a/game/modules/tome/data/talents/gifts/slime.lua +++ b/game/modules/tome/data/talents/gifts/slime.lua @@ -47,6 +47,7 @@ newTalent{ end, } +-- The damage on this was ludicrous, especially considering 3 of the 4 possible debuffs are among the stronger in the game and have *no save check* newTalent{ name = "Poisonous Spores", type = {"wild-gift/slime", 2}, @@ -59,8 +60,8 @@ newTalent{ range = 10, tactical = { ATTACKAREA = { NATURE = 2 }, DISABLE = 1 }, radius = function(self, t) return math.floor(self:combatTalentScale(t, 1, 2.7)) end, -- yields 2 at tl=3 - getDamage = function(self, t) return self:combatTalentMindDamage(t, 30, 500) end, - critPower = function(self, t) return self:combatTalentMindDamage(t, 10, 60) end, + getDamage = function(self, t) return self:combatTalentMindDamage(t, 30, 200) end, + critPower = function(self, t) return self:combatTalentMindDamage(t, 10, 40) end, requires_target = true, action = function(self, t) local tg = {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), friendlyfire=false} @@ -88,6 +89,8 @@ newTalent{ end, } +-- Boring, but disarm was way too far +-- Now that we have melee retaliation damage shown in tooltips its a little safer to raise the damage on this newTalent{ name = "Acidic Skin", type = {"wild-gift/slime", 3}, @@ -101,12 +104,12 @@ newTalent{ requires_target = false, tactical = { DEFEND = 1 }, getChance = function(self, t) return self:combatTalentLimit(t, 100, 7, 15) end, -- Limit < 100% - getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end, + getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 80) end, activate = function(self, t) game:playSoundNear(self, "talents/slime") local power = t.getDamage(self, t) return { - onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.ACID_DISARM]={dam=power, chance=t.getChance(self, t)}}), + onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.ACID] = t.getDamage(self, t)}), } end, deactivate = function(self, t, p) @@ -114,8 +117,8 @@ newTalent{ return true end, info = function(self, t) - return ([[Your skin drips with acid, damaging all that hit you for %0.1f Acid damage with a %d%% chance to disarm them for 3 turns. - The damage increases with your Mindpower.]]):format(damDesc(self, DamageType.ACID, t.getDamage(self, t)), t.getChance(self, t)) + return ([[Your skin drips with acid, damaging all that hit you for %0.1f Acid damage. + The damage increases with your Mindpower.]]):format(damDesc(self, DamageType.ACID, t.getDamage(self, t))) end, } diff --git a/game/modules/tome/data/talents/misc/inscriptions.lua b/game/modules/tome/data/talents/misc/inscriptions.lua index c6847ca287b53008b9221c6cceda6b5ca3034020..decffa4ca3e6f44a556e10e34747499a1ab1c589 100644 --- a/game/modules/tome/data/talents/misc/inscriptions.lua +++ b/game/modules/tome/data/talents/misc/inscriptions.lua @@ -90,11 +90,16 @@ newInscription{ points = 1, tactical = { HEAL = 2 }, is_heal = true, + no_energy = true, action = function(self, t) local data = self:getInscriptionData(t.short_name) self:attr("allow_on_heal", 1) self:heal(data.heal + data.inc_stat, t) self:attr("allow_on_heal", -1) + + self:removeEffectsFilter(function(e) return e.subtype.wound end, 1) + self:removeEffectsFilter(function(e) return e.subtype.poison end, 1) + if core.shader.active(4) then self:addParticles(Particles.new("shader_shield_temp", 1, {toback=true , size_factor=1.5, y=-0.3, img="healgreen", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=2.0})) self:addParticles(Particles.new("shader_shield_temp", 1, {toback=false, size_factor=1.5, y=-0.3, img="healgreen", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=1.0})) @@ -103,7 +108,7 @@ newInscription{ end, info = function(self, t) local data = self:getInscriptionData(t.short_name) - return ([[Activate the infusion to heal yourself for %d life.]]):format(data.heal + data.inc_stat) + return ([[Activate the infusion to instantly heal yourself for %d and cleanse 1 wound and poison effect.]]):format(data.heal + data.inc_stat) end, short_info = function(self, t) local data = self:getInscriptionData(t.short_name) @@ -465,7 +470,7 @@ newInscription{ action = function(self, t) local data = self:getInscriptionData(t.short_name) local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=data.range + data.inc_stat, radius=3, requires_knowledge=false} - x, y = self:getTarget(tg) + local x, y = self:getTarget(tg) if not x then return nil end -- Target code does not restrict the target coordinates to the range, it lets the project function do it -- but we cant ... diff --git a/game/modules/tome/data/talents/misc/npcs.lua b/game/modules/tome/data/talents/misc/npcs.lua index 41ea8c596cb041a41ad0c8c530349ced9fa3f244..52e7866942157bfacdc4dc229024f692593461b6 100644 --- a/game/modules/tome/data/talents/misc/npcs.lua +++ b/game/modules/tome/data/talents/misc/npcs.lua @@ -2091,9 +2091,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end diff --git a/game/modules/tome/data/talents/misc/objects.lua b/game/modules/tome/data/talents/misc/objects.lua index 0e852182d4773567eb3124e5ecf6917e06bdf876..4cf2019d20d077385ad08cb7383ebb7c25c81219 100644 --- a/game/modules/tome/data/talents/misc/objects.lua +++ b/game/modules/tome/data/talents/misc/objects.lua @@ -313,8 +313,8 @@ newTalent{ local tg = self:getTalentTarget(t) local x, y, target = self:getTarget(tg) if not x or not y then return nil end - dispower = t.getpower(self,t) - dismax = t.maxpower(self, t) + local dispower = t.getpower(self,t) + local dismax = t.maxpower(self, t) self:project(tg, x, y, function(px, py) target:setEffect(target.EFF_SPELL_DISRUPTION, 8, {src=self, power = dispower, max = dismax, apply_power=self:combatMindpower()}) if rng.percent(30) and self:getTalentLevel(t)>2 then diff --git a/game/modules/tome/data/talents/psionic/other.lua b/game/modules/tome/data/talents/psionic/other.lua index e30a5ebf16214b13913867c568750cd9d8920eb0..d2ffce420e52f7c14014baceb4fca2baa67d63fc 100644 --- a/game/modules/tome/data/talents/psionic/other.lua +++ b/game/modules/tome/data/talents/psionic/other.lua @@ -133,7 +133,7 @@ newTalent{ hit = hit or h if hit and not sound then sound = o.combat.sound elseif not hit and not sound_miss then sound_miss = o.combat.sound_miss end - if not o.combat.no_stealth_break then break_stealth = true end + if not o.combat.no_stealth_break then self:breakStealth() end self:breakStepUp() end end diff --git a/game/modules/tome/data/talents/psionic/possession.lua b/game/modules/tome/data/talents/psionic/possession.lua index 8b2f92096a7a73cf77bfb72d9f2c6a55653cba3e..a59d3a6bdf5a655142e7e0cbab6c1fb0ee021e85 100644 --- a/game/modules/tome/data/talents/psionic/possession.lua +++ b/game/modules/tome/data/talents/psionic/possession.lua @@ -40,7 +40,7 @@ newTalent{ local tx, ty = self:getTarget(tg) if not tx or not ty then return nil end local _ _, tx, ty = self:canProject(tg, tx, ty) - target = game.level.map(tx, ty, Map.ACTOR) + local target = game.level.map(tx, ty, Map.ACTOR) if not target or target == self then return nil end if target == self.summoner then diff --git a/game/modules/tome/data/talents/psionic/projection.lua b/game/modules/tome/data/talents/psionic/projection.lua index aef95430609ecc5d43c9ac872ebe63acfb32a973..33449dd5d5bfd257c687a2a8291b8636fed07830 100644 --- a/game/modules/tome/data/talents/psionic/projection.lua +++ b/game/modules/tome/data/talents/psionic/projection.lua @@ -397,7 +397,6 @@ newTalent{ print("[Chain lightning] targetting", fx, fy, "from", self.x, self.y) local actor = game.level.map(dx, dy, Map.ACTOR) if actor and not affected[actor] then - ignored = false affected[actor] = true first = actor diff --git a/game/modules/tome/data/talents/psionic/psi-archery.lua b/game/modules/tome/data/talents/psionic/psi-archery.lua index c51700059f7e5a6250a5a8e85f69c8c7da43b276..9d667f88db261cab64758f8704b516a52fc6aac0 100644 --- a/game/modules/tome/data/talents/psionic/psi-archery.lua +++ b/game/modules/tome/data/talents/psionic/psi-archery.lua @@ -192,7 +192,7 @@ newTalent{ --hit = hit or h --if hit and not sound then sound = o.combat.sound --elseif not hit and not sound_miss then sound_miss = o.combat.sound_miss end - if not o.combat.no_stealth_break then break_stealth = true end + if not o.combat.no_stealth_break then self:breakStealth() end self:breakStepUp() end end diff --git a/game/modules/tome/data/talents/spells/air.lua b/game/modules/tome/data/talents/spells/air.lua index b2c7e0cf8e4eaf8df2b19023982f2e9187693cdd..3905349e672f9a4ecbfdad0727b95886e50de5b7 100644 --- a/game/modules/tome/data/talents/spells/air.lua +++ b/game/modules/tome/data/talents/spells/air.lua @@ -84,7 +84,6 @@ newTalent{ print("[Chain lightning] targetting", fx, fy, "from", self.x, self.y) local actor = game.level.map(dx, dy, Map.ACTOR) if actor and not affected[actor] then - ignored = false affected[actor] = true first = actor diff --git a/game/modules/tome/data/talents/spells/divination.lua b/game/modules/tome/data/talents/spells/divination.lua index faa49384015e2fbddfe80a227eb3ba1df24d6912..bc48fe834f81e124ed540afb78ebbecc916cf3f0 100644 --- a/game/modules/tome/data/talents/spells/divination.lua +++ b/game/modules/tome/data/talents/spells/divination.lua @@ -31,7 +31,7 @@ newTalent{ getRadius = function(self, t) return math.floor(self:combatTalentScale(t, 5, 9)) end, action = function(self, t) local tg = {type="hit", nolock=true, pass_terrain=true, nowarning=true, range=100, requires_knowledge=false} - x, y = self:getTarget(tg) + local x, y = self:getTarget(tg) if not x then return nil end -- Target code does not restrict the target coordinates to the range, it lets the project function do it -- but we cant ... diff --git a/game/modules/tome/data/talents/techniques/2h-assault.lua b/game/modules/tome/data/talents/techniques/2h-assault.lua index a9a8bdc3874198c97d975b5ce81033a14af28889..bb0015f582c4ad22fa7ea8c598cafaa4307b41c6 100644 --- a/game/modules/tome/data/talents/techniques/2h-assault.lua +++ b/game/modules/tome/data/talents/techniques/2h-assault.lua @@ -67,6 +67,7 @@ newTalent{ no_energy = false, tactical = { ATTACK = { weapon = 2 }, CLOSEIN = 0.5 }, requires_target = true, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.7, 1.8) end, on_pre_use = function(self, t, silent) if not self:hasTwoHandedWeapon() then if not silent then game.logPlayer(self, "You require a two handed weapon to use this talent.") end return false end return true end, action = function(self, t) local weapon = self:hasTwoHandedWeapon() @@ -77,7 +78,7 @@ newTalent{ if not x or not y then return nil end if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end local dir = util.getDir(x, y, self.x, self.y) or 6 - local moved = 0.75 + local moved = 0.5 if self:canMove(x, y) then self:move(x, y) moved = 1 @@ -88,16 +89,19 @@ newTalent{ local rx, ry = util.coordAddDir(self.x, self.y, util.dirSides(dir, self.x, self.y).right) local target, lt, rt = game.level.map(fx, fy, Map.ACTOR), game.level.map(lx, ly, Map.ACTOR), game.level.map(rx, ry, Map.ACTOR) - if target then self:attackTargetWith(target, weapon.combat, nil, self:combatTalentWeaponDamage(t, 0.9, 2) * moved) end - if lt then self:attackTargetWith(lt, weapon.combat, nil, self:combatTalentWeaponDamage(t, 0.9, 2) * moved) end - if rt then self:attackTargetWith(rt, weapon.combat, nil, self:combatTalentWeaponDamage(t, 0.9, 2) * moved) end + local damage = t.getDamage(self, t) * moved + if target then self:attackTargetWith(target, weapon.combat, nil, damage) end + if lt then self:attackTargetWith(lt, weapon.combat, nil, damage) end + if rt then self:attackTargetWith(rt, weapon.combat, nil, damage) end return true end, info = function(self, t) + local damage = t.getDamage(self, t) * 100 + local movedamage = t.getDamage(self, t) * 0.5 * 100 return ([[Take a step toward your foes using the momentum to cleave all creatures in a 3 wide arc in front of you for %d%% weapon damage. If you failed to move the damage is instead %d%%.]]) - :format(100 * self:combatTalentWeaponDamage(t, 0.9, 2), 100 * self:combatTalentWeaponDamage(t, 0.9, 2) * 0.75) + :format(damage, movedamage) end, } diff --git a/game/modules/tome/data/talents/techniques/acrobatics.lua b/game/modules/tome/data/talents/techniques/acrobatics.lua index 8434c4a591a6dcf6a85b101f92dbf9789d5d52ba..55a5e7dd459a96ef0b5e21fc13d550766f87bd00 100644 --- a/game/modules/tome/data/talents/techniques/acrobatics.lua +++ b/game/modules/tome/data/talents/techniques/acrobatics.lua @@ -30,14 +30,14 @@ newTalent { require = techs_dex_req1, points = 5, random_ego = "attack", - cooldown = function(self, t) return 25 - cooldown_bonus(self) end, + cooldown = function(self, t) return 10 - cooldown_bonus(self) end, stamina = function(self, t) return math.max(0, 18 - stamina_bonus(self)) end, tactical = {ESCAPE = 2}, on_pre_use = function(self, t) return not self:attr("never_move") end, range = function(self, t) - return math.floor(2 + self:getTalentLevel(t) * 0.5) + return math.floor(self:combatTalentScale(t, 3, 8)) end, target = function(self, t) return {type="beam", range=self:getTalentRange(t), talent=t, nolock=true} @@ -92,8 +92,8 @@ newTalent { } newTalent { + name = "Tumble", short_name = "SKIRMISHER_CUNNING_ROLL", - name = "Cunning Roll", type = {"technique/acrobatics", 2}, require = techs_dex_req2, points = 5, @@ -101,11 +101,11 @@ newTalent { cooldown = function(self, t) return 20 - cooldown_bonus(self) end, no_energy = true, stamina = function(self, t) - return math.max(0, 40 - self:getTalentLevel(t) * 3 - stamina_bonus(self)) + return math.max(0, 20 - stamina_bonus(self)) end, tactical = {ESCAPE = 2, BUFF = 1}, range = function(self, t) - return 2 + math.floor(self:getTalentLevel(t) / 6) + return math.floor(self:combatTalentScale(t, 2, 4)) end, target = function(self, t) return {type="beam", range=self:getTalentRange(t), talent=t} @@ -121,8 +121,10 @@ newTalent { if not x or not y then return end if self.x == x and self.y == y then return end if core.fov.distance(self.x, self.y, x, y) > self:getTalentRange(t) then return end - if target or game.level.map:checkEntity(tx, ty, Map.TERRAIN, "block_move", self) then + + if target or game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move", self) then game.logPlayer(self, "You must have an empty space to roll to.") + return false end self:move(x, y, true) @@ -150,7 +152,7 @@ newTalent { points = 5, cooldown = function(self, t) return 10 - cooldown_bonus(self) end, stamina_per_use = function(self, t) return 30 - stamina_bonus(self) end, - sustain_stamina = 0, + sustain_stamina = 10, require = techs_dex_req3, tactical = { BUFF = 2 }, @@ -173,18 +175,9 @@ newTalent { local cost = t.stamina_per_use(self, t) if damage >= self.max_life * t.getLifeTrigger(self, t) * 0.01 then - -- now to find empty space - --[SHIBARI NOTE] Removing the roll part of this, too random and too much anti-synergy for a core defense - -- Shame though, its very thematic local nx, ny = util.findFreeGrid(self.x, self.y, 1, true, {[Map.ACTOR]=true}) if nx and ny and use_stamina(self, cost) then - --local ox, oy = self.x, self.y - --self:move(nx, ny, true) - - -- Don't have trigger cooldown. - -- -- Apply cooldown effect. - -- self:setEffect("EFF_SKIRMISHER_TRAINED_REACTIONS_COOLDOWN", t.cooldown(self, t), {}) -- Apply effect with duration 0. self:setEffect("EFF_SKIRMISHER_DEFENSIVE_ROLL", 1, {reduce = t.getReduction(self, t)}) @@ -209,7 +202,7 @@ newTalent { local reduce = t.getReduction(self, t) local cost = t.stamina_per_use(self, t) * (1 + self:combatFatigue() * 0.01) return ([[While sustainted, any time you would lose more than %d%% of your life in a single hit, you instead duck out of the way gaining a temporary buff that reduces this damage and all further damage that turn by %d%%. - This costs %d Stamina per dodge and will not trigger if you do not have the Stamina.]]) + This costs %d Stamina per dodge and will not trigger if you do not have the Stamina or there isn't an adjacent grid (though you will not move).]]) :format(trigger, reduce, cost) end, @@ -222,15 +215,17 @@ newTalent { require = techs_dex_req4, mode = "passive", points = 5, - cooldown_bonus = function(self, t) return math.floor(self:getTalentLevel(t)) end, - stamina_bonus = function(self, t) return math.floor(self:getTalentLevel(t) * 2) end, + --cooldown_bonus = function(self, t) return math.floor(self:getTalentLevel(t)) end, + --stamina_bonus = function(self, t) return math.floor(self:getTalentLevel(t) * 2) end, + stamina_bonus = function(self, t) return math.floor(self:combatTalentScale(t, 1, 10)) end, + cooldown_bonus = function(self, t) return math.floor(self:combatTalentScale(t, 1, 6)) end, speed_buff = function(self, t) local level = self:getTalentLevel(t) if level >= 5 then return {global_speed_add = 0.2, duration = 2} end if level >= 3 then return {global_speed_add = 0.1, duration = 1} end end, info = function(self, t) - return ([[Lowers the cooldown of Vault, Cunning Roll, and Trained Reactions by %d, and their stamina costs by %d. At Rank 3 you also gain 10%% global speed for 1 turn after Trained Reactions activates. At rank 5 this speed bonus becomes 20%% and lasts for 2 rounds.]]) + return ([[Lowers the cooldown of Vault and Cunning Roll by %d, and their stamina costs by %d. At Rank 3 you also gain 10%% global speed for 1 turn after Trained Reactions activates. At rank 5 this speed bonus becomes 20%% and lasts for 2 rounds.]]) :format(t.cooldown_bonus(self, t), t.stamina_bonus(self, t)) end, diff --git a/game/modules/tome/data/talents/techniques/buckler-training.lua b/game/modules/tome/data/talents/techniques/buckler-training.lua index 7a9ae9f5917538e9fd76158182b23b4402297eb6..df86703674443266161dc267181533d682003088 100644 --- a/game/modules/tome/data/talents/techniques/buckler-training.lua +++ b/game/modules/tome/data/talents/techniques/buckler-training.lua @@ -39,7 +39,12 @@ newTalent { t2.doCounter(self, t2, target) end end, - + on_learn = function(self, t) + self:attr("show_shield_combat", 1) + end, + on_unlearn = function(self, t) + self:attr("show_shield_combat", 1) + end, info = function(self, t) local block = t.chance(self, t) local armor = t.getHardiness(self, t) @@ -184,6 +189,8 @@ newTalent { end, } +-- Stamina cost removed, this triggers too much and tends to randomly spike your stamina to nothing +-- It might be ok if there weren't other passives with random stamina drain too, but.. newTalent { short_name = "SKIRMISHER_COUNTER_SHOT", name = "Counter Shot", @@ -208,44 +215,36 @@ newTalent { deactivate = function(self, t, p) return true end, - getStaminaPerShot = function(self, t) - return 10 * (1 + self:combatFatigue() * 0.01) - end, getMult = function(self, t) - return self:combatTalentScale(t, .9, 1.6) + return self:combatTalentScale(t, .4, 1) + end, + getBlocks = function(self, t) + return math.min(7, math.floor(self:combatTalentScale(t, 1, 4))) end, -- called from the relevant buckler talents doCounter = function(self, t, target) local sling = self:hasArcheryWeapon() - local stamina = t.getStaminaPerShot(self, t) - if not sling or self.stamina < stamina then + --local stamina = t.getStaminaPerShot(self, t) + if not sling or (self.turn_procs.counter_shot and self.turn_procs.counter_shot > t.getBlocks(self, t) ) or not target.x or not target.y then --or self.stamina < stamina then return false end + self.turn_procs.counter_shot = 1 + (self.turn_procs.counter_shot or 0) local targets = self:archeryAcquireTargets(nil, {one_shot=true, x=target.x, y=target.y, no_energy = true}) if targets then - --self:logCombat(who, "#Source# follows up with a countershot.") - self:incStamina(-stamina) + self:logCombat(who, "#ORCHID##Source# follows up with a countershot.#LAST#") + --self:incStamina(-stamina) - local autocrit = false - if self:getTalentLevelRaw(t) >= 5 then - autocrit = true - end - if autocrit then - self.combat_physcrit = self.combat_physcrit + 1000 - end self:archeryShoot(targets, t, nil, {mult=t.getMult(self, t)}) - if autocrit then - self.combat_physcrit = self.combat_physcrit - 1000 - end end end, info = function(self, t) local mult = t.getMult(self, t) * 100 - local stamina = t.getStaminaPerShot(self, t) - return ([[Any time you block an attack with Buckler Expertise or Buckler Mastery you instantly counterattack with your sling for %d%% damage at the cost of %d stamina. - With the fifth talent point, your Counter Shot is a guaranteed critical.]]) - :format(mult, stamina) + local blocks = t.getBlocks(self, t) + --local stamina = t.getStaminaPerShot(self, t) + return ([[Any time you block an attack with Buckler Expertise or Buckler Mastery you instantly counterattack with your sling for %d%% damage This can only occur up to %d times per turn. + ]]) + :format(mult, blocks) end, } diff --git a/game/modules/tome/data/talents/techniques/conditioning.lua b/game/modules/tome/data/talents/techniques/conditioning.lua index 571f7caad333623b5022aae9c61831c0b2be1b80..df72726e56819f42cce3b0dcc94167d3f7ac7949 100644 --- a/game/modules/tome/data/talents/techniques/conditioning.lua +++ b/game/modules/tome/data/talents/techniques/conditioning.lua @@ -23,21 +23,22 @@ newTalent{ require = techs_con_req1, mode = "passive", points = 5, + --getHealPct = function(self, t) return math.min(.3, self:combatTalentStatDamage(t, "con", 0.03, 0.2)) end, + getHealPct = function(self, t) return math.min(.4, self:combatTalentScale(t, 0.03, 0.3)) end, getWoundReduction = function(self, t) return self:combatTalentLimit(t, 1, 0.17, 0.5) end, -- Limit <100% - getHealMod = function(self, t) return self:combatTalentStatDamage(t, "con", 10, 50) end, - getLifeRegen = function(self, t) return self:combatTalentStatDamage(t, "con", 2, 20) + 0.001 * self.max_life end, -- Add fraction of max life - getDuration = function(self, t) return math.floor(self:combatTalentScale(t, 3, 7)) end, + getDuration = function(self, t) return 6 end, do_vitality_recovery = function(self, t) - self:setEffect(self.EFF_RECOVERY, t.getDuration(self, t), {heal_mod = t.getHealMod(self, t), regen = t.getLifeRegen(self, t)}) + self:setEffect(self.EFF_RECOVERY, t.getDuration(self, t), {pct = t.getHealPct(self, t) / t.getDuration(self, t)}) end, info = function(self, t) local wounds = t.getWoundReduction(self, t) * 100 - local regen = t.getLifeRegen(self, t) - local healmod = t.getHealMod(self, t) + local healpct = t.getHealPct(self, t) * 100 + local heal = t.getHealPct(self, t) * self.max_life local duration = t.getDuration(self, t) - return ([[You recover faster from poisons, diseases and wounds, reducing the duration of all such effects by %d%%. Additionally, you gain %0.2f life regen and %d%% healing modifier for %d turns when your life drops below 50%%. - The healing modifier and life regen will scale with your Constitution.]]): - format(wounds, regen, healmod, duration) + return ([[You recover faster from poisons, diseases and wounds, reducing the duration of all such effects by %d%%. + Additionally, when your life goes below 50%%, you heal for %d%% of your max HP (%d) over %d turns up to a max of 100 per turn. + The healing will scale with your Constitution.]]): + format(wounds, healpct, heal, duration) end, } @@ -62,7 +63,7 @@ newTalent{ effs[#effs+1] = {"effect", eff_id} elseif e.subtype.pin and self:getTalentLevel(t) >=4 then effs[#effs+1] = {"effect", eff_id} - elseif e.subtype.slow and self:getTalentLevel(t) >=5 then + elseif (e.subtype.slow or e.subtype.wound) and self:getTalentLevel(t) >=5 then effs[#effs+1] = {"effect", eff_id} end end @@ -72,14 +73,14 @@ newTalent{ local eff = rng.tableRemove(effs) if eff[1] == "effect" and rng.percent(t.getChance(self, t)) then self:removeEffect(eff[2]) - game.logSeen(self, "%s has recovered!", self.name:capitalize()) + game.logSeen(self, "#ORCHID#%s has recovered!#LAST#", self.name:capitalize()) end end end, info = function(self, t) local chance = t.getChance(self, t) return ([[You've learned to recover quickly from effects that would disable you. Each turn, you have a %d%% chance to recover from a single stun effect. - At talent level 2 you may also recover from blindness, at level 3 confusion, level 4 pins, and level 5 slows. + At talent level 2 you may also recover from blindness, at level 3 confusion, level 4 pins, and level 5 slows and wounds. Only one effect may be recovered from each turn, and the chance to recover from an effect scales with your Constitution.]]): format(chance) end, diff --git a/game/modules/tome/data/talents/techniques/dualweapon.lua b/game/modules/tome/data/talents/techniques/dualweapon.lua index 1855901237754ad9d70f4fe8ffeb91efca14af6f..c3f451f0a97ac0a22054018e0cc919fca4b9047d 100644 --- a/game/modules/tome/data/talents/techniques/dualweapon.lua +++ b/game/modules/tome/data/talents/techniques/dualweapon.lua @@ -127,12 +127,12 @@ newTalent{ sustain_stamina = 50, require = techs_dex_req4, tactical = { BUFF = 2 }, - on_pre_use = function(self, t, silent) if not self:hasDualWeapon() then if not silent then game.logPlayer(self, "You require two weapons to use this talent.") end return false end return true end, - getSpeed = function(self, t) return self:combatTalentScale(t, 0.21, 0.70, 0.75) end, + on_pre_use = function(self, t, silent) if self:hasArcheryWeapon() or not self:hasDualWeapon() then if not silent then game.logPlayer(self, "You require two melee weapons to use this talent.") end return false end return true end, + getSpeed = function(self, t) return self:combatTalentScale(t, 0.11, 0.40, 0.75) end, activate = function(self, t) local weapon, offweapon = self:hasDualWeapon() if not weapon then - game.logPlayer(self, "You cannot use Momentum without dual wielding!") + game.logPlayer(self, "You cannot use Momentum without dual wielding melee weapons!") return nil end @@ -235,6 +235,10 @@ newTalent{ end, } +-- This is a good candidate for replacement if someone has a clever idea +-- A. Its boring +-- B. Its pretty bad +-- D. I think we should solidify 2H as generally the best at multitarget hits, so having 1 less AoE than 2H Assault would be good newTalent{ name = "Sweep", type = {"technique/dualweapon-attack", 3}, diff --git a/game/modules/tome/data/talents/techniques/finishing-moves.lua b/game/modules/tome/data/talents/techniques/finishing-moves.lua index 6d4995058b1560a97c86a6426f62d1f3e9353cf6..c25f68d783128218169fc6e9af46cbcb565d03e6 100644 --- a/game/modules/tome/data/talents/techniques/finishing-moves.lua +++ b/game/modules/tome/data/talents/techniques/finishing-moves.lua @@ -38,9 +38,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end @@ -69,20 +67,22 @@ newTalent{ end, } +-- Low CD makes this more or less the "default" combo point dump for damage +-- Its pretty crap at low combo point newTalent{ name = "Concussive Punch", type = {"technique/finishing-moves", 2}, require = techs_dex_req2, points = 5, random_ego = "attack", - cooldown = 10, + cooldown = 6, stamina = 10, message = "@Source@ throws a concussive punch.", tactical = { ATTACK = { weapon = 2 }, }, requires_target = true, --on_pre_use = function(self, t, silent) if not self:hasEffect(self.EFF_COMBO) then if not silent then game.logPlayer(self, "You must have a combo going to use this ability.") end return false end return true end, getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.6, 1.5) + getStrikingStyle(self, dam) end, - getAreaDamage = function(self, t) return self:combatTalentStatDamage(t, "str", 20, 600) * (1 + getStrikingStyle(self, dam)) end, + getAreaDamage = function(self, t) return self:combatTalentStatDamage(t, "str", 10, 550) * (1 + getStrikingStyle(self, dam)) end, radius = function(self, t) return (1 + self:getCombo(combo) ) end, action = function(self, t) local tg = {type="hit", range=self:getTalentRange(t)} @@ -91,9 +91,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end @@ -188,19 +186,20 @@ newTalent{ end, } + newTalent{ name = "Haymaker", type = {"technique/finishing-moves", 4}, require = techs_dex_req4, points = 5, random_ego = "attack", - cooldown = 16, + cooldown = 12, stamina = 12, message = "@Source@ throws a wild haymaker!", tactical = { ATTACK = { weapon = 2 } }, requires_target = true, --on_pre_use = function(self, t, silent) if not self:hasEffect(self.EFF_COMBO) then if not silent then game.logPlayer(self, "You must have a combo going to use this ability.") end return false end return true end, - getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1, 2.8) + getStrikingStyle(self, dam) end, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.2, 3) + getStrikingStyle(self, dam) end, getBonusDamage = function(self, t) return self:getCombo(combo)/5 end, -- shift more of the damage to CP getStamina = function(self, t, comb) return self:combatLimit((self:getTalentLevel(t) + comb), 0.5, 0, 0, 0.2, 10) * self.max_stamina @@ -212,9 +211,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end diff --git a/game/modules/tome/data/talents/techniques/magical-combat.lua b/game/modules/tome/data/talents/techniques/magical-combat.lua index 8c98bd91d1ebd977506cc46067365566cfb7d13f..c32a8d12a70d43cdc200169838ff526538c202b5 100644 --- a/game/modules/tome/data/talents/techniques/magical-combat.lua +++ b/game/modules/tome/data/talents/techniques/magical-combat.lua @@ -32,7 +32,7 @@ newTalent{ if self.x == target.x and self.y == target.y then return nil end local chance = t.getChance(self, t) - if self:hasDualWeapon() then chance = chance / 2 end + if self:hasDualWeapon() or self:hasShield() then chance = chance / 2 end if rng.percent(chance) then local spells = {} @@ -78,7 +78,7 @@ newTalent{ end, info = function(self, t) return ([[Allows you to use a melee weapon to focus your spells, granting a %d%% chance per melee attack to deliver a Flame, Lightning or Earthen Missiles spell as a free action on the target. - When using two weapons, the chance is halved for each weapon. + When dual wielding or using a shield the chance is halved for each weapon. Delivering the spell this way will not trigger a spell cooldown, but only works if the spell is not cooling down. The chance increases with your Cunning.]]): format(t.getChance(self, t)) @@ -142,7 +142,8 @@ newTalent{ info = function(self, t) return ([[Raw magical damage channels through the caster's weapon, increasing Physical Power by %d. Each time your crit with a melee blow, you will unleash a radius 2 ball of either fire, lightning or arcane damage, doing %0.2f. - The bonus scales with your Spellpower.]]): + The bonus scales with your Spellpower. + If you are dual wielding or using a shield this will only occur 50%% of the time.]]): format(self:combatSpellpower() * t.getSPMult(self, t), self:combatSpellpower() * 2) end, } diff --git a/game/modules/tome/data/talents/techniques/pugilism.lua b/game/modules/tome/data/talents/techniques/pugilism.lua index 72b13a380578483deb6c8fddae673a23cfd76d94..4fbb5435200b1ec3ca3d72d1ecd2bda517490549 100644 --- a/game/modules/tome/data/talents/techniques/pugilism.lua +++ b/game/modules/tome/data/talents/techniques/pugilism.lua @@ -97,6 +97,7 @@ newTalent{ end -- breaks active grapples if the target is not grappled + local grappled if target:isGrappled(self) then grappled = true else @@ -243,7 +244,6 @@ newTalent{ end, } --- If kick, normal attack+small kick effect? newTalent{ name = "Axe Kick", type = {"technique/pugilism", 3}, @@ -255,7 +255,6 @@ newTalent{ return 20 end, getDuration = function(self, t) - --return self:combatTalentScale(t, 1, 3) return self:combatTalentLimit(t, 5, 1, 4) end, message = "@Source@ raises their leg and snaps it downward in a devastating axe kick.", @@ -269,9 +268,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end @@ -293,7 +290,8 @@ newTalent{ end, info = function(self, t) local damage = t.getDamage(self, t) * 100 - return ([[Deliver a devastating axe kick dealing %d%% damage. If the blow connects your target is brain damaged, causing all talents to fail for %d turns and earning 2 combo points.]]) + return ([[Deliver a devastating axe kick dealing %d%% damage. If the blow connects your target is brain damaged, causing all talents to fail for %d turns and earning 2 combo points. + This effect cannot be saved against, though it can be dodged.]]) :format(damage, t.getDuration(self, t)) end, } @@ -304,13 +302,12 @@ newTalent{ require = techs_dex_req4, points = 5, random_ego = "attack", - --cooldown = function(self, t) return math.ceil(24 * getRelentless(self, cd)) end, cooldown = 16, stamina = 15, message = "@Source@ lashes out with a flurry of fists.", tactical = { ATTACK = { weapon = 2 } }, requires_target = true, - getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.4, 0.8) + getStrikingStyle(self, dam) end, + getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.3, 1) + getStrikingStyle(self, dam) end, action = function(self, t) local tg = {type="hit", range=self:getTalentRange(t)} local x, y, target = self:getTarget(tg) @@ -319,8 +316,6 @@ newTalent{ -- breaks active grapples if the target is not grappled if target:isGrappled(self) then - grappled = true - else self:breakGrapples() end diff --git a/game/modules/tome/data/talents/techniques/skirmisher-slings.lua b/game/modules/tome/data/talents/techniques/skirmisher-slings.lua index dc64ca5709f8bc559d7034e1d16c82999c22605a..c8fb7874c3274c22acf44736f29e95b521fb8fe1 100644 --- a/game/modules/tome/data/talents/techniques/skirmisher-slings.lua +++ b/game/modules/tome/data/talents/techniques/skirmisher-slings.lua @@ -60,10 +60,10 @@ newTalent { tactical = {ATTACK = {weapon = 2}}, range = archery_range, cooldown = 5, - stamina = 10, + stamina = 15, on_pre_use = function(self, t, silent) return sling_equipped(self, silent) end, getDamage = function(self, t) - return self:combatTalentWeaponDamage(t, 1.4, 2.4) + return self:combatTalentWeaponDamage(t, 0.4, 1.6) end, callbackOnMove = function(self, t, moved, force, ox, oy) local cooldown = self.talents_cd[t.id] or 0 @@ -110,7 +110,7 @@ newTalent { range = 0, radius = archery_range, cooldown = 7, - stamina = 40, + stamina = 45, target = function(self, t) return { type = "cone", @@ -123,11 +123,11 @@ newTalent { end, on_pre_use = function(self, t, silent) return sling_equipped(self, silent) end, damage_multiplier = function(self, t) - return self:combatTalentWeaponDamage(t, 0.8, 1.0) + return self:combatTalentWeaponDamage(t, 0.4, 1) end, -- Maximum number of shots fired. limit_shots = function(self, t) - return math.floor(4 + self:getTalentLevel(t)) + return math.floor(6 + self:getTalentLevel(t)) end, action = function(self, t) -- Get list of possible targets, possibly doubled. @@ -156,12 +156,12 @@ newTalent { for i = 1, math.min(limit_shots, #targets) do local target = targets[i] game.target.forced = {target.x, target.y, target} - local targets = self:archeryAcquireTargets(nil, {one_shot=true, no_energy = fired}) + local targets = self:archeryAcquireTargets({type = "hit", speed = 200}, {one_shot=true, no_energy = fired}) if targets then local params = table.clone(shot_params_base) local target = targets.dual and targets.main[1] or targets[1] params.phase_target = game.level.map(target.x, target.y, game.level.map.ACTOR) - self:archeryShoot(targets, t, nil, params) + self:archeryShoot(targets, t, {type = "hit", speed = 200}, params) fired = true else -- If no target that means we're out of ammo. @@ -179,6 +179,8 @@ newTalent { end, } +-- The cost on this is extreme because its a completely ridiculous talent +-- We don't have any other talents like this, really, that are incredibly hard to use for much of anything until late. Should be interesting. newTalent { short_name = "SKIRMISHER_BOMBARDMENT", name = "Bombardment", @@ -190,16 +192,16 @@ newTalent { tactical = { BUFF = 2 }, on_pre_use = function(self, t, silent) return sling_equipped(self, silent) end, cooldown = function(self, t) - return math.max(0, math.floor(15 - self:getTalentLevel(t))) + return 10 end, bullet_count = function(self, t) - return 2 + return 3 end, shot_stamina = function(self, t) return 25 * (1 + self:combatFatigue() * 0.01) end, damage_multiplier = function(self, t) - return self:combatTalentWeaponDamage(t, 0.6, 1.0) + return self:combatTalentWeaponDamage(t, 0.1, 0.6) end, activate = function(self, t) return {} end, deactivate = function(self, t, p) return true end, diff --git a/game/modules/tome/data/talents/techniques/strength-of-the-berserker.lua b/game/modules/tome/data/talents/techniques/strength-of-the-berserker.lua index b20bfe5c747128924db2a41a8ca0e7e8af2f023c..5de1bee810820f2f4455814944b2c0792b205850 100644 --- a/game/modules/tome/data/talents/techniques/strength-of-the-berserker.lua +++ b/game/modules/tome/data/talents/techniques/strength-of-the-berserker.lua @@ -73,7 +73,7 @@ newTalent{ getImmune = function(self, t) return self:combatTalentLimit(t, 1, 0.17, 0.5) end, hasFoes = function(self) for i = 1, #self.fov.actors_dist do - act = self.fov.actors_dist[i] + local act = self.fov.actors_dist[i] if act and self:reactionToward(act) < 0 and self:canSee(act) then return true end end return false diff --git a/game/modules/tome/data/talents/techniques/unarmed-discipline.lua b/game/modules/tome/data/talents/techniques/unarmed-discipline.lua index ee1d536ba82888435fc1778615adab057107d3ab..61293b9d3dd6de27051dbf33fa16f43cc798da8f 100644 --- a/game/modules/tome/data/talents/techniques/unarmed-discipline.lua +++ b/game/modules/tome/data/talents/techniques/unarmed-discipline.lua @@ -18,6 +18,7 @@ -- darkgod@te4.org -- We don't have to worry much about this vs. players since it requires combo points to be really effective and the AI isn't very bright +-- I lied, letting the AI use this is a terrible idea newTalent{ name = "Combination Kick", type = {"technique/unarmed-discipline", 1}, @@ -50,9 +51,7 @@ newTalent{ if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end -- breaks active grapples if the target is not grappled - if target:isGrappled(self) then - grappled = true - else + if not target:isGrappled(self) then self:breakGrapples() end @@ -81,8 +80,8 @@ newTalent{ info = function(self, t) local damage = t.getDamage(self, t) * 100 return ([[Unleash a flurry of disruptive kicks at your target's vulnerable areas. For each combo point you attack for %d%% weapon damage and deactivate one physical sustain. - At talent level 3 Magical sustains will also be effected. - At talent level 5 Mental sustains will also be effected.]]) + At talent level 3 #DARK_ORCHID#Magical#LAST# sustains will also be effected. + At talent level 5 #YELLOW#Mental#LAST# sustains will also be effected.]]) :format(damage) end, } @@ -143,32 +142,50 @@ newTalent{ } newTalent{ - name = "Breath Control", + name = "Tempo", type = {"technique/unarmed-discipline", 3}, + short_name = "BREATH_CONTROL", require = techs_dex_req3, mode = "sustained", points = 5, cooldown = 30, sustain_stamina = 15, tactical = { BUFF = 1, STAMINA = 2 }, - getSpeed = function(self, t) return 0.1 end, - getStamina = function(self, t) return self:combatTalentScale(t, 2, 7.5, 0.75) end, - activate = function(self, t) + getStamina = function(self, t) return 1 end, + getDamage = function(self, t) return math.min(10, math.floor(self:combatTalentScale(t, 1, 4))) end, + getDefense = function(self, t) return math.floor(self:combatTalentScale(t, 1, 8)) end, + getResist = function(self, t) return 20 end, + activate = function(self, t) return { - speed = self:addTemporaryValue("global_speed_add", -t.getSpeed(self, t)), - stamina = self:addTemporaryValue("stamina_regen", t.getStamina(self, t)), + } end, deactivate = function(self, t, p) - self:removeTemporaryValue("global_speed_add", p.speed) - self:removeTemporaryValue("stamina_regen", p.stamina) + return true + end, + callbackOnMeleeAttack = function(self, t, target, hitted, crit, weapon, damtype, mult, dam) + if not hitted or self.turn_procs.tempo or not (self:reactionToward(target) < 0) then return end + self.turn_procs.tempo = true + + self:setEffect(target.EFF_RELENTLESS_TEMPO, 2, { + stamina = t.getStamina(self, t), + damage = t.getDamage(self, t), + defense = t.getDefense(self, t), + resist = t.getResist(self, t) + }) return true end, info = function(self, t) - local speed = t.getSpeed(self, t) local stamina = t.getStamina(self, t) - return ([[You focus your breathing, increasing stamina regeneration by %0.2f per turn at the cost of %d%% global speed.]]): - format(stamina, speed * 100) + local damage = t.getDamage(self, t) + local resistance = t.getResist(self, t) + local defense = t.getDefense(self, t) + + return ([[Your years of fighting have trained you for sustained engagements. Each turn you attack at least once you gain %d Stamina Regeneration, %d Defense, and %d%% Damage Increase. + This effect lasts 2 turns and stacks up to 5 times. + At talent level 3 you gain %d%% All Resistance upon reaching 5 stacks. + ]]): + format(stamina, defense, damage, resistance ) -- end, } diff --git a/game/modules/tome/data/talents/techniques/unarmed-training.lua b/game/modules/tome/data/talents/techniques/unarmed-training.lua index 25bcecf6d17ad6e8f1d3cea63dc4b0282b19128f..f613554f842ae1cb88797d19f4026f27adab9f51 100644 --- a/game/modules/tome/data/talents/techniques/unarmed-training.lua +++ b/game/modules/tome/data/talents/techniques/unarmed-training.lua @@ -73,27 +73,30 @@ newTalent{ end, } +-- Not thoroughly tested yet newTalent{ name = "Unified Body", type = {"technique/unarmed-training", 2}, require = techs_cun_req2, - mode = "sustained", + mode = "passive", points = 5, sustain_stamina = 20, cooldown = 18, tactical = { BUFF = 2 }, + last_update = 0, getStr = function(self, t) return math.ceil(self:combatTalentScale(t, 1.5, 7.5, 0.75) + self:combatTalentStatDamage(t, "cun", 2, 10)) end, getCon = function(self, t) return math.ceil(self:combatTalentScale(t, 1.5, 7.5, 0.75) + self:combatTalentStatDamage(t, "dex", 5, 25)) end, - activate = function(self, t) - return { - stat1 = self:addTemporaryValue("inc_stats", {[self.STAT_CON] = t.getCon(self, t)}), - stat2 = self:addTemporaryValue("inc_stats", {[self.STAT_STR] = t.getStr(self, t)}), - } + + passives = function(self, t, tmptable) + self:talentTemporaryValue(tmptable, "inc_stats", {[self.STAT_CON] = t.getCon(self, t)}) + self:talentTemporaryValue(tmptable, "inc_stats", {[self.STAT_STR] = t.getStr(self, t)}) end, - deactivate = function(self, t, p) - self:removeTemporaryValue("inc_stats", p.stat1) - self:removeTemporaryValue("inc_stats", p.stat2) - return true + callbackOnStatChange = function(self, t, stat, v) + if self.turn_procs.unified_body then return end + if stat == self.STAT_DEX or stat == self.STAT_CUN then + self.turn_procs.unified_body = true + self:updateTalentPassives(t) + end end, info = function(self, t) return ([[Your mastery of unarmed combat unifies your body. Increases your Strength by %d based on Cunning and your Constitution by %d based on Dexterity.]]):format(t.getStr(self, t), t.getCon(self, t)) @@ -127,7 +130,7 @@ newTalent{ no_energy = true, tactical = { BUFF = 2 }, getDefensePct = function(self, t) - return self:combatTalentScale(t, 0.15, 0.9) -- God scaling this is weird + return self:combatTalentScale(t, 0.15, 0.8) -- God scaling this is weird end, getDamageReduction = function(self, t) return math.min(0.8, t.getDefensePct(self, t) * self:combatDefense() / 100) @@ -151,7 +154,7 @@ newTalent{ return cb.value end, info = function(self, t) - return ([[Your understanding of physiology allows you to apply your reflexes in new ways. Whenever you receive damage greater than %d%% of your maximum life you reduce that damage by %d%% based on your defense.]]): + return ([[Your understanding of physiology allows you to apply your reflexes in new ways. Whenever you would receive damage greater than %d%% of your maximum life you reduce that damage by %d%% based on your defense.]]): format(t.getDamagePct(self, t)*100, t.getDamageReduction(self, t)*100 ) end, } diff --git a/game/modules/tome/data/talents/techniques/weaponshield.lua b/game/modules/tome/data/talents/techniques/weaponshield.lua index e265579231b30080f49912c5d7904cff214b1e4f..53a916fcf3ad1b07d86506b08b59e6632d3ee1a4 100644 --- a/game/modules/tome/data/talents/techniques/weaponshield.lua +++ b/game/modules/tome/data/talents/techniques/weaponshield.lua @@ -95,7 +95,7 @@ newTalent{ require = techs_req3, points = 5, random_ego = "attack", - cooldown = 10, + cooldown = 15, stamina = 15, requires_target = true, getShieldDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.1, 0.8, self:getTalentLevel(self.T_SHIELD_EXPERTISE)) end, diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua index a2a4b044e304487420bcf750668482b961773c7b..79ce8a42327ca62f63dda4003d19e7c4c045fe14 100644 --- a/game/modules/tome/data/timed_effects/magical.lua +++ b/game/modules/tome/data/timed_effects/magical.lua @@ -47,6 +47,39 @@ newEffect{ end, } +-- Use a word other than disease because diseases are associated with damage +-- Add dummy power/dam parameters to try to stay in line with other diseases for subtype checks +newEffect{ + name = "ITEM_BLIGHT_ILLNESS", image = "talents/decrepitude_disease.png", + desc = "Illness", + long_desc = function(self, eff) return ("The target is infected by a disease, reducing its dexterity, strength, and constitution by %d."):format(eff.reduce) end, + type = "magical", + subtype = {disease=true, blight=true}, + status = "detrimental", + parameters = {reduce = 1, dam = 0, power = 0}, + on_gain = function(self, err) return "#Target# is afflicted by a crippling illness!" end, + on_lose = function(self, err) return "#Target# is free from the illness." end, + -- Damage each turn + --[[ Reverse stats on purify? + on_timeout = function(self, eff) + if self:attr("purify_disease") then self:heal(eff.dam, eff.src) + else if eff.dam > 0 then DamageType:get(DamageType.BLIGHT).projector(eff.src, self.x, self.y, DamageType.BLIGHT, eff.dam, {from_disease=true}) + end end + end, + --]] + activate = function(self, eff) + eff.tmpid = self:addTemporaryValue("inc_stats", { + [Stats.STAT_DEX] = -eff.reduce, + [Stats.STAT_STR] = -eff.reduce, + [Stats.STAT_CON] = -eff.reduce, + }) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("inc_stats", eff.tmpid) + end, +} + + newEffect{ name = "ITEM_ACID_CORRODE", image = "talents/acidic_skin.png", desc = "Armor Corroded", @@ -122,7 +155,7 @@ newEffect{ desc = "Stoned", long_desc = function(self, eff) return "The target has been turned to stone, making it subject to shattering but improving physical(+20%), fire(+80%) and lightning(+50%) resistances." end, type = "magical", - subtype = { earth=true, stone=true}, + subtype = { earth=true, stone=true, stun = true}, status = "detrimental", parameters = {}, on_gain = function(self, err) return "#Target# turns to stone!", "+Stoned" end, @@ -135,6 +168,9 @@ newEffect{ [DamageType.LIGHTNING]=50, }) end, + on_timeout = function(self, eff) + if eff.dur > 7 then eff.dur = 7 end -- instakilling players is dumb and this is still lethal at 7s + end, deactivate = function(self, eff) self:removeTemporaryValue("stoned", eff.tmpid) self:removeTemporaryValue("resists", eff.resistsid) @@ -1947,6 +1983,21 @@ newEffect{ eff.resid= self:addTemporaryValue("resists", {all=eff.resists}) eff.durid = self:addTemporaryValue("reduce_detrimental_status_effects_time", eff.effect_reduction) eff.particle = self:addParticles(Particles.new("phantasm_shield", 1)) + end, + on_merge = function(self, old_eff, new_eff) + old_eff.defense = math.min(50, math.max(old_eff.defense, new_eff.defense)) or 0 + old_eff.resists = math.min(40, math.max(old_eff.resists, new_eff.resists)) or 0 + old_eff.effect_reduction = math.min(60, math.max(old_eff.effect_reduction, new_eff.effect_reduction)) or 0 + + self:removeTemporaryValue("combat_def", old_eff.defid) + self:removeTemporaryValue("resists", old_eff.resid) + self:removeTemporaryValue("reduce_detrimental_status_effects_time", old_eff.durid) + + eff.defid = self:addTemporaryValue("combat_def", eff.defense) + eff.resid= self:addTemporaryValue("resists", {all=eff.resists}) + eff.durid = self:addTemporaryValue("reduce_detrimental_status_effects_time", eff.effect_reduction) + + end, deactivate = function(self, eff) self:removeTemporaryValue("combat_def", eff.defid) @@ -2545,9 +2596,9 @@ newEffect{ newEffect{ name = "SUNCLOAK", image = "talents/suncloak.png", desc = "Suncloak", - long_desc = function(self, eff) return ("The target is protected by the sun, increasing their spell casting speed by 30%%, reducing spell cooldowns by 30%%, and preventing damage over %d%% of your maximum life from a single hit."):format(eff.cap) end, + long_desc = function(self, eff) return ("The target is protected by the sun, increasing their spell casting speed by %d%%, reducing spell cooldowns by %d%%, and preventing damage over %d%% of your maximum life from a single hit."):format(eff.haste, eff.haste, eff.cap) end, type = "magical", - subtype = { sun=true, }, + subtype = { light=true, }, status = "beneficial", parameters = {cap = 1, haste = 0.1, cd = 0.1}, on_gain = function(self, err) return "#Target# is energized and protected by the Sun!", "+Suncloak" end, @@ -2568,7 +2619,7 @@ newEffect{ desc = "Mark of Light", long_desc = function(self, eff) return ("The creature that marked the target with light will be healed for all melee attacks against it by %d%%."):format(eff.power) end, type = "magical", - subtype = { sun=true, }, + subtype = { light=true, }, status = "detrimental", parameters = { power = 10 }, on_gain = function(self, err) return "#Target# is marked by light!", "+Mark of Light" end, diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua index d2b628b7f7a412b9d2edb3ef20c93edee1284744..ae4b94fea1e5efe009749abf1b53bf1061a840c6 100644 --- a/game/modules/tome/data/timed_effects/physical.lua +++ b/game/modules/tome/data/timed_effects/physical.lua @@ -38,17 +38,6 @@ newEffect{ on_timeout = function(self, eff) end, activate = function(self, eff) - --[[ Changed method - eff.spell = self.combat_spellpower * eff.pct - eff.mind = self.combat_mindpower * eff.pct - eff.phys = self.combat_dam * eff.pct - - eff.power_str = "Physical: "..eff.phys.."\nSpell: "..eff.spell.."\nMind: "..eff.mind - - self:effectTemporaryValue(eff, "combat_spell", -eff.spell) - self:effectTemporaryValue(eff, "combat_mindpower", -eff.mind) - self:effectTemporaryValue(eff, "combat_dam", -eff.phys) - --]] self:effectTemporaryValue(eff, "scoured", 1) end, deactivate = function(self, eff) @@ -56,6 +45,64 @@ newEffect{ end, } +newEffect{ + name = "RELENTLESS_TEMPO", image = "talents/sunder_mind.png", + desc = "Relentless Tempo", + long_desc = function(self, eff) return ("Attuning to the flow of combat, increasing their combat stats. \nDefense: %d\nAll Damage: %d%%\nStamina Regeneration: %d\n%s"): + format( eff.cur_defense or 0, eff.cur_damage or 0, eff.cur_stamina or 0, eff.stacks >= 5 and "All Resistance: 20%" or "") end, + charges = function(self, eff) return eff.stacks end, + type = "physical", + subtype = { tempo=true }, + status = "beneficial", + on_gain = function(self, err) return "#Target# is gaining tempo.", "+Tempo" end, + on_lose = function(self, err) return "#Target# loses their tempo.", "-Tempo" end, + parameters = { stamina = 0, defense = 0, damage = 0, stacks = 0, resists = 0 }, + on_merge = function(self, old_eff, new_eff) + old_eff.dur =3 + + if old_eff.stacks >= 5 then + if old_eff.resists ~= 20 then + old_eff.resists = 20 + old_eff.resid = self:addTemporaryValue("resists", {all=old_eff.resists}) + end + return old_eff + end + + old_eff.stacks = old_eff.stacks + 1 + + self:removeTemporaryValue("stamina_regen", old_eff.staminaid) + self:removeTemporaryValue("combat_def", old_eff.defenseid) + self:removeTemporaryValue("inc_damage", old_eff.damageid) + + old_eff.cur_stamina = old_eff.cur_stamina + new_eff.stamina + old_eff.cur_defense = old_eff.cur_defense + new_eff.defense + old_eff.cur_damage = old_eff.cur_damage + new_eff.damage + + old_eff.staminaid = self:addTemporaryValue("stamina_regen", old_eff.cur_stamina) + old_eff.defenseid = self:addTemporaryValue("combat_def", old_eff.cur_defense) + old_eff.damageid = self:addTemporaryValue("inc_damage", {all = old_eff.cur_damage}) + + return old_eff + end, + activate = function(self, eff) + eff.stacks = 1 + eff.cur_stamina = eff.stamina + eff.cur_defense = eff.defense + eff.cur_damage = eff.damage + + eff.staminaid = self:addTemporaryValue("stamina_regen", eff.cur_defense) + eff.defenseid = self:addTemporaryValue("combat_def", eff.cur_defense) + eff.damageid = self:addTemporaryValue("inc_damage", {all = eff.cur_damage}) + end, + deactivate = function(self, eff) + self:removeTemporaryValue("stamina_regen", eff.staminaid) + self:removeTemporaryValue("combat_def", eff.defenseid) + self:removeTemporaryValue("inc_damage", eff.damageid) + if eff.resid then self:removeTemporaryValue("resists", eff.resid) end + end, +} + + newEffect{ name = "DELIRIOUS_CONCUSSION", image = "talents/slippery_moss.png", desc = "Concussion", @@ -81,7 +128,7 @@ newEffect{ desc = "Bleeding", long_desc = function(self, eff) return ("Huge cut that bleeds, doing %0.2f physical damage per turn."):format(eff.power) end, type = "physical", - subtype = { wound=true, cut=true }, + subtype = { wound=true, cut=true, bleed=true }, status = "detrimental", parameters = { power=1 }, on_gain = function(self, err) return "#Target# starts to bleed.", "+Bleeds" end, @@ -96,7 +143,7 @@ newEffect{ return old_eff end, activate = function(self, eff) - if eff.src:knowTalent(self.T_BLOODY_BUTCHER) then + if eff.src and eff.src:knowTalent(self.T_BLOODY_BUTCHER) then local t = eff.src:getTalentFromId(eff.src.T_BLOODY_BUTCHER) local resist = math.min(t.getResist(eff.src, t), math.max(0, self:combatGetResist(DamageType.PHYSICAL))) self:effectTemporaryValue(eff, "resists", {[DamageType.PHYSICAL] = -resist}) @@ -112,7 +159,7 @@ newEffect{ desc = "Deep Wound", long_desc = function(self, eff) return ("Huge cut that bleeds, doing %0.2f physical damage per turn and decreasing all heals received by %d%%."):format(eff.power, eff.heal_factor) end, type = "physical", - subtype = { wound=true, cut=true }, + subtype = { wound=true, cut=true, bleed=true }, status = "detrimental", parameters = {power=10, heal_factor=30}, on_gain = function(self, err) return "#Target# starts to bleed.", "+Deep Wounds" end, @@ -1355,26 +1402,30 @@ newEffect{ newEffect{ name = "Recovery", desc = "Recovery", - long_desc = function(self, eff) return ("The target is recovering %d life each turn and its healing modifier has been increased by %d%%."):format(eff.regen, eff.heal_mod) end, + long_desc = function(self, eff) return ("The target is recovering %d life each turn."):format(math.min(100, eff.pct * self.max_life)) end, type = "physical", subtype = { heal=true }, status = "beneficial", - parameters = { power=10 }, + parameters = { power=10, pct = 0.01 }, on_gain = function(self, err) return "#Target# is recovering from the damage!", "+Recovery" end, on_lose = function(self, err) return "#Target# has finished recovering.", "-Recovery" end, activate = function(self, eff) - eff.regenid = self:addTemporaryValue("life_regen", eff.regen) - eff.healid = self:addTemporaryValue("healing_factor", eff.heal_mod / 100) + --eff.regenid = self:addTemporaryValue("life_regen", eff.regen) + --eff.healid = self:addTemporaryValue("healing_factor", eff.heal_mod / 100) if core.shader.active(4) then eff.particle1 = self:addParticles(Particles.new("shader_shield", 1, {toback=true, size_factor=1.5, y=-0.3, img="healarcane"}, {type="healing", time_factor=4000, noup=2.0, beamColor1={0xff/255, 0x22/255, 0x22/255, 1}, beamColor2={0xff/255, 0x60/255, 0x60/255, 1}, circleColor={0,0,0,0}, beamsCount=8})) eff.particle2 = self:addParticles(Particles.new("shader_shield", 1, {toback=false, size_factor=1.5, y=-0.3, img="healarcane"}, {type="healing", time_factor=4000, noup=1.0, beamColor1={0xff/255, 0x22/255, 0x22/255, 1}, beamColor2={0xff/255, 0x60/255, 0x60/255, 1}, circleColor={0,0,0,0}, beamsCount=8})) end end, + on_timeout = function(self, eff) + local heal = math.min(100, self.max_life * eff.pct) + self:heal(heal, src) + end, deactivate = function(self, eff) self:removeParticles(eff.particle1) self:removeParticles(eff.particle2) - self:removeTemporaryValue("life_regen", eff.regenid) - self:removeTemporaryValue("healing_factor", eff.healid) + --self:removeTemporaryValue("life_regen", eff.regenid) + --self:removeTemporaryValue("healing_factor", eff.healid) end, } diff --git a/game/modules/tome/data/zones/ritch-tunnels/npcs.lua b/game/modules/tome/data/zones/ritch-tunnels/npcs.lua index 5fa9bc6ea176f56b9d29c5b64d62458f8124f8c5..13723302e6e542e0122ba94a473d8fef86bb0299 100644 --- a/game/modules/tome/data/zones/ritch-tunnels/npcs.lua +++ b/game/modules/tome/data/zones/ritch-tunnels/npcs.lua @@ -94,6 +94,7 @@ newEntity{ base = "BASE_NPC_RITCH_REL", ai_state = { ai_move="move_complex", talent_in=1, }, } +-- Screw it just die, die, die newEntity{ base = "BASE_NPC_RITCH_REL", define_as = "HIVE_MOTHER", unique = true, name = "Ritch Great Hive Mother", image = "npc/insect_ritch_ritch_hive_mother.png", @@ -119,7 +120,7 @@ newEntity{ base = "BASE_NPC_RITCH_REL", define_as = "HIVE_MOTHER", body = { INVEN = 10, BODY=1 }, - inc_damage = {all=-30}, + inc_damage = {all=-70}, resolvers.drops{chance=100, nb=1, {defined="FLAMEWROUGHT", random_art_replace={chance=75}}, }, resolvers.drops{chance=100, nb=3, {tome_drops="boss"} }, diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua index 18e2afda15240b9353bc03662bdc7e87814f92d1..6f18c25dc551bdad787524ec8e9795e92be7ead6 100644 --- a/game/modules/tome/dialogs/CharacterSheet.lua +++ b/game/modules/tome/dialogs/CharacterSheet.lua @@ -326,6 +326,9 @@ function _M:drawDialog(kind, actor_to_compare) if player:attr("forbid_arcane") then s:drawColorStringBlended(self.font, "#ORCHID#Zigur follower", w, h, 255, 255, 255, true) h = h + self.font_h end + if player:attr("blood_life") then + s:drawColorStringBlended(self.font, "#DARK_RED#Blood of Life", w, h, 255, 255, 255, true) h = h + self.font_h + end h = h + self.font_h self:mouseTooltip(self.TOOLTIP_LEVEL, s:drawColorStringBlended(self.font, "Level: #00ff00#"..player.level, w, h, 255, 255, 255, true)) h = h + self.font_h @@ -520,10 +523,10 @@ function _M:drawDialog(kind, actor_to_compare) print_stat(self.actor.STAT_STR, ("%-12s"):format(Stats.stats_def[self.actor.STAT_STR].name:capitalize()), self.TOOLTIP_STR) print_stat(self.actor.STAT_DEX, ("%-12s"):format(Stats.stats_def[self.actor.STAT_DEX].name:capitalize()), self.TOOLTIP_DEX) + print_stat(self.actor.STAT_CON, ("%-12s"):format(Stats.stats_def[self.actor.STAT_CON].name:capitalize()), self.TOOLTIP_CON) print_stat(self.actor.STAT_MAG, ("%-12s"):format(Stats.stats_def[self.actor.STAT_MAG].name:capitalize()), self.TOOLTIP_MAG) print_stat(self.actor.STAT_WIL, ("%-12s"):format(Stats.stats_def[self.actor.STAT_WIL].name:capitalize()), self.TOOLTIP_WIL) print_stat(self.actor.STAT_CUN, ("%-12s"):format(Stats.stats_def[self.actor.STAT_CUN].name:capitalize()), self.TOOLTIP_CUN) - print_stat(self.actor.STAT_CON, ("%-12s"):format(Stats.stats_def[self.actor.STAT_CON].name:capitalize()), self.TOOLTIP_CON) h = h + self.font_h local nb_inscriptions = 0 @@ -707,7 +710,7 @@ function _M:drawDialog(kind, actor_to_compare) end local inc_damages = {} - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player:combatHasDamageIncrease(DamageType[t.type]) then inc_damages[t] = inc_damages[t] or {} inc_damages[t][1] = player:combatGetDamageIncrease(DamageType[t.type]) @@ -774,7 +777,7 @@ function _M:drawDialog(kind, actor_to_compare) end local resists_pens = {} - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player.resists_pen[DamageType[t.type]] and player.resists_pen[DamageType[t.type]] ~= 0 then resists_pens[t] = resists_pens[t] or {} resists_pens[t][1] = player.resists_pen[DamageType[t.type]] @@ -848,7 +851,7 @@ function _M:drawDialog(kind, actor_to_compare) s:drawColorStringBlended(self.font, "#LIGHT_BLUE#Resistances base / cap:", w, h, 255, 255, 255, true) h = h + self.font_h local resists = {} - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player.resists[DamageType[t.type]] and player.resists[DamageType[t.type]] ~= 0 then resists[t] = resists[t] or {} resists[t][1] = player:combatGetResist(DamageType[t.type]) @@ -868,7 +871,7 @@ function _M:drawDialog(kind, actor_to_compare) end self:mouseTooltip(self.TOOLTIP_RESIST_ALL, s:drawColorStringBlended(self.font, ("%-10s: #00ff00#%3d%% / %d%%%s"):format("All", player.resists.all, player.resists_cap.all or 0, res_text), w, h, 255, 255, 255, true)) h = h + self.font_h end - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player.resists[DamageType[t.type]] and player.resists[DamageType[t.type]] ~= 0 then self:mouseTooltip(self.TOOLTIP_RESIST, s:drawColorStringBlended(self.font, ("%s%-10s#LAST#: #00ff00#%3d%% / %d%%"):format((t.text_color or "#WHITE#"), t.name:capitalize(), player:combatGetResist(DamageType[t.type]), (player.resists_cap[DamageType[t.type]] or 0) + (player.resists_cap.all or 0)), w, h, 255, 255, 255, true)) h = h + self.font_h end @@ -890,7 +893,7 @@ function _M:drawDialog(kind, actor_to_compare) end local damage_affinitys = {} - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player.damage_affinity[DamageType[t.type]] and player.damage_affinity[DamageType[t.type]] ~= 0 then damage_affinitys[t] = damage_affinitys[t] or {} damage_affinitys[t][1] = player.damage_affinity[DamageType[t.type]] @@ -944,11 +947,17 @@ function _M:drawDialog(kind, actor_to_compare) s:drawColorStringBlended(self.font, "#LIGHT_BLUE#Damage when hit:", w, h, 255, 255, 255, true) h = h + self.font_h - for i, t in ipairs(DamageType.dam_def) do + for i, t in pairs(DamageType.dam_def) do if player.on_melee_hit[DamageType[t.type]] and player.on_melee_hit[DamageType[t.type]] ~= 0 then local dval = player.on_melee_hit[DamageType[t.type]] - dval = Talents.damDesc(player, DamageType[t.type] ,type(dval) == "number" and dval or dval.dam) - self:mouseTooltip(self.TOOLTIP_ON_HIT_DAMAGE, s:drawColorStringBlended(self.font, ("%s%-10s#LAST#: #00ff00#%.1f"):format((t.text_color or "#WHITE#"), t.name:capitalize(), dval), w, h, 255, 255, 255, true)) h = h + self.font_h + if t.tdesc then + dval = t.tdesc(dval) + self:mouseTooltip(self.TOOLTIP_ON_HIT_DAMAGE, s:drawColorStringBlended(self.font, ("%s"):format(dval), w, h, 255, 255, 255, true)) h = h + self.font_h + else + dval = Talents.damDesc(player, DamageType[t.type] ,type(dval) == "number" and dval or dval.dam) + self:mouseTooltip(self.TOOLTIP_ON_HIT_DAMAGE, s:drawColorStringBlended(self.font, ("%s%-10s#LAST#: #00ff00#%.1f"):format((t.text_color or "#WHITE#"), t.name:capitalize(), dval), w, h, 255, 255, 255, true)) h = h + self.font_h + + end end end diff --git a/game/modules/tome/dialogs/GameOptions.lua b/game/modules/tome/dialogs/GameOptions.lua index 28bb3c2341fbc0700a26c04792fa14a8b66bd5b8..dae63742cb0a59a9c897e53c442b66f14c834b82 100644 --- a/game/modules/tome/dialogs/GameOptions.lua +++ b/game/modules/tome/dialogs/GameOptions.lua @@ -275,6 +275,26 @@ function _M:generateListUi() self.c_list:drawItem(item) end,} + local zone = Textzone.new{width=self.c_desc.w, height=self.c_desc.h, text=string.toTString"If disabled you will not get a fullscreen notification of stun/daze effects. Beware.#WHITE#"} + list[#list+1] = { zone=zone, name=string.toTString"#GOLD##{bold}#Fullscreen stun/daze notification.#WHITE##{normal}#", status=function(item) + return tostring(config.settings.tome.fullscreen_stun and "enabled" or "disabled") + end, fct=function(item) + config.settings.tome.fullscreen_stun = not config.settings.tome.fullscreen_stun + game:saveSettings("tome.fullscreen_stun", ("tome.fullscreen_stun = %s\n"):format(tostring(config.settings.tome.fullscreen_stun))) + self.c_list:drawItem(item) + if game.player.updateMainShader then game.player:updateMainShader() end + end,} + + local zone = Textzone.new{width=self.c_desc.w, height=self.c_desc.h, text=string.toTString"If disabled you will not get a fullscreen notification of confusion effects. Beware.#WHITE#"} + list[#list+1] = { zone=zone, name=string.toTString"#GOLD##{bold}#Fullscreen confusion notification.#WHITE##{normal}#", status=function(item) + return tostring(config.settings.tome.fullscreen_confusion and "enabled" or "disabled") + end, fct=function(item) + config.settings.tome.fullscreen_confusion = not config.settings.tome.fullscreen_confusion + game:saveSettings("tome.fullscreen_confusion", ("tome.fullscreen_confusion = %s\n"):format(tostring(config.settings.tome.fullscreen_confusion))) + self.c_list:drawItem(item) + if game.player.updateMainShader then game.player:updateMainShader() end + end,} + self.list = list end diff --git a/game/modules/tome/dialogs/ShowEquipInven.lua b/game/modules/tome/dialogs/ShowEquipInven.lua index b913a1819f5cdff3fc1370aeb61d8cb2e0920eaa..3452c734703ef4ccb91019f0e837b670c94cf443 100644 --- a/game/modules/tome/dialogs/ShowEquipInven.lua +++ b/game/modules/tome/dialogs/ShowEquipInven.lua @@ -153,12 +153,22 @@ function _M:init(title, equip_actor, filter, action, on_select, inven_actor) } self.key:addBinds{ ACCEPT = function() if self.focus_ui and self.focus_ui.ui == self.c_inven then self:use(self.c_inven.c_inven.list[self.c_inven.c_inven.sel]) end end, - EXIT = function() game.tooltip.locked = false game:unregisterDialog(self) end, + EXIT = function() + if self.c_inven.c_inven.scrollbar then + self.equip_actor.inv_scroll = self.c_inven.c_inven.scrollbar.pos or 0 + end + game.tooltip.locked = false + game:unregisterDialog(self) + end, MOVE_UP = function() game.log("up") if game.tooltip.locked then game.tooltip.container.scroll_inertia = math.min(game.tooltip.container.scroll_inertia, 0) - 5 end end, MOVE_DOWN = function() if game.tooltip.locked then game.tooltip.container.scroll_inertia = math.max(game.tooltip.container.scroll_inertia, 0) + 5 end end, LOCK_TOOLTIP = lock_tooltip, LOCK_TOOLTIP_COMPARE = lock_tooltip, + SCREENSHOT = function() if type(game) == "table" and game.key then game.key:triggerVirtual("SCREENSHOT") end end, } + if self.equip_actor.inv_scroll and self.c_inven.c_inven.scrollbar then + self.c_inven.c_inven.scrollbar.pos = util.bound(self.equip_actor.inv_scroll, 0, self.c_inven.c_inven.scrollbar.max) + end end function _M:switchSets(which) @@ -203,6 +213,9 @@ function _M:select(item, force) end function _M:use(item, button, event) + if self.c_inven.c_inven.scrollbar then + self.equip_actor.inv_scroll = self.c_inven.c_inven.scrollbar.pos or 0 + end if item then if self.action(item.object, item.inven, item.item, button, event) then game:unregisterDialog(self) @@ -228,6 +241,9 @@ function _M:updateTitle(title) g = util.lerp(green.g, red.g, v), b = util.lerp(green.b, red.b, v), } + if self.equip_actor.inv_scroll and self.c_inven.c_inven.scrollbar then + self.c_inven.c_inven.scrollbar.pos = util.bound(self.equip_actor.inv_scroll, 0, self.c_inven.c_inven.scrollbar.max) + end end function _M:onDrag(item) diff --git a/game/modules/tome/dialogs/ShowStore.lua b/game/modules/tome/dialogs/ShowStore.lua index 4af0d3e61d8db0c8e1f45099cad3d9b22ef04607..f968db31e2e796e0a162b4448fb4ec73bd442ab8 100644 --- a/game/modules/tome/dialogs/ShowStore.lua +++ b/game/modules/tome/dialogs/ShowStore.lua @@ -119,7 +119,15 @@ function _M:init(title, store_inven, actor_inven, store_filter, actor_filter, ac [{"_TAB","shift"}] = function() self:moveFocus(1) end, } self.key:addBinds{ - EXIT = function() game:unregisterDialog(self) end, + EXIT = function() + if self.c_inven.c_inven.scrollbar then + self.actor_actor.inv_scroll = self.c_inven.c_inven.scrollbar.pos or 0 + end + if self.c_store.c_inven.scrollbar then + self.actor_actor.store_scroll = self.c_store.c_inven.scrollbar.pos or 0 + end + game:unregisterDialog(self) + end, } -- Add tooltips @@ -147,6 +155,12 @@ function _M:init(title, store_inven, actor_inven, store_filter, actor_filter, ac self.prev_ctrl = ctrl end end + if self.actor_actor.inv_scroll and self.c_inven.c_inven.scrollbar then + self.c_inven.c_inven.scrollbar.pos = util.bound(self.actor_actor.inv_scroll, 0, self.c_inven.c_inven.scrollbar.max or 0) + end + if self.actor_actor.store_scroll and self.c_store.c_inven.scrollbar then + self.c_store.c_inven.scrollbar.pos = util.bound(self.actor_actor.store_scroll, 0, self.c_store.c_inven.scrollbar.max or 0) + end end function _M:on_register() @@ -160,6 +174,12 @@ end function _M:updateStore() self:generateList() self:updateTitle(self:getStoreTitle()) + if self.actor_actor.inv_scroll and self.c_inven.c_inven.scrollbar then + self.c_inven.c_inven.scrollbar.pos = util.bound(self.actor_actor.inv_scroll, 0, self.c_inven.c_inven.scrollbar.max or 0) + end + if self.actor_actor.store_scroll and self.c_store.c_inven.scrollbar then + self.c_store.c_inven.scrollbar.pos = util.bound(self.actor_actor.store_scroll, 0, self.c_store.c_inven.scrollbar.max or 0) + end end function _M:select(item, force) @@ -169,6 +189,8 @@ function _M:select(item, force) end function _M:use(item, force) + self.actor_actor.inv_scroll = self.c_inven.c_inven.scrollbar and self.c_inven.c_inven.scrollbar.pos or 0 + self.actor_actor.store_scroll = self.c_store.c_inven.scrollbar and self.c_store.c_inven.scrollbar.pos or 0 if item and item.object then if self.focus_ui and self.focus_ui.ui == self.c_store then if util.getval(self.allow_buy, item.object, item.item) then diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua index bc44cf70ef96610f2baec214cc5a828b2c6f2460..9e79676c20041846a485ea2ffade00c9208608b9 100644 --- a/game/modules/tome/load.lua +++ b/game/modules/tome/load.lua @@ -59,6 +59,8 @@ if type(config.settings.tome.immediate_melee_keys) == "nil" then config.settings if type(config.settings.tome.immediate_melee_keys_auto) == "nil" then config.settings.tome.immediate_melee_keys_auto = true end if type(config.settings.tome.allow_online_events) == "nil" then config.settings.tome.allow_online_events = true end if type(config.settings.tome.small_frame_side) == "nil" then config.settings.tome.small_frame_side = true end +if type(config.settings.tome.fullscreen_stun) == "nil" then config.settings.tome.fullscreen_stun = true end +if type(config.settings.tome.fullscreen_confusion) == "nil" then config.settings.tome.fullscreen_confusion = true end if not config.settings.tome.fonts then config.settings.tome.fonts = {type="fantasy", size="normal"} end if not config.settings.tome.ui_theme2 then config.settings.tome.ui_theme2 = "metal" end if not config.settings.tome.uiset_mode then config.settings.tome.uiset_mode = "Minimalist" end diff --git a/game/thirdparty/licenses/CEF3.txt b/game/thirdparty/licenses/CEF3.txt new file mode 100644 index 0000000000000000000000000000000000000000..a5d84adabad0579d18940bee7315203bd4ce743e --- /dev/null +++ b/game/thirdparty/licenses/CEF3.txt @@ -0,0 +1,29 @@ +// Copyright (c) 2008-2013 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-2009 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/game/thirdparty/licenses/LuaJIT.txt b/game/thirdparty/licenses/LuaJIT.txt new file mode 100644 index 0000000000000000000000000000000000000000..83ce94daee972200f5da0bb105b37100be034a67 --- /dev/null +++ b/game/thirdparty/licenses/LuaJIT.txt @@ -0,0 +1,56 @@ +=============================================================================== +LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/ + +Copyright (C) 2005-2013 Mike Pall. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +[ MIT license: http://www.opensource.org/licenses/mit-license.php ] + +=============================================================================== +[ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ] + +Copyright (C) 1994-2012 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== +[ LuaJIT includes code from dlmalloc, which has this license statement: ] + +This is a version (aka dlmalloc) of malloc/free/realloc written by +Doug Lea and released to the public domain, as explained at +http://creativecommons.org/licenses/publicdomain + +=============================================================================== diff --git a/game/thirdparty/licenses/SDL.txt b/game/thirdparty/licenses/SDL.txt new file mode 100644 index 0000000000000000000000000000000000000000..2be412ae149d3e029bec9ffb9f7392c9eff58183 --- /dev/null +++ b/game/thirdparty/licenses/SDL.txt @@ -0,0 +1,18 @@ +Simple DirectMedia Layer +Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org> + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/game/thirdparty/licenses/SDL_image.txt b/game/thirdparty/licenses/SDL_image.txt new file mode 100644 index 0000000000000000000000000000000000000000..1a86597ed5bf18df215ba3999946ecd21f31783a --- /dev/null +++ b/game/thirdparty/licenses/SDL_image.txt @@ -0,0 +1,18 @@ + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/game/thirdparty/licenses/SDL_ttf.txt b/game/thirdparty/licenses/SDL_ttf.txt new file mode 100644 index 0000000000000000000000000000000000000000..bedb902bf083a65daf87cc7c9911c5f4397480e4 --- /dev/null +++ b/game/thirdparty/licenses/SDL_ttf.txt @@ -0,0 +1,18 @@ + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/game/thirdparty/licenses/expat.txt b/game/thirdparty/licenses/expat.txt new file mode 100644 index 0000000000000000000000000000000000000000..dcb4506429684b253cc440ca40a109fb6b9253a9 --- /dev/null +++ b/game/thirdparty/licenses/expat.txt @@ -0,0 +1,22 @@ +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + and Clark Cooper +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/game/thirdparty/licenses/freetype.txt b/game/thirdparty/licenses/freetype.txt new file mode 100644 index 0000000000000000000000000000000000000000..5443b5e4efa4f06c0c22bd202880953cbeee92ea --- /dev/null +++ b/game/thirdparty/licenses/freetype.txt @@ -0,0 +1,169 @@ + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright � <year> The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace <year> with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + + +--- end of FTL.TXT --- \ No newline at end of file diff --git a/game/thirdparty/licenses/libogg.txt b/game/thirdparty/licenses/libogg.txt new file mode 100644 index 0000000000000000000000000000000000000000..6111c6c5a6b95057e43d36b7c217b073bf5f9b22 --- /dev/null +++ b/game/thirdparty/licenses/libogg.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002, Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/game/thirdparty/licenses/libpng.txt b/game/thirdparty/licenses/libpng.txt new file mode 100644 index 0000000000000000000000000000000000000000..94f5e9500af29fc07df92bd9d4e3237090cc60fa --- /dev/null +++ b/game/thirdparty/licenses/libpng.txt @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are +Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +March 6, 2014 diff --git a/game/thirdparty/licenses/libvorbis.txt b/game/thirdparty/licenses/libvorbis.txt new file mode 100644 index 0000000000000000000000000000000000000000..28de72a9705bfa6b2aa777c608feade0ef6bcb26 --- /dev/null +++ b/game/thirdparty/licenses/libvorbis.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002-2008 Xiph.org Foundation + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiph.org Foundation nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/game/thirdparty/licenses/lpeg.txt b/game/thirdparty/licenses/lpeg.txt new file mode 100644 index 0000000000000000000000000000000000000000..4c49c2c01a48a9618cedcc2f1e3dcbc0387e69c2 --- /dev/null +++ b/game/thirdparty/licenses/lpeg.txt @@ -0,0 +1,7 @@ + Copyright © 2013 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/game/thirdparty/licenses/luabitop.txt b/game/thirdparty/licenses/luabitop.txt new file mode 100644 index 0000000000000000000000000000000000000000..f18a7a9a368bd55a7367af0afdc70ad4c0b98c72 --- /dev/null +++ b/game/thirdparty/licenses/luabitop.txt @@ -0,0 +1 @@ +Lua BitOp is Copyright © 2008-2012 Mike Pall. Lua BitOp is free software, released under the MIT license (same license as the Lua core). \ No newline at end of file diff --git a/game/thirdparty/licenses/luamd5.txt b/game/thirdparty/licenses/luamd5.txt new file mode 100644 index 0000000000000000000000000000000000000000..5bd1790b6a355c6ac512068760fa3d18bb1c2619 --- /dev/null +++ b/game/thirdparty/licenses/luamd5.txt @@ -0,0 +1,7 @@ +Copyright © 2003 PUC-Rio. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/game/thirdparty/licenses/luaprofiler.txt b/game/thirdparty/licenses/luaprofiler.txt new file mode 100644 index 0000000000000000000000000000000000000000..419df0ee1c160fea44fcb1cd769e868f98768c6a --- /dev/null +++ b/game/thirdparty/licenses/luaprofiler.txt @@ -0,0 +1,7 @@ +Copyright (c) 2002-2007 Kepler Project. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/game/thirdparty/licenses/luasocket.txt b/game/thirdparty/licenses/luasocket.txt new file mode 100644 index 0000000000000000000000000000000000000000..b0b53673930a1d8497b094112e159fff7a0f2581 --- /dev/null +++ b/game/thirdparty/licenses/luasocket.txt @@ -0,0 +1,20 @@ +LuaSocket 2.0.2 license +Copyright © 2004-2007 Diego Nehab + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/game/thirdparty/licenses/luazlib.txt b/game/thirdparty/licenses/luazlib.txt new file mode 100644 index 0000000000000000000000000000000000000000..46aeada51cd1a6ac41b624b8d12e9d6d765dd854 --- /dev/null +++ b/game/thirdparty/licenses/luazlib.txt @@ -0,0 +1,24 @@ +* Author : Brian Maher <maherb at brimworks dot com> +* Library : lua_zlib - Lua 5.1 interface to zlib +* +* The MIT License +* +* Copyright (c) 2009 Brian Maher +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. \ No newline at end of file diff --git a/game/thirdparty/licenses/lxp.txt b/game/thirdparty/licenses/lxp.txt new file mode 100644 index 0000000000000000000000000000000000000000..498fd7e27d5a8fb88a2c1babc99f2c71410c9d4e --- /dev/null +++ b/game/thirdparty/licenses/lxp.txt @@ -0,0 +1,7 @@ +Copyright © 2003-2007 The Kepler Project. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/game/thirdparty/licenses/physfs.txt b/game/thirdparty/licenses/physfs.txt new file mode 100644 index 0000000000000000000000000000000000000000..d20c01721081c7034092b21dcf5f5173ec19846a --- /dev/null +++ b/game/thirdparty/licenses/physfs.txt @@ -0,0 +1,22 @@ + + Copyright (c) 2001-2012 Ryan C. Gordon and others. + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from + the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Ryan C. Gordon <icculus@icculus.org> \ No newline at end of file diff --git a/game/thirdparty/licenses/tcod.txt b/game/thirdparty/licenses/tcod.txt new file mode 100644 index 0000000000000000000000000000000000000000..ecff62e4df616421821cd4fec69c3e8d73ce2b35 --- /dev/null +++ b/game/thirdparty/licenses/tcod.txt @@ -0,0 +1,24 @@ +* libtcod 1.5.0 +* Copyright (c) 2008,2009,2010 Jice +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * The name of Jice may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY Jice ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL Jice BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/game/thirdparty/tween.LICENSE b/game/thirdparty/licenses/tween.txt similarity index 100% rename from game/thirdparty/tween.LICENSE rename to game/thirdparty/licenses/tween.txt diff --git a/game/thirdparty/licenses/zlib.txt b/game/thirdparty/licenses/zlib.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ca109b9723907d9f3f555c7e7bd09e46a5c8a14 --- /dev/null +++ b/game/thirdparty/licenses/zlib.txt @@ -0,0 +1,25 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.8, April 28th, 2013 + + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +*/ \ No newline at end of file diff --git a/src/main.c b/src/main.c index ae8e56c224d8a9fa1004e1e414cdf42d356948fb..4f3d3bba853f596d99349009c243fad9e462c120 100644 --- a/src/main.c +++ b/src/main.c @@ -304,7 +304,6 @@ void on_event(SDL_Event *event) lastts = event->text.timestamp; lastc = event->text.text[0]; - printf("<==text event %ld : '%s'\n", (long int)event->text.timestamp, event->text.text); lua_rawgeti(L, LUA_REGISTRYINDEX, current_keyhandler); lua_pushstring(L, "receiveKey"); lua_gettable(L, -2); @@ -1243,6 +1242,7 @@ int main(int argc, char *argv[]) if (!strncmp(arg, "--no-steam", 10)) no_steam = TRUE; if (!strncmp(arg, "--type=zygote", 13)) is_zygote = TRUE; if (!strncmp(arg, "--type=renderer", 15)) is_zygote = TRUE; + if (!strncmp(arg, "--no-sandbox", 12)) is_zygote = TRUE; } #ifdef SELFEXE_WINDOWS diff --git a/src/web-cef3/web-internal.h b/src/web-cef3/web-internal.h index 296653cd1e259e7ae2411c3f375fc9b662b9f244..f306848423569e292eaef85a1aa36796d28d7310 100644 --- a/src/web-cef3/web-internal.h +++ b/src/web-cef3/web-internal.h @@ -1,8 +1,22 @@ /* TE4 - T-Engine 4 - Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicolas Casalini + Copyright (C) 2009 - 2014 Nicolas Casalini - No permission to copy or replicate in any ways. + 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 */ #ifndef __TE4WEB_INTERNAL_H__ diff --git a/src/web-cef3/web-utils.cpp b/src/web-cef3/web-utils.cpp index 263568e25f4a82ad56b1ea141e852ef58289d503..3c3dbcc9f870bec4bb6e153d32d7e92fa9d0c0f9 100644 --- a/src/web-cef3/web-utils.cpp +++ b/src/web-cef3/web-utils.cpp @@ -1,8 +1,22 @@ /* TE4 - T-Engine 4 - Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicolas Casalini + Copyright (C) 2009 - 2014 Nicolas Casalini - No permission to copy or replicate in any ways, awesomium is not gpl so we cant link directly + 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 */ extern "C" { diff --git a/src/web-cef3/web.cpp b/src/web-cef3/web.cpp index 77dcf36288c12ef549877dc61d1d614ae3b816c7..0deeaee9563097adeab64a44d9896f4f18e222a3 100644 --- a/src/web-cef3/web.cpp +++ b/src/web-cef3/web.cpp @@ -1,8 +1,22 @@ /* TE4 - T-Engine 4 - Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicolas Casalini + Copyright (C) 2009 - 2014 Nicolas Casalini - No permission to copy or replicate in any ways. + 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 */ #include <map> @@ -89,6 +103,7 @@ class BrowserClient; class WebViewOpaque { public: + bool crashed; CefRefPtr<RenderHandler> render; CefRefPtr<CefBrowser> browser; CefRefPtr<BrowserClient> view; @@ -105,11 +120,11 @@ class BrowserClient : public CefLoadHandler { std::map<int32, CurrentDownload*> downloads; - WebViewOpaque *opaque; CefRefPtr<CefRenderHandler> m_renderHandler; int handlers; public: + WebViewOpaque *opaque; CefRefPtr<CefBrowser> browser; bool first_load; BrowserClient(WebViewOpaque *opaque, RenderHandler *renderHandler, int handlers) : m_renderHandler(renderHandler) { @@ -158,6 +173,25 @@ public: return false; } + virtual bool OnBeforePluginLoad(CefRefPtr<CefBrowser> browser, const CefString& url, const CefString& policy_url, CefRefPtr<CefWebPluginInfo> info) OVERRIDE { + char *name = cstring_to_c(info->GetName()); + char *path = cstring_to_c(info->GetPath()); + fprintf(logfile, "[WEBCORE] Forbade plugin %s from %s\n", name, path); + free(name); + free(path); + return true; + } + + virtual void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, TerminationStatus status) OVERRIDE { + if ((status == TS_ABNORMAL_TERMINATION) || (status == TS_PROCESS_WAS_KILLED) || (status == TS_PROCESS_CRASHED)) { + opaque->crashed = true; + WebEvent *event = new WebEvent(); + event->kind = TE4_WEB_EVENT_END_BROWSER; + event->handlers = handlers; + push_event(event); + } + } + virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& target_url, @@ -314,12 +348,15 @@ void te4_web_new(web_view_type *view, int w, int h) { CefWindowInfo window_info; CefBrowserSettings browserSettings; + browserSettings.java = STATE_DISABLED; + browserSettings.plugins = STATE_DISABLED; window_info.SetAsOffScreen(NULL); window_info.SetTransparentPainting(true); opaque->render = new RenderHandler(w, h); opaque->view = new BrowserClient(opaque, opaque->render, view->handlers); CefString curl(""); opaque->browser = CefBrowserHost::CreateBrowserSync(window_info, opaque->view.get(), curl, browserSettings); + opaque->crashed = false; view->w = w; view->h = h; @@ -331,9 +368,13 @@ bool te4_web_close(web_view_type *view) { WebViewOpaque *opaque = (WebViewOpaque*)view->opaque; if (!view->closed) { view->closed = true; - fprintf(logfile, "[WEBCORE] Destroying webview for browser\n"); - opaque->browser->GetHost()->CloseBrowser(true); - fprintf(logfile, "[WEBCORE] Destroying send done\n"); + if (opaque->crashed) { + fprintf(logfile, "[WEBCORE] Destroying webview but it was already crashed, doing nothing\n"); + } else { + fprintf(logfile, "[WEBCORE] Destroying webview for browser\n"); + opaque->browser->GetHost()->CloseBrowser(true); + fprintf(logfile, "[WEBCORE] Destroying send done\n"); + } return true; } return false; @@ -829,7 +870,9 @@ void te4_web_shutdown() { } for (std::map<BrowserClient*, bool>::iterator it=all.begin(); it != all.end(); ++it) { - it->first->browser->GetHost()->CloseBrowser(true); + if (!it->first->opaque->crashed) { + it->first->browser->GetHost()->CloseBrowser(true); + } } while (!all_browsers.empty()) { diff --git a/src/web-cef3/web.h b/src/web-cef3/web.h index 90b0718d9307545b5f7e8e464fa1f9a1e6d32ed4..ca31aeb515d44cc486a4b2298726bead14186825 100644 --- a/src/web-cef3/web.h +++ b/src/web-cef3/web.h @@ -1,8 +1,22 @@ /* TE4 - T-Engine 4 - Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicolas Casalini + Copyright (C) 2009 - 2014 Nicolas Casalini - No permission to copy or replicate in any ways. + 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 */ #ifndef __TE4WEB_H__ diff --git a/src/web-external.h b/src/web-external.h index bf1a837555cb4d41ad8da4d96dd98d1ccacc8443..6a1afc2b75a0ebee0208d0f63785f17c76151690 100644 --- a/src/web-external.h +++ b/src/web-external.h @@ -35,6 +35,7 @@ enum web_event_kind { TE4_WEB_EVENT_LOADING, TE4_WEB_EVENT_LOCAL_REQUEST, TE4_WEB_EVENT_RUN_LUA, + TE4_WEB_EVENT_END_BROWSER, }; typedef struct { diff --git a/src/web.c b/src/web.c index 8a2622dc220a317d7db46efb291bdfdd7c353926..05b0e560e90d3d8d3b482f13d02a20aef02f0213 100644 --- a/src/web.c +++ b/src/web.c @@ -351,6 +351,16 @@ static void handle_event(WebEvent *event) { } else lua_pop(he_L, 1); break; + case TE4_WEB_EVENT_END_BROWSER: + lua_rawgeti(he_L, LUA_REGISTRYINDEX, event->handlers); + lua_pushstring(he_L, "on_crash"); + lua_gettable(he_L, -2); + lua_remove(he_L, -2); + if (!lua_isnil(he_L, -1)) { + docall(he_L, 0, 0); + } else lua_pop(he_L, 1); + break; + case TE4_WEB_EVENT_LOCAL_REQUEST: lua_getglobal(he_L, "core"); lua_getfield(he_L, -1, "webview");