Newer
Older
function _M:spellCrit(dam, add_chance)
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
return dam * (1.5 + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7), true
local chance = self:combatSpellCrit() + (add_chance or 0)
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: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)
--- Computes mind crit for a damage
function _M:mindCrit(dam, add_chance)
if self:isTalentActive(self.T_STEALTH) and self:knowTalent(self.T_SHADOWSTRIKE) then
return dam * (1.5 + self:getTalentLevel(self.T_SHADOWSTRIKE) / 7), true
end
local chance = self:combatMindCrit() + (add_chance or 0)
local crit = false
print("[MIND CRIT %]", chance)
if rng.percent(chance) then
dam = dam * (1.5 + (self.combat_critical_power or 0) / 100)
crit = true
dg
committed
game.logSeen(self, "#{bold}#%s's mind surges with critical power!#{normal}#", self.name:capitalize())
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
chance = 100 - chance
print("[SPELL] friendly fire chance", chance)
return chance
end
--- Gets mindpower
function _M:combatMindpower(mod)
mod = mod or 1
local add = 0
dg
committed
if self:knowTalent(self.T_GESTURE_OF_COMMAND) then
local t = self:getTalentFromId(self.T_GESTURE_OF_COMMAND)
add = t.getMindpowerChange(self, t)
end
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
if self:knowTalent(self.T_POWER_IS_MONEY) then
add = add + util.bound(self.money / (80 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 10)
end
return self:rescaleCombatStats(self.combat_physresist + (self:getCon() + self:getStr() + (self:getLck() - 50) * 0.5) * 0.35 + add)
--- 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 / (80 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 10)
return self:rescaleCombatStats(self.combat_spellresist + (self:getMag() + self:getWil() + (self:getLck() - 50) * 0.5) * 0.35 + add)
--- 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 / (80 - self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 5), 0, self:getTalentLevelRaw(self.T_POWER_IS_MONEY) * 10)
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 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
end
--- Computes movement speed
function _M:combatMovementSpeed()
if game.level and game.level.data.zero_gravity then
mult = 3
end
return mult * (self.base_movement_speed or 1) / self.movement_speed
--- 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 end
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 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
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
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