From 1fd47821ea86965184441502d7084bb081753621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lilian=20J=C3=B3nsd=C3=B3ttir?= Date: Sun, 25 Oct 2020 16:30:42 -0700 Subject: [PATCH] companions resist spells if stop damage is enabled --- .../celediel/NoMoreFriendlyFire/common.lua | 3 + .../celediel/NoMoreFriendlyFire/config.lua | 2 +- .../mods/celediel/NoMoreFriendlyFire/main.lua | 66 ++++++++++++++----- MWSE/mods/celediel/NoMoreFriendlyFire/mcm.lua | 11 +++- 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/MWSE/mods/celediel/NoMoreFriendlyFire/common.lua b/MWSE/mods/celediel/NoMoreFriendlyFire/common.lua index 51bf791..26821c4 100644 --- a/MWSE/mods/celediel/NoMoreFriendlyFire/common.lua +++ b/MWSE/mods/celediel/NoMoreFriendlyFire/common.lua @@ -8,4 +8,7 @@ this.modInfo = "Stop friendly fire. Player companions can't damage the player, t this.author = "Celediel" this.version = "1.4.0" +-- debug +this.logLevels = {no = 0, small = 1, big = 2} + return this diff --git a/MWSE/mods/celediel/NoMoreFriendlyFire/config.lua b/MWSE/mods/celediel/NoMoreFriendlyFire/config.lua index 2c93d2d..1c2bab9 100644 --- a/MWSE/mods/celediel/NoMoreFriendlyFire/config.lua +++ b/MWSE/mods/celediel/NoMoreFriendlyFire/config.lua @@ -1,7 +1,7 @@ local common = require("celediel.NoMoreFriendlyFire.common") local currentConfig -local defaultConfig = {stopDamage = true, stopCombat = true, debug = false, ignored = {}} +local defaultConfig = {stopDamage = true, stopCombat = true, debugLevel = common.logLevels.no, ignored = {}} local this = {} this.getConfig = function() diff --git a/MWSE/mods/celediel/NoMoreFriendlyFire/main.lua b/MWSE/mods/celediel/NoMoreFriendlyFire/main.lua index 7e5c6f7..3b08787 100644 --- a/MWSE/mods/celediel/NoMoreFriendlyFire/main.lua +++ b/MWSE/mods/celediel/NoMoreFriendlyFire/main.lua @@ -8,7 +8,9 @@ pcall(function() mag = require("celediel.MoreAttentiveGuards.interop") end) local followMatches = {"follow", "together", "travel", "wait", "stay"} local postDialogueTimer -local function log(...) if config.debug then mwse.log("[%s] %s", common.modName, string.format(...)) end end +local function log(level, ...) + if config.debugLevel >= level then mwse.log("[%s] %s", common.modName, string.format(...)) end +end -- keep track of followers local followers = {} @@ -22,8 +24,8 @@ local function notActuallyFriend(friend) local ignoredId = config.ignored[obj.id:lower()] local ignoredMod = config.ignored[obj.sourceMod:lower()] - log("Friend %s: Is MAG Guard:%s, Ignored id:%s, Ignored mod:%s", obj.name, friend == magGuard, - ignoredId or "false", ignoredMod or "false") + log(common.logLevels.small, "Friend %s: Is MAG Guard:%s, Ignored id:%s, Ignored mod:%s", obj.name, + friend == magGuard, ignoredId or "false", ignoredMod or "false") return friend == magGuard or ignoredId or ignoredMod end @@ -44,9 +46,22 @@ local function buildFollowerList() msg = msg .. friend.object.name .. " " end end - if msg ~= "" then log("Friends: %s", msg) end + if msg ~= "" then log(common.logLevels.small, "Friends: %s", msg) end return friends end + +local function isHarmfulSpell(source) + -- look for harmful effects in the source spell + for i = 1, 8 do + local effect = source.effects[i] + if effect.object then + -- todo: get name of spell effect instead of id + log(common.logLevels.big, "effect #%s id:%s: harmful:%s", i, effect.object.id, effect.object.isHarmful) + if effect.object.isHarmful then return true end -- found one! + end + end + return false -- found nothing +end -- }}} -- {{{ Event functions @@ -58,23 +73,41 @@ eventFunctions.onDamage = function(e) if followerCheck(e.attackerReference, e.reference) then if config.stopDamage then - log("%s hit %s for %s friendly damage, nullifying", e.attackerReference.object.name, + log(common.logLevels.small, "%s hit %s for %s friendly damage, nullifying", e.attackerReference.object.name, e.reference.object.name, e.damage) e.damage = 0 return false -- I don't know if this makes a difference or not else - log("%s hit %s for %s friendly damage", e.attackerReference.object.name, e.reference.object.name, e.damage) + log(common.logLevels.small, "%s hit %s for %s friendly damage", e.attackerReference.object.name, + e.reference.object.name, e.damage) + end + else + log(common.logLevels.big, "%s hit %s for %s damage", e.attackerReference.object.name, e.reference.object.name, + e.damage) + end +end + +eventFunctions.onSpellResist = function(e) + -- ignore non-targeted magicka or without caster + if not e.caster or not e.target then return end + -- shortcuts + local caster = e.caster + local target = e.target + local source = e.source + + if followerCheck(caster, target) then + log(common.logLevels.small, "%s hit %s with friendly magicka %s", caster, target, source) + if config.stopDamage and isHarmfulSpell(e.source) then + e.resistedPercent = 100 + log(common.logLevels.small, "%s spell resist vs harmful %s maxified", target, source) end - -- uncomment this to see all damage done by everyone to everyone else - -- else - -- log("%s hit %s for %s damage", e.attackerReference.object.name, e.reference.object.name, e.damage) end end -- prevent combat from even happening between friendly actors eventFunctions.onCombatStart = function(e) if config.stopCombat and followerCheck(e.actor, e.target) then - log("Friendly combat attempted, putting a stop to it!") + log(common.logLevels.small, "Friendly combat attempted, putting a stop to it!") return false end end @@ -94,10 +127,10 @@ eventFunctions.onInfoResponse = function(e) if command:match(item) or dialogue:match(item) then -- wait until game time restarts, and don't set multiple timers if not postDialogueTimer or postDialogueTimer.state ~= timer.active then - log("Found %s in dialogue, rebuilding followers", item) + log(common.logLevels.big, "Found %s in dialogue, rebuilding followers", item) postDialogueTimer = timer.start({ type = timer.simulate, - duration = 0.5, + duration = 0.25, iteration = 1, callback = function() followers = buildFollowerList() end }) @@ -108,13 +141,14 @@ end -- rebuild followers list when player casts conjuration, in case its a summon spell -- false positives are okay because we're not doing anything destructive +-- doesn't work if Skill Based Magicka Progression is activated because e.expGainSchool becomes nil eventFunctions.onSpellCasted = function(e) if e.caster == tes3.player and e.expGainSchool == tes3.magicSchool.conjuration then - log("Player cast conjuration spell %s, rebuilding followers list...", e.source.id) + log(common.logLevels.big, "Player cast conjuration spell %s, rebuilding followers list...", e.source.id) -- wait for summon to be loaded timer.start({ type = timer.simulate, - duration = 1, + duration = 0.25, iterations = 1, callback = function() followers = buildFollowerList() end }) @@ -127,10 +161,10 @@ end local function onInitialized() for name, func in pairs(eventFunctions) do event.register(name:gsub("on(%u)", string.lower), func) - log("%s event registered", name) + log(common.logLevels.small, "%s event registered", name) end - mwse.log("[%s] Successfully initialized%s", common.modName, mag and " with More Attentive Guards interop" or "") + log(common.logLevels.no, "Successfully initialized%s", mag and " with More Attentive Guards interop" or "") end event.register("modConfigReady", function() mwse.mcm.register(require("celediel.NoMoreFriendlyFire.mcm")) end) diff --git a/MWSE/mods/celediel/NoMoreFriendlyFire/mcm.lua b/MWSE/mods/celediel/NoMoreFriendlyFire/mcm.lua index dfaac7f..7ae9192 100644 --- a/MWSE/mods/celediel/NoMoreFriendlyFire/mcm.lua +++ b/MWSE/mods/celediel/NoMoreFriendlyFire/mcm.lua @@ -21,9 +21,14 @@ category:createYesNoButton({ variable = mwse.mcm.createTableVariable({id = "stopCombat", table = config}) }) -category:createYesNoButton({ - label = "Debug logging", - variable = mwse.mcm.createTableVariable({id = "debug", table = config}) +category:createDropdown({ + label = "Debug log level", + options = { + {label = "No", value = common.logLevels.no}, + {label = "Small", value = common.logLevels.small}, + {label = "Big", value = common.logLevels.big} + }, + variable = mwse.mcm.createTableVariable({id = "debugLevel", table = config}) }) template:createExclusionsPage({