0 of 0

File information

Last updated

Original upload

Created by

Xe

Uploaded by

Xerxse

Virus scan

Safe to use

21 comments

  1. PresquePlayed
    PresquePlayed
    • member
    • 0 kudos
    So I edited the lua script to work with the "x" key instead of the right mouse button - this is useful for folks like me that play on a Macbook were left and right click alternation is kinda funky @Xerxse feel free to upload it as an optional file it might help out some people
    local core = require('openmw.core')
     local input = require('openmw.input')
     local self = require('openmw.self')
     local time = require('openmw_aux.time')
     local types = require('openmw.types')
     local ui = require('openmw.ui')
     local anim = require('openmw.animation')
     local Controls = require('openmw.interfaces').Controls
     local storage = require('openmw.storage') -- For settings
     local async = require('openmw.async') -- For settings updates

     local I = require('openmw.interfaces')

     local isBlocking = false
     local hasShieldEquipped = false
     local isInWeaponStance = false
     local hasOneHandedWeapon = false
     local isBlockDebuffed = false -- Track if the debuff is currently applied

     -- Skill and Attribute IDs
     local skills = types.NPC.stats.skills
     local attributes = types.Actor.stats.attributes

     -- Default Settings
     local blockBuffPercent_default = 65
     local weaponDebuffPercent_default = 35
     local speedDebuffPercent_default = 35

     -- Settings Keys
     local settingsGroupKey = 'Settings_ShieldBuffDebuff'

     -- Runtime Settings
     local blockBuffPercent = blockBuffPercent_default
     local weaponDebuffPercent = weaponDebuffPercent_default
     local speedDebuffPercent = speedDebuffPercent_default

     -- Store modifier values for saving/loading
     local savedBlockModifier = 0
     local savedAxeModifier = 0
     local savedBluntModifier = 0
     local savedLongBladeModifier = 0
     local savedShortBladeModifier = 0
     local savedSpeedModifier = 0

     -- Function to apply skill/attribute modifiers
     local function modifySkill(skill, percent, isBuff)
         if percent == 0 then return end
         local modValue = math.floor(skill.base * (percent / 100))
         skill.modifier = skill.modifier + (isBuff and modValue or -modValue)
         return modValue -- Return the modifier value for saving
     end

     local function modifyAttribute(attribute, percent, isBuff)
         if percent == 0 then return end
         local modValue = math.floor(attribute.base * (percent / 100))
         attribute.modifier = attribute.modifier + (isBuff and modValue or -modValue)
         return modValue -- Return the modifier value for saving
     end

     local function updateEquipmentStatus()
         local shield = types.Actor.getEquipment(self, types.Actor.EQUIPMENT_SLOT.CarriedLeft)
         hasShieldEquipped = shield ~= nil and shield.type == types.Armor

         local weapon = types.Actor.getEquipment(self, types.Actor.EQUIPMENT_SLOT.CarriedRight)
         local weaponRecord = weapon and types.Weapon.records[weapon.recordId]
         local weaponTypes = types.Weapon.TYPE
         hasOneHandedWeapon = weaponRecord and (
             weaponRecord.type == weaponTypes.AxeOneHand or
             weaponRecord.type == weaponTypes.ShortBladeOneHand or
             weaponRecord.type == weaponTypes.LongBladeOneHand or
             weaponRecord.type == weaponTypes.BluntOneHand
         )
     end

     local function updateCombatState()
         isInWeaponStance = types.Actor.getStance(self) == types.Actor.STANCE.Weapon
     end

     local function shouldApplyBlockDebuff()
         return isInWeaponStance and hasShieldEquipped and hasOneHandedWeapon and not isBlocking
     end

     local function applyBlockDebuff()
         if shouldApplyBlockDebuff() and not isBlockDebuffed then
             savedBlockModifier = modifySkill(skills.block(self), 100, false) -- Set Block skill to 0
             isBlockDebuffed = true
         elseif not shouldApplyBlockDebuff() and isBlockDebuffed then
             modifySkill(skills.block(self), 100, true) -- Restore Block skill
             isBlockDebuffed = false
         end
     end

     local function removeBlockDebuff()
         if isBlockDebuffed then
             modifySkill(skills.block(self), 100, true) -- Restore Block skill
             isBlockDebuffed = false
         end
     end

     local function canBlock()
         return isInWeaponStance and hasShieldEquipped and hasOneHandedWeapon and not isBlocking
     end

     local function blockBegin(key)
         local isPaused = core.isWorldPaused()
         local mode = I.UI and I.UI:getMode() -- Corrected way to access UI mode

         if isPaused or mode == "Dialogue" or mode == "Inventory" then
             return -- Do nothing if paused or in dialogue/inventory
         end

         updateEquipmentStatus() -- Ensure shield status is up-to-date
             if key.symbol == 'x' and canBlock() and hasShieldEquipped then -- Added hasShieldEquipped check
             isBlocking = true
             Controls.overrideCombatControls(true)
             removeBlockDebuff() -- Ensure the debuff is removed before applying the buff


    1. PresquePlayed
      PresquePlayed
      • member
      • 0 kudos
      part 2 of code

               -- Apply Buffs/Debuffs
               savedBlockModifier = modifySkill(skills.block(self), blockBuffPercent, true)
               savedAxeModifier = modifySkill(skills.axe(self), weaponDebuffPercent, false)
               savedBluntModifier = modifySkill(skills.bluntweapon(self), weaponDebuffPercent, false)
               savedLongBladeModifier = modifySkill(skills.longblade(self), weaponDebuffPercent, false)
               savedShortBladeModifier = modifySkill(skills.shortblade(self), weaponDebuffPercent, false)
               savedSpeedModifier = modifyAttribute(attributes.speed(self), speedDebuffPercent, false)

               I.AnimationController.playBlendedAnimation('shieldraise', {
                   startKey = 'start',
                   stopKey = 'stop',
                   priority = {
                       [anim.BONE_GROUP.LeftArm] = anim.PRIORITY.Weapon,
                   },
                   autoDisable = false,
                   blendMask = anim.BLEND_MASK.LeftArm + anim.BLEND_MASK.Torso + anim.BLEND_MASK.RightArm,
               })
           end
       end

       local function onKeyRelease(key)
           if key.symbol == 'x' then
           local isPaused = core.isWorldPaused()
           local mode = I.UI and I.UI:getMode() -- Corrected way to access UI mode

           if isPaused or mode == "Dialogue" or mode == "Inventory" then
               return -- Do nothing if paused or in dialogue/inventory
           end

               isBlocking = false
               Controls.overrideCombatControls(false)

               -- Remove Buffs/Debuffs
               modifySkill(skills.block(self), blockBuffPercent, false)
               modifySkill(skills.axe(self), weaponDebuffPercent, true)
               modifySkill(skills.bluntweapon(self), weaponDebuffPercent, true)
               modifySkill(skills.longblade(self), weaponDebuffPercent, true)
               modifySkill(skills.shortblade(self), weaponDebuffPercent, true)
               modifyAttribute(attributes.speed(self), speedDebuffPercent, true)

               -- Reapply the debuff *after* the buffs are removed and blocking has stopped
               applyBlockDebuff()

               I.AnimationController.playBlendedAnimation('idle1', {
                   startKey = 'loop start',
                   stopKey = 'loop stop',
                   priority = {
                       [anim.BONE_GROUP.LeftArm] = anim.PRIORITY.Weapon,
                   },
                   autoDisable = true,
               })
           end
       end

       -- Settings Registration
       I.Settings.registerPage({
           key = 'ShieldsUp',
           l10n = 'ShieldsUp',
           name = 'Shields Up',
           description = 'Improved vanilla block experience. By Xe',
       })

       I.Settings.registerGroup({
           key = settingsGroupKey,
           page = 'ShieldsUp',
           l10n = 'ShieldsUp',
           name = 'Settings',
           permanentStorage = true,
           settings = {
               {
                   key = 'blockBuffPercent',
                   default = blockBuffPercent_default,
                   renderer = 'number',
                   name = 'Block Skill Buff (%)',
                   description = 'Percentage to buff the Block skill when blocking. Default: 65',
                   argument = { integer = true, min = 0, max = 100 },
               },
               {
                   key = 'weaponDebuffPercent',
                   default = weaponDebuffPercent_default,
                   renderer = 'number',
                   name = 'Weapon Skill Debuff (%)',
                   description = 'Percentage to debuff weapon skills when blocking. Default: 35',
                   argument = { integer = true, min = 0, max = 100 },
               },
               {
                   key = 'speedDebuffPercent',
                   default = speedDebuffPercent_default,
                   renderer = 'number',
                   name = 'Speed Attribute Debuff (%)',
                   description = 'Percentage to debuff the Speed attribute when blocking. Default: 35',
                   argument = { integer = true, min = 0, max = 100 },
               },
           },
       })

       -- Settings Update Function
       local settingsGroup = storage.playerSection(settingsGroupKey)

       local function updateSettings()
           blockBuffPercent = settingsGroup:get('blockBuffPercent')
           weaponDebuffPercent = settingsGroup:get('weaponDebuffPercent')
           speedDebuffPercent = settingsGroup:get('speedDebuffPercent')
       end

       settingsGroup:subscribe(async:callback(updateSettings))

       -- Save and Load Handlers
       local function onSave()
           return {
               isBlocking = isBlocking,
               isBlockDebuffed = isBlockDebuffed,
               savedBlockModifier = savedBlockModifier,
               savedAxeModifier = savedAxeModifier,
               savedBluntModifier = savedBluntModifier,
               savedLongBladeModifier = savedLongBladeModifier,
               savedShortBladeModifier = savedShortBladeModifier,
               savedSpeedModifier = savedSpeedModifier,
           }
       end

       local function onLoad(data)
           if data then
               isBlocking = data.isBlocking
               isBlockDebuffed = data.isBlockDebuffed

              
    2. PresquePlayed
      PresquePlayed
      • member
      • 0 kudos
      part 3 of code/script
      -- Reapply modifiers (undo previous and then reapply)
               if data.savedBlockModifier ~= 0 then
                   modifySkill(skills.block(self), data.savedBlockModifier * 100 /
      math.floor(skills.block(self).base * (100 / 100)), false) -- Undo
                   modifySkill(skills.block(self), data.savedBlockModifier * 100 /
      math.floor(skills.block(self).base * (100 / 100)), true) -- Reapply
                   savedBlockModifier = data.savedBlockModifier
               end
               if data.savedAxeModifier ~= 0 then
                   modifySkill(skills.axe(self), data.savedAxeModifier * 100 /
      math.floor(skills.axe(self).base * (100 / 100)), true) -- Undo
                   modifySkill(skills.axe(self), data.savedAxeModifier * 100 /
      math.floor(skills.axe(self).base * (100 / 100)), false) -- Reapply
                   savedAxeModifier = data.savedAxeModifier
               end
               if data.savedBluntModifier ~= 0 then
                   modifySkill(skills.bluntweapon(self), data.savedBluntModifier * 100 /
      math.floor(skills.bluntweapon(self).base * (100 / 100)), true) -- Undo
                   modifySkill(skills.bluntweapon(self), data.savedBluntModifier * 100 /
      math.floor(skills.bluntweapon(self).base * (100 / 100)), false) --
      Reapply
                   savedBluntModifier = data.savedBluntModifier
               end
               if data.savedLongBladeModifier ~= 0 then
                   modifySkill(skills.longblade(self), data.savedLongBladeModifier * 100 /
      math.floor(skills.longblade(self).base * (100 / 100)), true) -- Undo
                   modifySkill(skills.longblade(self), data.savedLongBladeModifier * 100 /
      math.floor(skills.longblade(self).base * (100 / 100)), false) --
      Reapply
                   savedLongBladeModifier = data.savedLongBladeModifier
               end
               if data.savedShortBladeModifier ~= 0 then
                   modifySkill(skills.shortblade(self), data.savedShortBladeModifier * 100
      / math.floor(skills.shortblade(self).base * (100 / 100)), true) -- Undo
                   modifySkill(skills.shortblade(self), data.savedShortBladeModifier * 100
      / math.floor(skills.shortblade(self).base * (100 / 100)), false) --
      Reapply
                   savedShortBladeModifier = data.savedShortBladeModifier
               end
               if data.savedSpeedModifier ~= 0 then
                   modifyAttribute(attributes.speed(self), data.savedSpeedModifier * 100 /
      math.floor(attributes.speed(self).base * (100 / 100)), true) -- Undo
                   modifyAttribute(attributes.speed(self), data.savedSpeedModifier * 100 /
      math.floor(attributes.speed(self).base * (100 / 100)), false) --
      Reapply
                   savedSpeedModifier = data.savedSpeedModifier
               end
           end
       end

       return {
           engineHandlers = {
               onKeyPress = blockBegin,
               onKeyRelease = onKeyRelease,
               onEquip = function()
                   updateEquipmentStatus()
                   applyBlockDebuff()
               end,
               onUnequip = function()
                   updateEquipmentStatus()
                   applyBlockDebuff()
               end,
               onStanceChange = function()
                   updateCombatState()
                   updateEquipmentStatus()
                   applyBlockDebuff()
               end,
               onActive = function()
                   updateSettings() -- Initialize settings on activation
                   updateCombatState()
                   updateEquipmentStatus()
                   applyBlockDebuff()
               end,
               onDeactivate = function()
                   removeBlockDebuff()
               end,
               onUpdate = function(dt)
                   updateCombatState()
                   updateEquipmentStatus()
                   -- Only apply the debuff if *not* actively blocking
                   if not isBlocking then
                       applyBlockDebuff()
                   end
               end,
               onSave = onSave,
               onLoad = onLoad,
           },
       }
  2. Explorer1911
    Explorer1911
    • member
    • 44 kudos
    Is a system that allows blocking possible with hand-to-hand/no shield and just a weapon? Or do you know if OpenMW wouldn't be able to support that yet?
  3. SMO1992
    SMO1992
    • member
    • 23 kudos
    how did you remove vanilla blocking? if you want you can build on the features of my mod too, it has its own animation for blocking and blocks based on a button. (edit I see you already have those features, great mod! still curious about how you removed vanilla block as it was an issue for me)
    1. Xerxse
      Xerxse
      • member
      • 3 kudos
      hey man, I used a tweaked version of your mod for some time and yeah I recall the auto blocking. It works by setting the min block chance to 0 and temporarily debuffing Block skill to 0
  4. JuliaRK
    JuliaRK
    • premium
    • 8 kudos
    Probably out of scope for this mod, but I'd love to be able to block without a shield, with just a weapon alone, similar to the later games. Would probably involve a lot more work, though, so I get it if you're not interested.

    Regardless, I really like this as it is, easy endorse from me :)
    1. Xerxse
      Xerxse
      • member
      • 3 kudos
      nah if I could I would. simply said, if its currently possible to do it right someone would have already made it happen.

      but if I could somehow dream up an elaborate stunt then lol why not
    2. SMO1992
      SMO1992
      • member
      • 23 kudos
      It sorta is but it takes a lot of work and would be very very hacky and tedious
  5. dreughjiggers
    dreughjiggers
    • supporter
    • 1 kudos
    Instead of a speed debuff, is it possible to consume fatigue? Tanky classes are already played slow; speed usually isn't a favored attribute, so the sacrifice is sort of pointless. Melee's only hairy when you're pacing fatigue, so you don't get knocked down.
  6. Atanvarn
    Atanvarn
    • member
    • 3 kudos
    Looks great. Could you make it compatible with UI-modes?
    1. Xerxse
      Xerxse
      • member
      • 3 kudos
      I use UI-modes as well but changed its key to something else, are you using something that hinders that?
    2. Atanvarn
      Atanvarn
      • member
      • 3 kudos
      It's set to RMB for me. Where can I change that? It'd be compatible if UI-modes would only open its widget when the weapon is sheathed. Now it activates when raising a shield too. But UI-modes doesn't have a Nexus page, so can't really ask for this fix :)
    3. Xerxse
      Xerxse
      • member
      • 3 kudos
      its binded to your 'inventory' key, you can change it in options > controls > mouse/keyboard
  7. MadsBille
    MadsBille
    • member
    • 1 kudos
    Your mods are awesome dude. If you'll forgive me for being a bit cheeky, you wouldn't be able to make a death knock back mod a'la "rag n'wahs" (or bomberman for magic) could you? It's the only mod left that vanilla morrowind still has over openmw. Just in case you were looking for ideas
    1. Xerxse
      Xerxse
      • member
      • 3 kudos
      someones working on something a little more extra i think, havent seen any progress update in a while though
  8. PresquePlayed
    PresquePlayed
    • member
    • 0 kudos
    Will there be an option to change the block button to another key?
  9. Bwanazz
    Bwanazz
    • member
    • 1 kudos
    It would be nice if there is a video showcase of it. 
  10. christianhulen
    christianhulen
    • premium
    • 19 kudos
    This is REALLY cool! I am hoping for maybe controller support? No biggie if not!
    1. Xerxse
      Xerxse
      • member
      • 3 kudos
      💯% once I figure it out
    2. christianhulen
      christianhulen
      • premium
      • 19 kudos
      Thanks!