Newer
Older
function _M:combatAttackMag(weapon, ammo)
return self:rescaleCombatStats(self:combatAttackBase(weapon, ammo) + (self:getMag(100, true) - 10))
--- Gets the armor penetration
function _M:combatAPR(weapon)
local addapr = 0
return self.combat_apr + (weapon.apr or 0) + addapr
end
--- Gets the weapon speed
function _M:combatSpeed(weapon)
return (weapon.physspeed or 1) / self.combat_physspeed
end
--- Gets the crit rate
function _M:combatCrit(weapon)
local addcrit = 0
if weapon.talented and weapon.talented == "knife" and self:knowTalent(Talents.T_LETHALITY) then
addcrit = 1 + self:getTalentLevel(Talents.T_LETHALITY) * 1.3
end
dg
committed
local crit = self.combat_physcrit + (self:getCun() - 10) * 0.3 + (self:getLck() - 50) * 0.30 + (weapon.physcrit or 1) + addcrit
-- This currently beefs up high-end damage values to make up for the combat stat rescale nerf.
function _M:rescaleDamage(dam)
if dam <= 0 then return dam end
-- return dam * (1 - math.log10(dam * 2) / 7) --this is the old version, pre-combat-stat-rescale
return dam ^ 1.04
end
--Diminishing-returns method of scaling combat stats, observing this rule: the first twenty ranks cost 1 point each, the second twenty cost two each, and so on. This is much, much better for players than some logarithmic mess, since they always know exactly what's going on, and there are nice breakpoints to strive for.
function _M:rescaleCombatStats(raw_combat_stat_value)
local x = raw_combat_stat_value
local tiers = 5 -- Just increase this if you want to add high-level content that allows for combat stat scores over 100.
--return math.floor(math.min(x, 20) + math.min(math.max((x-20), 0)/2, 20) + math.min(math.max((x-60), 0)/3, 20) + math.min(math.max((x-120), 0)/4, 20) + math.min(math.max((x-200), 0)/5, 20)) --Five terms of the summation below.
local total = 0
for i = 1, tiers do
local sub = 20*(i*(i-1)/2)
total = total + math.min(math.max(x-sub, 0)/i, 20)
end
return total
--- Gets the damage
function _M:combatDamage(weapon)
local sub_cun_to_str = false
if weapon.talented and weapon.talented == "knife" and self:knowTalent(Talents.T_LETHALITY) then sub_cun_to_str = true end
if self.use_psi_combat and stat == "str" then stat = "wil" end
if self.use_psi_combat and stat == "dex" then stat = "cun" end
totstat = totstat + self:getStat(stat) * mod
if self:knowTalent(self.T_GREATER_TELEKINETIC_GRASP) then
local g = self:getTalentFromId(self.T_GREATER_TELEKINETIC_GRASP)
totstat = totstat * g.stat_sub(self, g)
else
if self:knowTalent(self.T_ARCANE_MIGHT) then
totstat = totstat + self:getStat("mag") * 0.5
end
local talented_mod = math.sqrt(self:combatCheckTraining(weapon) / 5) / 2 + 1
local power = math.max((weapon.dam or 1), 1)
power = (math.sqrt(power / 10) - 1) * 0.5 + 1
--print(("[COMBAT DAMAGE] power(%f) totstat(%f) talent_mod(%f)"):format(power, totstat, talented_mod))
return self:rescaleDamage(0.3*(self:combatPhysicalpower(nil, weapon) + totstat) * power * talented_mod)
function _M:combatPhysicalpower(mod, weapon, add)
add = add or 0
if self:knowTalent(Talents.T_ARCANE_DESTRUCTION) then
add = add + self:combatSpellpower() * self:getTalentLevel(Talents.T_ARCANE_DESTRUCTION) / 7
if self:isTalentActive(Talents.T_BLOOD_FRENZY) then
add = add + self.blood_frenzy
end
if self:knowTalent(self.T_EMPTY_HAND) and self:isUnarmed() then
local t = self:getTalentFromId(self.T_EMPTY_HAND)
add = add + t.getDamage(self, t)
end
if self:attr("psychometry_power") then
add = add + self:attr("psychometry_power")
end
if not weapon then
local inven = self:getInven(self.INVEN_MAINHAND)
if inven and inven[1] then weapon = inven[1].combat else weapon = self.combat end
add = add + 10 * self:combatCheckTraining(weapon)
return self:rescaleCombatStats((self.combat_dam > 0 and self.combat_dam or 0) + add + self:getStr()) * mod
--- Gets damage based on talent
function _M:combatTalentPhysicalDamage(t, base, max)
-- Compute at "max"
local mod = max / ((base + 100) * ((math.sqrt(5) - 1) * 0.8 + 1))
-- Compute real
return self:rescaleDamage((base + (self:combatPhysicalpower())) * ((math.sqrt(self:getTalentLevel(t)) - 1) * 0.8 + 1) * mod)
end
function _M:combatSpellpower(mod, add)
add = add or 0
if self:knowTalent(self.T_ARCANE_CUNNING) then
add = add + (15 + self:getTalentLevel(self.T_ARCANE_CUNNING) * 5) * self:getCun() / 100
if self:knowTalent(self.T_SHADOW_CUNNING) then
add = add + (15 + self:getTalentLevel(self.T_SHADOW_CUNNING) * 5) * self:getCun() / 100
end
if self:hasEffect(self.EFF_BLOODLUST) then
add = add + self:hasEffect(self.EFF_BLOODLUST).dur
local am = 1
if self:attr("spellpower_reduction") then am = 1 / (1 + self:attr("spellpower_reduction")) end
return self:rescaleCombatStats((self.combat_spellpower > 0 and self.combat_spellpower or 0) + add + self:getMag()) * mod * am
end
--- Gets damage based on talent
function _M:combatTalentSpellDamage(t, base, max, spellpower_override)
-- Compute at "max"
local mod = max / ((base + 100) * ((math.sqrt(5) - 1) * 0.8 + 1))
-- Compute real
return self:rescaleDamage((base + (spellpower_override or self:combatSpellpower())) * ((math.sqrt(self:getTalentLevel(t)) - 1) * 0.8 + 1) * mod)
--- Gets weapon damage mult based on talent
function _M:combatTalentWeaponDamage(t, base, max, t2)
if t2 then t2 = t2 / 2 else t2 = 0 end
local diff = max - base
local mult = base + diff * math.sqrt((self:getTalentLevel(t) + t2) / 5)
-- print("[TALENT WEAPON MULT]", self:getTalentLevel(t), base, max, t2, mult)
local offmult = (mult or 1) / 2
if self:knowTalent(Talents.T_DUAL_WEAPON_TRAINING) then
offmult = math.max(offmult, (mult or 1) / (2 - (math.min(self:getTalentLevel(Talents.T_DUAL_WEAPON_TRAINING), 8) / 6)))
end
if self:knowTalent(Talents.T_CORRUPTED_STRENGTH) then
offmult = math.max(offmult, (mult or 1) / (2 - (math.min(self:getTalentLevel(Talents.T_CORRUPTED_STRENGTH), 8) / 9)))
if self:hasEffect(self.EFF_CURSE_OF_MADNESS) then
local eff = self:hasEffect(self.EFF_CURSE_OF_MADNESS)
if eff.level >= 1 and eff.unlockLevel >= 1 then
local def = self.tempeffect_def[self.EFF_CURSE_OF_MADNESS]
offmult = offmult + ((mult or 1) * def.getOffHandMultChange(eff.level) / 100)
end
end
if combat and combat.no_offhand_penalty then
return math.max(1, offmult)
else
return offmult
end
--- Gets fatigue
function _M:combatFatigue()
if self.fatigue < 0 then return 0 end
dg
committed
local crit = self.combat_spellcrit + (self:getCun() - 10) * 0.3 + (self:getLck() - 50) * 0.30 + 1
dg
committed
--- Gets mindcrit
dg
committed
function _M:combatMindCrit(add)
local add = add or 0
dg
committed
if self:knowTalent(self.T_GESTURE_OF_POWER) then
local t = self:getTalentFromId(self.T_GESTURE_OF_POWER)
add = t.getMindCritChange(self, t)
end
dg
committed
local crit = self.combat_mindcrit + (self:getCun() - 10) * 0.3 + (self:getLck() - 50) * 0.30 + 1 + add
dg
committed
end
return 1 / self.combat_spellspeed
function _M:combatMindSpeed()
return 1 / self.combat_mindspeed
--- Gets summon speed
function _M:combatSummonSpeed()
return math.max(1 - ((self:attr("fast_summons") or 0) / 100), 0.1)
end
--- Computes physical crit chance reduction
function _M:combatCritReduction()
local crit_reduction = 0
if self:hasHeavyArmor() and self:knowTalent(self.T_ARMOUR_TRAINING) then
local at = Talents:getTalentFromId(Talents.T_ARMOUR_TRAINING)
crit_reduction = crit_reduction + at.getCriticalChanceReduction(self, at)
if self:knowTalent(self.T_GOLEM_ARMOUR) then
local ga = Talents:getTalentFromId(Talents.T_GOLEM_ARMOUR)
crit_reduction = crit_reduction + ga.getCriticalChanceReduction(self, ga)
end
end
if self:attr("combat_crit_reduction") then
crit_reduction = crit_reduction + self:attr("combat_crit_reduction")
end
return crit_reduction
end
function _M:physicalCrit(dam, weapon, target, atk, def, add_chance, crit_power_add)
local chance = self:combatCrit(weapon) + (add_chance or 0)
crit_power_add = crit_power_add or 0
if self:knowTalent(self.T_BACKSTAB) and target:attr("stunned") then chance = chance + self:getTalentLevel(self.T_BACKSTAB) * 10 end
if target:attr("combat_crit_vulnerable") then
chance = chance + target:attr("combat_crit_vulnerable")
if target:hasEffect(target.EFF_SET_UP) then
local p = target:hasEffect(target.EFF_SET_UP)
if p and p.src == self then
chance = chance - target:combatCritReduction()
dg
committed
if target:hasEffect(target.EFF_DISMAYED) then
chance = 100
end
-- Scoundrel's Strategies
if self:attr("cut") and target:knowTalent(self.T_SCOUNDREL) then
chance = chance - (5 + (target:getTalentLevel(self.T_SCOUNDREL)*5))
end
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
chance = 100
crit_power_add = crit_power_add + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7
end
if target:hasEffect(target.EFF_OFFGUARD) then
crit_power_add = crit_power_add + 0.1
self.turn_procs.is_crit = "physical"
self.turn_procs.crit_power = (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
dam = dam * (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
if self:knowTalent(self.T_EYE_OF_THE_TIGER) then self:triggerTalent(self.T_EYE_OF_THE_TIGER, nil, "physical") end
local chance = self:combatSpellCrit() + (add_chance or 0)
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
chance = 100
crit_power_add = crit_power_add + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7
end
self.turn_procs.crit_power = (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
dam = dam * (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
dg
committed
game.logSeen(self, "#{bold}#%s's spell attains critical power!#{normal}#", self.name:capitalize())
if self:attr("mana_on_crit") then self:incMana(self:attr("mana_on_crit")) end
if self:attr("vim_on_crit") then self:incVim(self:attr("vim_on_crit")) end
if self:attr("paradox_on_crit") then self:incParadox(self:attr("paradox_on_crit")) end
if self:attr("positive_on_crit") then self:incPositive(self:attr("positive_on_crit")) end
if self:attr("negative_on_crit") then self:incNegative(self:attr("negative_on_crit")) end
if self:attr("spellsurge_on_crit") then
local power = self:attr("spellsurge_on_crit")
self:setEffect(self.EFF_SPELLSURGE, 10, {power=power, max=power*3})
end
if self:isTalentActive(self.T_BLOOD_FURY) then
local t = self:getTalentFromId(self.T_BLOOD_FURY)
t.on_crit(self, t)
end
if self:isTalentActive(self.T_CORONA) then
local t = self:getTalentFromId(self.T_CORONA)
if self:knowTalent(self.T_EYE_OF_THE_TIGER) then self:triggerTalent(self.T_EYE_OF_THE_TIGER, nil, "spell") end
local chance = self:combatMindCrit() + (add_chance or 0)
local crit = false
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
chance = 100
crit_power_add = crit_power_add + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7
end
print("[MIND CRIT %]", chance)
if rng.percent(chance) then
self.turn_procs.crit_power = (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
dam = dam * (1.5 + crit_power_add + (self.combat_critical_power or 0) / 100)
dg
committed
game.logSeen(self, "#{bold}#%s's mind surges with critical power!#{normal}#", self.name:capitalize())
if self:attr("hate_on_crit") then self:incHate(self:attr("hate_on_crit")) end
if self:attr("psi_on_crit") then self:incPsi(self:attr("psi_on_crit")) end
if self:attr("equilibrium_on_crit") then self:incEquilibrium(self:attr("equilibrium_on_crit")) end
if self:knowTalent(self.T_EYE_OF_THE_TIGER) then self:triggerTalent(self.T_EYE_OF_THE_TIGER, nil, "mind") end
if self:knowTalent(self.T_LIVING_MUCUS) then self:callTalent(self.T_LIVING_MUCUS, "on_crit") end
dg
committed
--- Do we get hit by our own AOE ?
function _M:spellFriendlyFire()
local chance = (self:getLck() - 50) * 0.2
if self:isTalentActive(self.T_SPELLCRAFT) then chance = chance + self:getTalentLevelRaw(self.T_SPELLCRAFT) * 20 end
dg
committed
chance = 100 - chance
print("[SPELL] friendly fire chance", chance)
dg
committed
end
dg
committed
function _M:combatMindpower(mod, add)
dg
committed
add = add or 0
dg
committed
if self:knowTalent(self.T_GESTURE_OF_POWER) then
local t = self:getTalentFromId(self.T_GESTURE_OF_POWER)
dg
committed
add = add + t.getMindpowerChange(self, t)
dg
committed
end
if self:attr("psychometry_power") then
add = add + self:attr("psychometry_power")
end
dg
committed
return self:rescaleCombatStats((self.combat_mindpower > 0 and self.combat_mindpower or 0) + add + self:getWil() * 0.7 + self:getCun() * 0.4) * mod
end
--- Gets damage based on talent
function _M:combatTalentMindDamage(t, base, max)
-- Compute at "max"
local mod = max / ((base + 100) * ((math.sqrt(5) - 1) * 0.8 + 1))
-- Compute real
return self:rescaleDamage((base + (self:combatMindpower())) * ((math.sqrt(self:getTalentLevel(t)) - 1) * 0.8 + 1) * mod)
--- Gets damage based on talent
function _M:combatTalentStatDamage(t, stat, base, max)
-- Compute at "max"
local mod = max / ((base + 100) * ((math.sqrt(5) - 1) * 0.8 + 1))
-- Compute real
local dam = (base + (self:getStat(stat))) * ((math.sqrt(self:getTalentLevel(t)) - 1) * 0.8 + 1) * mod
dam = dam * (1 - math.log10(dam * 2) / 7)
dam = dam ^ (1 / 1.04)
return self:rescaleDamage(dam)
function _M:combatTalentIntervalDamage(t, stat, min, max, stat_weight)
local stat_weight = stat_weight or 0.5
local dam = min + (max - min)*((stat_weight * self:getStat(stat)/100) + (1 - stat_weight) * self:getTalentLevel(t)/6.5)
dam = dam * (1 - math.log10(dam * 2) / 7)
dam = dam ^ (1 / 1.04)
return self:rescaleDamage(dam)
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))
--- Fake denotes a check not actually being made, used by character sheets etc.
function _M:combatPhysicalResist(fake)
add = add + (self:checkOnDefenseCall("physical") or 0)
end
add = add + util.bound(self.money / (90 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 7)
-- To return later
local total = self:rescaleCombatStats(self.combat_physresist + (self:getCon() + self:getStr() + (self:getLck() - 50) * 0.5) * 0.35 + add)
-- Psionic Balance
if self:knowTalent(self.T_BALANCE) then
local t = self:getTalentFromId(self.T_BALANCE)
local ratio = t.getBalanceRatio(self, t)
total = (1 - ratio)*total + self:combatMentalResist(fake)*ratio
end
return total
--- Fake denotes a check not actually being made, used by character sheets etc.
function _M:combatSpellResist(fake)
add = add + (self:checkOnDefenseCall("spell") or 0)
end
add = add + util.bound(self.money / (90 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 7)
-- To return later
local total = self:rescaleCombatStats(self.combat_spellresist + (self:getMag() + self:getWil() + (self:getLck() - 50) * 0.5) * 0.35 + add)
-- Psionic Balance
if self:knowTalent(self.T_BALANCE) then
local t = self:getTalentFromId(self.T_BALANCE)
local ratio = t.getBalanceRatio(self, t)
total = (1 - ratio)*total + self:combatMentalResist(fake)*ratio
end
return total
--- Fake denotes a check not actually being made, used by character sheets etc.
function _M:combatMentalResist(fake)
add = add + (self:checkOnDefenseCall("mental") or 0)
end
if self:knowTalent(self.T_STEADY_MIND) then
local t = self:getTalentFromId(self.T_STEADY_MIND)
add = add + t.getMental(self, t)
end
add = add + util.bound(self.money / (90 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 7)
return self:rescaleCombatStats(self.combat_mentalresist + (self:getCun() + self:getWil() + (self:getLck() - 50) * 0.5) * 0.35 + add)
-- Called when a Save or Defense is checked
function _M:checkOnDefenseCall(type)
local add = 0
if self:knowTalent(self.T_SPIN_FATE) then
print("Spin Fate", type)
local t = self:getTalentFromId(self.T_SPIN_FATE)
t.do_spin_fate(self, t, type)
end
return add
end
--- Returns the resistance
function _M:combatGetResist(type)
local power = 100
if self.force_use_resist and self.force_use_resist ~= type then
type = self.force_use_resist
power = self.force_use_resist_percent or 100
end
local a = (self.resists.all or 0) / 100
local b = (self.resists[type] or 0) / 100
local r = math.min(100 * (1 - (1 - a) * (1 - b)), (self.resists_cap.all or 0) + (self.resists_cap[type] or 0))
return r * power / 100
function _M:combatMovementSpeed(x, y)
if game.level and game.level.data.zero_gravity then
local movement_speed = self.movement_speed
if x and y and game.level.map:checkAllEntities(x, y, "creepingDark") and self:knowTalent(self.T_DARK_VISION) then
local t = self:getTalentFromId(self.T_DARK_VISION)
movement_speed = movement_speed + t.getMovementSpeedChange(self, t)
end
return mult * (self.base_movement_speed or 1) / movement_speed
--- Computes see stealth
function _M:combatSeeStealth()
local bonus = 0
if self:knowTalent(self.T_PIERCING_SIGHT) then bonus = bonus + 5 + self:getTalentLevel(self.T_PIERCING_SIGHT) * self:getCun(15, true) end
return self.level / 2 + self:getCun(25, true) + (self:attr("see_stealth") or 0) + bonus
end
--- Computes see invisible
function _M:combatSeeInvisible()
local bonus = 0
if self:knowTalent(self.T_PIERCING_SIGHT) then bonus = bonus + 5 + self:getTalentLevel(self.T_PIERCING_SIGHT) * self:getCun(15, true) end
return (self:attr("see_invisible") or 0) + bonus
end
--- Check if the actor has a gem bomb in quiver
function _M:hasAlchemistWeapon()
if not self:getInven("QUIVER") then return nil, "no ammo" end
local ammo = self:getInven("QUIVER")[1]
if not ammo or not ammo.alchemist_power then
return nil, "bad or no ammo"
end
return ammo
end
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("MAINHAND") then return end
local weapon = self:getInven("MAINHAND")[1]
if not weapon or weapon.subtype ~= "staff" then
return nil
end
return weapon
end
--- Check if the actor has an axe weapon
function _M:hasAxeWeapon()
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("MAINHAND") then return end
local weapon = self:getInven("MAINHAND")[1]
if not weapon or (weapon.subtype ~= "battleaxe" and weapon.subtype ~= "waraxe") then
return nil
end
return weapon
end
--- Check if the actor has a cursed weapon
function _M:hasCursedWeapon()
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("MAINHAND") then return end
local weapon = self:getInven("MAINHAND")[1]
if not weapon or not weapon.curse then
local t = self:getTalentFromId(self.T_DEFILING_TOUCH)
if not t.canCurseItem(self, t, weapon) then return nil end
return weapon
end
--- Check if the actor has a cursed weapon
function _M:hasCursedOffhandWeapon()
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("OFFHAND") then return end
local weapon = self:getInven("OFFHAND")[1]
if not weapon or not weapon.combat or not weapon.curse then
local t = self:getTalentFromId(self.T_DEFILING_TOUCH)
if not t.canCurseItem(self, t, weapon) then return nil end
--- Check if the actor has a two handed weapon
if self:attr("disarmed") then
return nil, "disarmed"
end
local weapon = self:getInven("MAINHAND")[1]
if not weapon or not weapon.twohanded then
return nil
end
return weapon
end
--- Check if the actor has a shield
function _M:hasShield()
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("MAINHAND") or not self:getInven("OFFHAND") then return end
local shield = self:getInven("OFFHAND")[1]
if not shield or not shield.special_combat then
return nil
end
return shield
-- Check if actor is unarmed
function _M:isUnarmed()
local unarmed = true
if not self:getInven("MAINHAND") or not self:getInven("OFFHAND") then return end
local weapon = self:getInven("MAINHAND")[1]
local offweapon = self:getInven("OFFHAND")[1]
if weapon or offweapon then
unarmed = false
end
return unarmed
end
dg
committed
-- Get the number of free hands the actor has
function _M:getFreeHands()
if not self:getInven("MAINHAND") or not self:getInven("OFFHAND") then return 0 end
dg
committed
local weapon = self:getInven("MAINHAND")[1]
local offweapon = self:getInven("OFFHAND")[1]
if weapon and offweapon then return 0 end
dg
committed
if weapon or offweapon then return 1 end
return 2
end
if self:attr("disarmed") then
return nil, "disarmed"
end
if not self:getInven("MAINHAND") or not self:getInven("OFFHAND") then return end
local weapon = self:getInven("MAINHAND")[1]
local offweapon = self:getInven("OFFHAND")[1]
if not weapon or not offweapon or not weapon.combat or not offweapon.combat then
return nil
end
return weapon, offweapon
end
--- Check if the actor uses psiblades
function _M:hasPsiblades(main, off)
if self:attr("disarmed") then
return nil, "disarmed"
end
local weapon, offweapon = nil, nil
if main then
if not self:getInven("MAINHAND") then return end
weapon = self:getInven("MAINHAND")[1]
if not weapon or not weapon.combat or not weapon.psiblade_active then return nil, "unactivated psiblade" end
end
if off then
if not self:getInven("OFFHAND") then return end
offweapon = self:getInven("OFFHAND")[1]
if not offweapon or not offweapon.combat or not offweapon.psiblade_active then return nil, "unactivated psiblade" end
end
return weapon, offweapon
end
--- Check if the actor has a light armor
function _M:hasLightArmor()
if not self:getInven("BODY") then return end
local armor = self:getInven("BODY")[1]
if not armor or (armor.subtype ~= "cloth" and armor.subtype ~= "light") then
return nil
end
return armor
end
--- Check if the actor has a heavy armor
function _M:hasHeavyArmor()
if not self:getInven("BODY") then return end
local armor = self:getInven("BODY")[1]
if not armor or (armor.subtype ~= "heavy" and armor.subtype ~= "massive") then
end
--- Check if the actor has a massive armor
function _M:hasMassiveArmor()
if not self:getInven("BODY") then return end
local armor = self:getInven("BODY")[1]
if not armor or armor.subtype ~= "massive" then
return nil
end
-- Unarmed Combat; this handles grapple checks and building combo points
-- Builds Comob; reduces the cooldown on all unarmed abilities on cooldown by one
function _M:buildCombo()
local duration = 3
local power = 1
-- Combo String bonuses
if self:knowTalent(self.T_COMBO_STRING) then
local t = self:getTalentFromId(self.T_COMBO_STRING)
local t = self:getTalentFromId(self.T_RELENTLESS_STRIKES)
self:setEffect(self.EFF_COMBO, duration, {power=power})
end
function _M:getCombo(combo)
local combo = 0
local p = self:hasEffect(self.EFF_COMBO)
combo = p.cur_power
end
return combo
end
function _M:clearCombo()
if self:hasEffect(self.EFF_COMBO) then
self:removeEffect(self.EFF_COMBO)
end
end
-- Check to see if the target is already being grappled; many talents have extra effects on grappled targets
function _M:isGrappled(source)
local p = self:hasEffect(self.EFF_GRAPPLED)
if p and p.src == source then
return true
else
return false
end
end
-- Breaks active grapples; called by a few talents that involve a lot of movement
function _M:breakGrapples()
if self:hasEffect(self.EFF_GRAPPLING) then
local p = self:hasEffect(self.EFF_GRAPPLING)
if p.trgt then
p.trgt:removeEffect(p.trgt.EFF_GRAPPLED)
end
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
self:removeEffect(self.EFF_GRAPPLING)
end
end
-- grapple size check; compares attackers size and targets size
function _M:grappleSizeCheck(target)
size = target.size_category - self.size_category
if size > 1 then
game.logSeen(target, "%s fails because %s is too big!", self.name:capitalize(), target.name:capitalize())
return true
else
return false
end
end
-- Starts the grapple
function _M:startGrapple(target)
-- pulls boosted grapple effect from the clinch talent if known
if self:knowTalent(self.T_CLINCH) then
local t = self:getTalentFromId(self.T_CLINCH)
power = t.getPower(self, t)
duration = t.getDuration(self, t)
hitbonus = self:getTalentLevel(t)/2
else
power = 5
duration = 4
hitbonus = 0
end
-- Breaks the grapple before reapplying
if self:hasEffect(self.EFF_GRAPPLING) then
self:removeEffect(self.EFF_GRAPPLING, true)
target:setEffect(target.EFF_GRAPPLED, duration, {src=self, power=power}, true)
self:setEffect(self.EFF_GRAPPLING, duration, {trgt=target}, true)
elseif target:canBe("pin") then
target:setEffect(target.EFF_GRAPPLED, duration, {src=self, power=power, apply_power=self:combatPhysicalpower()})
target:crossTierEffect(target.EFF_GRAPPLED, self:combatPhysicalpower())
self:setEffect(self.EFF_GRAPPLING, duration, {trgt=target})
return true
else
game.logSeen(target, "%s resists the grapple!", target.name:capitalize())
return false
end