Skip to content

Commit

Permalink
Add interop
Browse files Browse the repository at this point in the history
  • Loading branch information
jhaakma committed Jul 29, 2023
1 parent e196343 commit 4534228
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 296 deletions.
5 changes: 3 additions & 2 deletions Data Files/MWSE/mods/mer/drip/common/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ Common.getAllLootObjectIds = function()
return objectIds
end

Common.canBeDripified = function(object)
---@param obj tes3object
Common.canBeDripified = function(obj)
local objIds = Common.getAllLootObjectIds()
return objIds[object.id:lower()] ~= nil
return objIds[obj.id:lower()] ~= nil
end

return Common
138 changes: 110 additions & 28 deletions Data Files/MWSE/mods/mer/drip/components/Modifier.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,60 @@ local common = require("mer.drip.common")
local modifierConfig = common.config.modifiers
local logger = common.createLogger("Modifier")

---@type DripModifier
local Modifier = {}
---@class Drip.Modifier.Effect
---@field id string The effect id. Use tes3.effect mapping.
---@field duration number The duration of the effect.
---@field min number The minimum magnitude of the effect.
---@field max number The maximum magnitude of the effect.
---@field rangeType number The range type derived from tes3.effectRange
---@field attribute number The attribute id. Use tes3.attribute mapping.
---@field skill number The skill id. Use tes3.skill mapping.

function Modifier:validate(modifierData)
---@class Drip.Modifier.Data
---@field prefix string The prefix appended to the loot name. A modifier should have at least a prefix or a suffix.
---@field suffix string The suffix appended to the loot name. A modifier should have at least a prefix or a suffix.
---@field castType number **Required** The cast type of the enchantment. Use tes3.enchantmentType mapping.
---@field chargeCost number The cost of the enchantment. Required when castType is not constant.
---@field maxCharge number The maximum charge of the enchantment. Required when castType is not constant.
---@field effects table<Drip.Modifier.Effect> **Required** The effects to be enchanted onto the loot.
---@field validObjectTypes table<number, boolean> A list of objectTypes that can have this modifier. use tes3.objectType mapping as the key and set value to true. e.g "[tes3.objectType.weapon] = true"
---@field validWeaponTypes table<number, boolean> A list of weaponTypes that can have this modifier. use tes3.weaponType mapping as the key and set value to true. e.g "[tes3.weaponType.shortBlade] = true"
---@field validWeightClasses table<number, boolean> A list of armor weight classes that can have this modifier. use tes3.armorWeightClass mapping as the key and set value to true. e.g "[tes3.armorWeightClass.heavy] = true"
---@field validArmorSlots table<number, boolean> A list of armor slots that can have this modifier. use tes3.armorSlot mapping as the key and set value to true. e.g "[tes3.armorSlot.helmet] = true"\
---@field validClothingSlots table<number, boolean> A list of clothing slots that can have this modifier. use tes3.clothingSlot mapping as the key and set value to true. e.g "[tes3.clothingSlot.amulet] = true"
---@field icon string The path to a custom icon
---@field description string A a description of the effect.
---@field valueMulti number The multiplier for the value of the loot. e.g 1.5 will increase the value by 50%
---@field value number Adds a flat value to the loot value.
---@field multipliers table A list of object fields that will be multiplied by the value
---@field modifications table A list of object fields that will be modified by the value

---@class Drip.Modifier : Drip.Modifier.Data
local Modifier = {
---@type boolean Whether this modifier is a wild modifier
wild = nil
}

---------------------------------------------------
-- Static Methods
---------------------------------------------------

--Constructor
---@param data Drip.Modifier.Data
function Modifier:new(data)
local isValid, errorMsg = Modifier.validate(data)
if not isValid then
logger:debug("Invalid modifier data: %s", errorMsg)
return nil
end
if data == nil then return end
local modifier = setmetatable(data, self)
self.__index = self

return modifier
end

function Modifier.validate(modifierData)
if not modifierData then return nil end
local dripModifierFields = {
prefix = "string",
Expand Down Expand Up @@ -35,20 +85,67 @@ function Modifier:validate(modifierData)
return true
end

---@param data DripModifierData
function Modifier:new(data)
local isValid, errorMsg = self:validate(data)
if not isValid then
logger:debug("Invalid modifier data: %s", errorMsg)
return nil
function Modifier.getRandomModifier(object, list)
list = list or math.random() < 0.5 and modifierConfig.prefixes or modifierConfig.suffixes
local attempts = 0
local MAX_ATTEMPTS = 100
local modifier
while attempts < MAX_ATTEMPTS do
modifier = Modifier:new(table.choice(list))
if modifier and modifier:validForObject(object) then
return modifier
end
attempts = attempts + 1
end
if data == nil then return end
local modifier = setmetatable(data, self)
self.__index = self
logger:trace("Failed to find a modifier for %s", object.name)
end

return modifier

function Modifier.getFirstModifier(object)
if math.random(100) <= common.config.mcm.modifierChance then
local list = math.random() < 0.5 and modifierConfig.prefixes or modifierConfig.suffixes
return Modifier.getRandomModifier(object, list)
end
end

--[[
Generate a random set of modifiers for the given object
]]
function Modifier.rollForModifiers(object)
--Roll for fist modifier, and if it succeeds, roll for second modifier
--First modifier has 50/50 chance of being prefix or suffix
local modifiers = {}

logger:trace("Object: %s", object.name)

local firstModifier = Modifier.getFirstModifier(object)
if not firstModifier then
return
end
table.insert(modifiers, firstModifier)
local secondModifier
--If first modifier was wild, guarantee a second.
--If wild is the second modifier, we already have another to apply the wild to
if firstModifier.wild or math.random(100) < common.config.mcm.secondaryModifierChance then
if firstModifier.prefix then
secondModifier = Modifier.getRandomModifier(object, modifierConfig.suffixes)
else
secondModifier = Modifier.getRandomModifier(object, modifierConfig.prefixes)
end
end
if secondModifier then
table.insert(modifiers, secondModifier)
end

if #modifiers > 0 then
return modifiers
end
end

---------------------------------------------------
-- Instance Methods
---------------------------------------------------

function Modifier:validForObject(object)
logger:trace("Checking if modifier is valid for object %s", object.id)

Expand Down Expand Up @@ -145,19 +242,4 @@ function Modifier:validForObject(object)
return true
end

function Modifier:getRandomModifier(object, list)
list = list or math.random() < 0.5 and modifierConfig.prefixes or modifierConfig.suffixes
local attempts = 0
local MAX_ATTEMPTS = 100
local modifier
while attempts < MAX_ATTEMPTS do
modifier = Modifier:new(table.choice(list))
if modifier and modifier:validForObject(object) then
return modifier
end
attempts = attempts + 1
end
logger:trace("Failed to find a modifier for %s", object.name)
end

return Modifier
54 changes: 9 additions & 45 deletions Data Files/MWSE/mods/mer/drip/controllers/lootPlacement.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,6 @@ local common = require("mer.drip.common")
local logger = common.createLogger("LootPlacement")
local Loot = require("mer.drip.components.Loot")
local Modifier = require("mer.drip.components.Modifier")
local modifierConfig = common.config.modifiers

local function getFirstModifier(object)
if math.random(100) <= common.config.mcm.modifierChance then
local list = math.random() < 0.5 and modifierConfig.prefixes or modifierConfig.suffixes
return Modifier:getRandomModifier(object, list)
end
end

local function rollForModifiers(object)
--Roll for fist modifier, and if it succeeds, roll for second modifier
--First modifier has 50/50 chance of being prefix or suffix
local modifiers = {}

logger:trace("Object: %s", object.name)

local firstModifier = getFirstModifier(object)
if not firstModifier then
return
end
table.insert(modifiers, firstModifier)
local secondModifier
--If first modifier was wild, guarantee a second.
--If wild is the second modifier, we already have another to apply the wild to
if firstModifier.wild or math.random(100) < common.config.mcm.secondaryModifierChance then
if firstModifier.prefix then
secondModifier = Modifier:getRandomModifier(object, modifierConfig.suffixes)
else
secondModifier = Modifier:getRandomModifier(object, modifierConfig.prefixes)
end
end
if secondModifier then
table.insert(modifiers, secondModifier)
end

if #modifiers > 0 then
return modifiers
end
end


local function addToRef(reference)
Expand All @@ -55,7 +16,7 @@ local function addToRef(reference)
for _, stack in pairs(inventory) do
--Check if it's a lootifiable object
if common.canBeDripified(stack.object) then
local modifiers = rollForModifiers(stack.object)
local modifiers = Modifier.rollForModifiers(stack.object)
if modifiers and #modifiers > 0 then
logger:debug("Converting %s to loot", stack.object.name)
local loot = Loot:new{
Expand Down Expand Up @@ -92,6 +53,10 @@ local function checkSpawnerDripified(spawner)
logger:debug("checkSpawnerDripified: Spawner %s has not beed dripified, setting state to 1 and delaying a frame to set to 2", spawner)
spawner.data.dripifiedSpawnerState = 1
local safeRef = tes3.makeSafeObjectHandle(spawner)
if not safeRef then
logger:error("checkSpawnerDripified: Failed to make safe handle for spawner %s", spawner)
return
end
timer.delayOneFrame(function()
if safeRef:valid() then
logger:debug("checkSpawnerDripified: Setting spawner %s state to 2", spawner)
Expand All @@ -115,21 +80,20 @@ end
local function onLeveledItemPicked(e)
if not common.config.mcm.enabled then return end
if not e.pick then return end
local objectIds = common.getAllLootObjectIds()
if objectIds[e.pick.id:lower()] then
if common.canBeDripified(e.pick) then
if checkSpawnerDripified(e.spawner) == true then return end
local object = e.pick
local modifiers = rollForModifiers(object)
local modifiers = Modifier.rollForModifiers(object)
if modifiers then
logger:debug("Converting leveled item %s to loot", object.name)
local loot = Loot:new{
baseObject = object,
baseObject = object, ---@diagnostic disable-line: assign-type-mismatch
modifiers = modifiers,
}
if loot then
logger:debug("Converted to %s", loot.object.name)
logger:debug("Replacing existing object with enchanted version")
e.pick = loot.object
e.pick = loot.object ---@diagnostic disable-line: assign-type-mismatch
loot:persist()
end
end
Expand Down
121 changes: 0 additions & 121 deletions Data Files/MWSE/mods/mer/drip/customEffects/infectious.lua

This file was deleted.

Loading

0 comments on commit 4534228

Please sign in to comment.
  翻译: