Skip to content
Snippets Groups Projects
Commit 868f71f0 authored by Hachem_Muche's avatar Hachem_Muche
Browse files

Rogue's Artfice tools update:

Significant rewrite of artifice talents, eliminating parallel code.  Adding new tools is now much simpler.
Talent descriptions are more complete and clear.
NPC's can use all tools, including Master Artificer, and will automatically select what to prepare at random the first time they try to use talents.
Tools automatically use and benefit from the mastery level for the "cunning/artifice" tree.
Added some missing stamina costs.
Chat dialogs display the changes in the associated talents in their tooltips, and allow the player to cancel the action with no penalty,
Rogue's Brew scaling corrected (does not depend on maximum life).
Assassinate grants only physical resistance penetration (nerf), errors are trapped to prevent any possible permanent buffs.
Only actors can get Backstab damage bonuses.
Updated some new DamageTypes to display in the combat log as appropriate.
parent bf7bbf84
No related branches found
No related tags found
1 merge request!354Rogue rework update
......@@ -18,40 +18,41 @@
-- darkgod@te4.org
local Talents = require("engine.interface.ActorTalents")
chat_talent = player:getTalentFromId(chat_tid)
chat_level = player:getTalentLevelRaw(chat_tid)
local function generate_tools()
local answers = {}
local tools =
{
}
if player:knowTalent(player.T_HIDDEN_BLADES) then tools[Talents.T_ASSASSINATE] = 1 end
if player:knowTalent(player.T_SMOKESCREEN) then tools[Talents.T_SMOKESCREEN_MASTERY] = 1 end
if player:knowTalent(player.T_ROGUE_S_BREW) then tools[Talents.T_ROGUE_S_BREW_MASTERY] = 1 end
if player:knowTalent(player.T_DART_LAUNCHER) then tools[Talents.T_DART_LAUNCHER_MASTERY] = 1 end
if tools then
for tid, level in pairs(tools) do
local t = npc:getTalentFromId(tid)
level = math.min(t.points - game.player:getTalentLevelRaw(tid), level)
local answers = {{"Cancel"}}
for tid, m_tid in pairs(tool_ids) do
local t = player:getTalentFromId(tid)
local m_t = player:getTalentFromId(m_tid)
local master_talent = function(npc, player)
local old_mastery_level = player:getTalentLevelRaw(m_tid)
if old_mastery_level == chat_level then return end
-- unlearn mastery talent(s)
for tid, m_tid in pairs(tool_ids) do
if player:knowTalent(m_tid) then player:unlearnTalentFull(m_tid) end
end
local doit = function(npc, player)
if game.player:knowTalentType(t.type[1]) == nil then player:setTalentTypeMastery(t.type[1], 1.0) end
player:learnTalent(tid, true, level, {no_unlearn=true})
player:startTalentCooldown(tid)
player:learnTalent(m_tid, true, chat_level, {no_unlearn=true})
player.artifice_tools_mastery = tid
-- start talent cooldowns
if old_mastery_level == 0 then
player:startTalentCooldown(tid) player:startTalentCooldown(m_tid)
player:startTalentCooldown(chat_tid)
game.log("#LIGHT_BLUE# You enhance your preparation of %s.", t.name)
end
answers[#answers+1] = {("[%s]"):format(t.name),
action=doit,
on_select=function(npc, player)
local mastery = nil
if player:knowTalentType(t.type[1]) == nil then mastery = 1.0 end
game.tooltip_x, game.tooltip_y = 1, 1
game:tooltipDisplayAtMap(game.w, game.h, "#GOLD#"..t.name.."#LAST#\n"..tostring(player:getTalentFullDescription(t, 1, nil, mastery)))
end,
}
end
answers[#answers+1] = {"Cancel"}
answers[#answers+1] = {("%s[%s -- mastery: %s]#LAST#"):format(player.artifice_tools_mastery == tid and "#YELLOW#" or "", t.name, m_t.name),
action=master_talent,
on_select=function(npc, player)
local mastery = nil
game.tooltip_x, game.tooltip_y = 1, 1
game:tooltipDisplayAtMap(game.w, game.h, "#GOLD#"..m_t.name.."#LAST#\n"..tostring(player:getTalentFullDescription(m_t, nil, {force_level=chat_level}, mastery)))
end,
}
end
return answers
end
......
......@@ -18,63 +18,79 @@
-- darkgod@te4.org
local Talents = require("engine.interface.ActorTalents")
chat_talent = player:getTalentFromId(chat_tid)
chat_level = player:getTalentLevelRaw(chat_tid)
local function generate_tools()
local answers = {}
local tools =
{
}
--populate the tool list, also apply a temp value so talents display correctly
if not player.artifice_hidden_blades then
tools[Talents.T_HIDDEN_BLADES] = 1
player.artifice_hidden_blades = slot
end
if not player.artifice_smokescreen then
tools[Talents.T_SMOKESCREEN] = 1
player.artifice_smokescreen = slot
end
if not player.artifice_rogue_s_brew then
tools[Talents.T_ROGUE_S_BREW] = 1
player.artifice_rogue_s_brew = slot
end
if not player.artifice_dart_launcher then
tools[Talents.T_DART_LAUNCHER] = 1
player.artifice_dart_launcher = slot
end
local answers = {{"[Cancel]"}}
local tool_ids = tool_ids or player.main_env.artifice_tool_tids
player.artifice_tools = player.artifice_tools or {}
if tools then
for tid, level in pairs(tools) do
local t = npc:getTalentFromId(tid)
level = math.min(t.points - game.player:getTalentLevelRaw(tid), level)
local doit = function(npc, player)
if game.player:knowTalentType(t.type[1]) == nil then player:setTalentTypeMastery(t.type[1], 1.0) end
player:learnTalent(tid, true, level, {no_unlearn=true})
--remove the temp values set earlier
if not (t.name=="Hidden Blades" or player:knowTalent(player.T_HIDDEN_BLADES)) then player.artifice_hidden_blades = null end
if not (t.name=="Smokescreen" or player:knowTalent(player.T_SMOKESCREEN)) then player.artifice_smokescreen = null end
if not (t.name=="Rogue's Brew" or player:knowTalent(player.T_ROGUE_S_BREW)) then player.artifice_rogue_s_brew = null end
if not (t.name=="Dart Launcher" or player:knowTalent(player.T_DART_LAUNCHER)) then player.artifice_dart_launcher = null end
player:startTalentCooldown(tid)
for tid, m_tid in pairs(tool_ids) do
local t = player:getTalentFromId(tid)
if t then
local tool_level = player:getTalentLevelRaw(t)
local equip_tool = function(npc, player) -- equip a tool
if tool_level == chat_level then return end -- already selected and up to date
-- unlearn the previous talent
player:unlearnTalentFull(player.artifice_tools[chat_tid])
-- (re)learn the talent
player:unlearnTalentFull(tid)
player:learnTalent(tid, true, chat_level, {no_unlearn=true})
-- clear other tool slots
for slot, tool_id in pairs(player.artifice_tools) do
if tool_id == tid then player.artifice_tools[slot] = nil end
end
player.artifice_tools[chat_tid] = tid
-- start talent cooldowns and use energy
player.turn_procs._did_artifice = true -- controls energy use
player:startTalentCooldown(tid) player:startTalentCooldown(m_tid)
end
answers[#answers+1] = {("[Equip %s]"):format(t.name),
action=doit,
local txt, slot
-- check for an existing slot
for slot_id, tool_id in pairs(player.artifice_tools) do
if tool_id == tid then slot = slot_id break end
end
if slot then
txt = ("[%sEquip %s%s#LAST#]"):format(slot==chat_tid and "#YELLOW#" or "", t.name, slot and (" (%s)"):format(player:getTalentFromId(slot).name) or "")
else
txt = ("[Equip %s]"):format(t.name)
end
answers[#answers+1] = {txt,
action=equip_tool,
on_select=function(npc, player)
local mastery = nil
if player:knowTalentType(t.type[1]) == nil then mastery = 1.0 end
local display_level
display_level = chat_level - tool_level
game.tooltip_x, game.tooltip_y = 1, 1
game:tooltipDisplayAtMap(game.w, game.h, "#GOLD#"..t.name.."#LAST#\n"..tostring(player:getTalentFullDescription(t, 1, nil, mastery)))
-- set up tooltip
local text = tstring{}
if display_level ~= 0 and player:knowTalent(t) then
local diff = function(i2, i1, res)
if i2 > i1 then
res:add({"color", "LIGHT_GREEN"}, i1, {"color", "LAST"}, " [->", {"color", "YELLOW_GREEN"}, i2, {"color", "LAST"}, "]")
elseif i2 < i1 then
res:add({"color", "LIGHT_GREEN"}, i1, {"color", "LAST"}, " [->", {"color", "LIGHT_RED"}, i2, {"color", "LAST"}, "]")
end
end
text:merge(player:getTalentFullDescription(t, display_level, nil):diffWith(player:getTalentFullDescription(t, 0, nil), diff))
else
text = player:getTalentFullDescription(t, nil, {force_level=chat_level})
end
game:tooltipDisplayAtMap(game.w, game.h, "#GOLD#"..t.name.."#LAST#\n"..tostring(text))
end,
}
end
end
return answers
end
newChat{ id="welcome",
text = [[Equip which tools?]],
text = ([[Equip which tool for #YELLOW#%s#LAST#?]]):format(chat_talent.name),
answers = generate_tools(),
}
......
......@@ -239,7 +239,7 @@ setDefaultProjector(function(src, x, y, type, dam, state)
end
end
if src and dam > 0 and src.knowTalent and src:knowTalent(src.T_BACKSTAB) and src.__CLASSNAME ~= "mod.class.Grid" then
if dam > 0 and src and src.__is_actor and src:knowTalent(src.T_BACKSTAB) and src.__CLASSNAME ~= "mod.class.Grid" then
local power = src:callTalent("T_BACKSTAB", "getDamageBoost")
local nb = 0
for eff_id, p in pairs(target.tmp) do
......@@ -3878,11 +3878,13 @@ newDamageType{
newDamageType{
name = "terror", type = "TERROR",
text_color = "#YELLOW#",
projector = function(src, x, y, type, dam, state)
state = initState(state)
useImplicitCrit(src, state)
local target = game.level.map(x, y, Map.ACTOR)
if target then
game:delayedLogDamage(src, target, 0, ("%s<terror chance>#LAST#"):format(DamageType:get(type).text_color or "#aaaaaa#"), false)
if not src:checkHit(src:combatAttack(), target:combatMentalResist()) then return end
local effect = rng.range(1, 3)
if effect == 1 then
......@@ -3908,6 +3910,7 @@ newDamageType{
end,
}
-- Random poison: 25% to be enhanced
newDamageType{
name = "random poison", type = "RANDOM_POISON", text_color = "#LIGHT_GREEN#",
projector = function(src, x, y, t, dam, poison, state)
......@@ -3915,10 +3918,10 @@ newDamageType{
useImplicitCrit(src, state)
local power
local target = game.level.map(x, y, Map.ACTOR)
if target and src:reactionToward(target) < 0 then
if target and src:reactionToward(target) < 0 and target:canBe("poison") then
local realdam = DamageType:get(DamageType.NATURE).projector(src, x, y, DamageType.NATURE, dam.dam / 6, state)
chance = rng.range(1, 3)
if target and target:canBe("poison") and rng.percent(25) then
if rng.percent(dam.random_chance or 25) then
local chance = rng.range(1, 3)
if chance == 1 then
target:setEffect(target.EFF_INSIDIOUS_POISON, 5, {src=src, power=dam.dam / 6, heal_factor=dam.power*2, apply_power=dam.apply_power or (src.combatAttack and src:combatAttack()) or 0})
elseif chance == 2 then
......@@ -3926,7 +3929,7 @@ newDamageType{
elseif chance == 3 then
target:setEffect(target.EFF_CRIPPLING_POISON, 5, {src=src, power=dam.dam / 6, fail=dam.power, apply_power=dam.apply_power or (src.combatAttack and src:combatAttack()) or 0})
end
elseif target and target:canBe("poison") then
else
target:setEffect(target.EFF_POISONED, 5, {src=src, power=dam.dam / 6, apply_power=dam.apply_power or (src.combatAttack and src:combatAttack()) or 0})
end
return realdam
......@@ -3936,11 +3939,13 @@ newDamageType{
newDamageType{
name = "blinding powder", type = "BLINDING_POWDER",
text_color = "#GREY#",
projector = function(src, x, y, type, dam, state)
state = initState(state)
useImplicitCrit(src, state)
local target = game.level.map(x, y, Map.ACTOR)
if target then
game:delayedLogDamage(src, target, 0, ("%s<blinding powder>#LAST#"):format(DamageType:get(type).text_color or "#aaaaaa#"), false)
if not src:checkHit(src:combatAttack(), target:combatPhysicalResist()) then return end
if target:canBe("blind") then
......@@ -3955,12 +3960,13 @@ newDamageType{
newDamageType{
name = "smokescreen", type = "SMOKESCREEN",
text_color = "#GREY#",
projector = function(src, x, y, type, dam, state)
state = initState(state)
useImplicitCrit(src, state)
local target = game.level.map(x, y, Map.ACTOR)
if target and src:reactionToward(target) < 0 then
game:delayedLogDamage(src, target, 0, ("%s<smoke>#LAST#"):format(DamageType:get(type).text_color or "#aaaaaa#"), false)
if target:canBe("blind") then
target:setEffect(target.EFF_DIM_VISION, 2, {sight=dam.dam, apply_power=src:combatAttack(), no_ct_effect=true})
else
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment