Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@celediel
Last active March 9, 2022 00:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save celediel/c6a10113f594b540b2d8a15775844d73 to your computer and use it in GitHub Desktop.
Save celediel/c6a10113f594b540b2d8a15775844d73 to your computer and use it in GitHub Desktop.
Morrowind Containers Animated - quickloot compatibility
local modConfigMenu = {}
local pane
local skipAnimKeyButton
local this = {}
local itemsButtonText = {[0] = 'Skip animation', 'Hide items when animation is playing', 'Transfer items to the player inventory', 'Place items inside the container when they are loaded'}
local tItemsButtonAlign = {[0] = 0.45, 0.605, 0.61, 0.81}
local function RegisterModConfig()
-- mwse.log('RegisterModConfig %s', isModActive)
if tes3.isModActive('MW Containers Animated.esp') then
mwse.registerModConfig("MW Containers Animated", modConfigMenu)
end
end
-- fires before initialized event
event.register("modConfigReady", RegisterModConfig)
local function GetKeybindName(scancode)
return tes3.findGMST(tes3.gmst.sKeyName_00 + scancode).value
end
function modConfigMenu.onClose(container)
mwse.saveConfig('MWCA_config', this.config)
end
function modConfigMenu.onCreate(container)
-- mwse.log('config.stayOpen init %s', this.config.stayOpen)
pane = container:createThinBorder{}
pane.widthProportional = 1.0
pane.heightProportional = 1.0
pane.paddingAllSides = 12
pane.flowDirection = "top_to_bottom"
local header = pane:createLabel{ text = 'MW Containers Animated version 2.06' }
header.color = tes3ui.getPalette("header_color")
header.borderBottom = 35
local stayOpenBlock = pane:createBlock()
stayOpenBlock.flowDirection = "left_to_right"
stayOpenBlock.widthProportional = 1.0
stayOpenBlock.autoHeight = true
stayOpenBlock:createLabel({ text = 'Containers stay open :' })
local stayOpenButton = stayOpenBlock:createButton({ text = this.config.stayOpen and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value })
stayOpenButton.absolutePosAlignX = 0.4
-- stayOpenButton.paddingTop = 2
stayOpenButton:register("mouseClick", function(e)
this.config.stayOpen = not this.config.stayOpen
stayOpenButton.text = this.config.stayOpen and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value
end)
-- ! QuickLoot mode or og mode ! --
local activateModeBlock = pane:createBlock()
activateModeBlock.flowDirection = "left_to_right"
activateModeBlock.widthProportional = 1.0
activateModeBlock.autoHeight = true
activateModeBlock:createLabel({ text = "Activation mode: :" })
local activateModeButton = activateModeBlock:createButton({ text = this.config.activateMode and "on activate" or "quickloot mode" })
activateModeButton.absolutePosAlignX = 0.4
activateModeButton:register("mouseClick", function(e)
this.config.activateMode = not this.config.activateMode
activateModeButton.text = this.config.activateMode and "on activate" or "quickloot mode"
end)
local animateWhileRunningBlock = pane:createBlock()
animateWhileRunningBlock.flowDirection = "left_to_right"
animateWhileRunningBlock.widthProportional = 1.0
animateWhileRunningBlock.autoHeight = true
animateWhileRunningBlock:createLabel({ text = 'Animate while running\nin quickloot mode :' })
local animateWhileRunningButton = animateWhileRunningBlock:createButton({ text = this.config.animateWhileRunning and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value })
animateWhileRunningButton.absolutePosAlignX = 0.4
-- animateWhileRunningButton.paddingTop = 2
animateWhileRunningButton:register("mouseClick", function(e)
this.config.animateWhileRunning = not this.config.animateWhileRunning
animateWhileRunningButton.text = this.config.animateWhileRunning and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value
end)
local playSoundBlock = pane:createBlock()
playSoundBlock.flowDirection = "left_to_right"
playSoundBlock.widthProportional = 1.0
playSoundBlock.autoHeight = true
playSoundBlock:createLabel({ text = 'Play sound during animation :' })
local playSoundButton = playSoundBlock:createButton({ text = this.config.playSound and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value })
playSoundButton.absolutePosAlignX = 0.4
playSoundButton:register("mouseClick", function(e)
this.config.playSound = not this.config.playSound
playSoundButton.text = this.config.playSound and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value
end)
local itemsBlock = pane:createBlock()
itemsBlock.widthProportional = 1.0
itemsBlock.autoHeight = true
itemsBlock.paddingBottom = 13
itemsBlock:createLabel({text = "When items placed on container\ninterfere with animation"})
local itemsButton = itemsBlock:createButton({ text = itemsButtonText[this.config.items] })
itemsButton.absolutePosAlignX = tItemsButtonAlign[this.config.items]
itemsButton.paddingLeft = 9
itemsButton.paddingRight = 9
itemsButton:register("mouseClick", function(e)
this.config.items = itemsButtonText[this.config.items + 1] and this.config.items + 1 or 0
-- tes3.messageBox(itemsButtonText[this.config.items])
itemsButton.text = itemsButtonText[this.config.items]
itemsButton.absolutePosAlignX = tItemsButtonAlign[this.config.items]
-- pane:updateLayout()
end)
local barrelBlock = pane:createBlock()
barrelBlock.flowDirection = "left_to_right"
barrelBlock.widthProportional = 1.0
barrelBlock.autoHeight = true
barrelBlock:createLabel({ text = 'Barrel model has rivets' })
local playSoundButton = barrelBlock:createButton({ text = this.config.barrelRivet and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value })
playSoundButton.absolutePosAlignX = 0.4
playSoundButton:register("mouseClick", function(e)
tes3.messageBox('You have to restart the game after you change this option')
this.config.barrelRivet = not this.config.barrelRivet
playSoundButton.text = this.config.barrelRivet and tes3.findGMST(tes3.gmst.sYes).value or tes3.findGMST(tes3.gmst.sNo).value
end)
local sliderBlock = pane:createBlock()
sliderBlock.widthProportional = 1.0
sliderBlock.autoHeight = true
sliderBlock:createLabel({text = "Animation time percent to wait before\nshowing container's contents :"})
local sliderValue = this.config.animTimeToWait
local sliderLabel = sliderBlock:createLabel({ text = tostring(sliderValue) })
sliderLabel.absolutePosAlignX = 0.57
sliderLabel.minWidth = 30
local slider = sliderBlock:createSlider({ current = sliderValue, max = 200 , step = 1, jump = 25 })
slider.borderLeft = 20
slider.absolutePosAlignY = 1.0
slider.width = 330
slider:register("PartScrollBar_changed", function(e)
this.config.animTimeToWait = slider:getPropertyInt("PartScrollBar_current")
sliderLabel.text = this.config.animTimeToWait
end)
-- local skipAnimKeyBlock = pane:createBlock()
-- skipAnimKeyBlock.widthProportional = 0.6
-- skipAnimKeyBlock.autoHeight = true
-- skipAnimKeyBlock:createLabel({text = 'Container animation will be skipped if\nactivated while this key is pressed down'})
-- skipAnimKeyBlock.flowDirection = "left_to_right"
-- skipAnimKeyButton = skipAnimKeyBlock:createButton({ text = GetKeybindName(this.config.skipAnimKey)})
-- skipAnimKeyButton.absolutePosAlignX = 1.0
-- skipAnimKeyButton.paddingTop = 2
-- skipAnimKeyButton.borderRight = 6
-- skipAnimKeyButton:register("mouseClick", function(e)
-- tes3.messageBox('mouseClick')
-- skipAnimKeyButton.widget.state = 4
-- pane:updateLayout()
-- event.register("keyDown", KeybindDown)
-- end)
end
local function KeybindDown(e)
-- If keycode not ESC
tes3.messageBox('key pressed %s', GetKeybindName(e.keyCode))
if e.keyCode ~= 1 then
this.config.skipAnimKey = e.keyCode
skipAnimKeyButton.text = GetKeybindName(e.keyCode)
end
skipAnimKeyButton.widget.state = 1
pane:updateLayout()
event.unregister("keyDown", KeybindDown)
end
return this
local tMeshNamesToReplace = {}
local sContainerType
local containerRef
local openLockSound
local pickUpSound
local openLockFailSound
local sKeyUsedGMST
local tOpenSounds = {}
local tCloseSounds = {}
local tUpdatedCells = {}
local tContainerTypes = {}
local iActivationDist
local iActivationDistGMST
local openTimer
local closeTimer
-- local tCompatibleScripts = {}
local tNotSafeCtypes = {} -- items placed on them clip into them when animation plays
local playerRef
local tCellsChecked
local tObjectTypesToCheck = {}
local tMovableItemsOnCont = {}
local tStaticItemsOnCont = {}
local tBigStaticsOnCont = {}
local tDontCheck = {}
-- local tOverriddenScripts = {}
-- local tLocalScriptsToRun = {}
local tContHeightToCheck = {} -- Container Height % To Check when detecting items on top of it
local v3up = tes3vector3.new(0,0,1)
local v3down = tes3vector3.new(0,0,-1)
local itemsConfig = {['SkipAnim'] = 0, ['Hide'] = 1, ['TransferToPlayer'] = 2, ['TransferToCont'] = 3}
local config = mwse.loadConfig('MWCA_config') or {stayOpen = true, activateMode = true, animateWhileRunning = true, playSound = true, items = 0, animTimeToWait = 100, barrelRivet = true, version = 2.06}
local iContainerType = tes3.objectType.container
local idistToCheck = 222 -- distance used when looking for items placed on chests
-- local autoUnlock = false
local graphicHerbalism = include("graphicHerbalism.interop")
local modConfig = require("MWCA.configMenu")
modConfig.config = config
local function GetCellName(cell)
local sCellName = cell.id
if not cell.isInterior then
sCellName = sCellName..' '..cell.gridX..' '..cell.gridY
end
return sCellName
end
local function GetContainerType(ref)
local dir, name = ref.object.mesh:match("(.-)([^\\]+)$")
name = name:lower()
name = name:gsub(".nif", "")
return tContainerTypes[name]
end
local function IsRefPickUpable(ref)
-- check tObjectTypesToCheck[ref.object.objectType] before this
local iType = ref.object.objectType
if iType == tes3.objectType.static or iType == tes3.objectType.activator or iType == iContainerType then
return false
end
if iType == tes3.objectType.light then
return ref.object.canCarry
end
return true
end
local function BigStatic(cRef, ref)
if ref.object.boundingBox.max.x - ref.object.boundingBox.min.x >=cRef.object.boundingBox.max.x - cRef.object.boundingBox.min.x or ref.object.boundingBox.max.y - ref.object.boundingBox.min.y >= cRef.object.boundingBox.max.y - cRef.object.boundingBox.min.y then
return true
end
return false
end
local function IsRefOnChest(cRef, ref)
-- mwse.log('IsRefOnChest %s %s', cRef.object.id, ref.object.id)
-- local dist = cRef.object.boundingBox.max.z - cRef.object.boundingBox.min.z - ref.object.boundingBox.min.z
local fContHeight = cRef.object.boundingBox.max.z - cRef.object.boundingBox.min.z
local dist = -ref.object.boundingBox.min.z + fContHeight * tContHeightToCheck[GetContainerType(cRef)]
local result = tes3.rayTest{position = ref.position, direction = v3down, maxDistance = dist, findAll = true, useModelBounds = false, useBackTriangles = true, ignore = {ref}}
if result then
for i, hit in pairs(result) do
if hit.reference then
-- mwse.log('ray test down hit #%d %s', i, hit.reference.id)
if hit.reference.id == cRef.object.id then
-- mwse.log('%s is on top %s', ref.object.id, cRef.object.id)
return true
elseif BigStatic(cRef, hit.reference) then
-- mwse.log('%s Big Static on %s', hit.reference.id, cRef.object.id)
return false
end
end
end
end
return false
end
local function GetBoundingBoxVertexPositions(position, orientation, boundingBoxMin,boundingBoxMax)
-- need function to get bounding box position
-- using hack for now
local bBoxMinX = boundingBoxMin.x
local bBoxMinY = boundingBoxMin.y
local bBoxMaxX = boundingBoxMax.x
local bBoxMaxY = boundingBoxMax.y
if orientation.z ~= 0 then
bBoxMinX = math.min(boundingBoxMin.y, boundingBoxMin.x)
bBoxMinY = math.min(boundingBoxMin.y, boundingBoxMin.x)
bBoxMaxX = math.max(boundingBoxMax.y, boundingBoxMax.x)
bBoxMaxY = math.max(boundingBoxMax.y, boundingBoxMax.x)
end
local posX = position.x
local posY = position.y
local x = posX + bBoxMinX
local y = posY + bBoxMinY
local z = position.z + boundingBoxMin.z
local pos0 = tes3vector3.new(x,y,z)
x = posX + bBoxMaxX
local pos1 = tes3vector3.new(x,y,z)
x = posX + bBoxMinX
y = posY + bBoxMaxY
local pos2 = tes3vector3.new(x,y,z)
y = posY + bBoxMinY
z = position.z + boundingBoxMax.z
local pos3 = tes3vector3.new(x,y,z)
x = posX + bBoxMaxX
y = posY + bBoxMaxY
local pos4 = tes3vector3.new(x,y,z)
x = posX + bBoxMinX
local pos5 = tes3vector3.new(x,y,z)
x = posX + bBoxMaxX
y = posY + bBoxMinY
local pos6 = tes3vector3.new(x,y,z)
y = posY + bBoxMaxY
z = position.z + boundingBoxMin.z
local pos7 = tes3vector3.new(x,y,z)
return {pos0, pos1, pos2, pos3, pos4, pos5, pos6, pos7}
end
local function IsAnotherRefInside(refWithBBox, refToFind, doubleMaxZ)
local tBBvertexPos = GetBoundingBoxVertexPositions(refWithBBox.position:copy(), refWithBBox.orientation:copy(), refWithBBox.object.boundingBox.min:copy(), refWithBBox.object.boundingBox.max:copy())
local xMin = math.min(tBBvertexPos[1].x, tBBvertexPos[2].x, tBBvertexPos[3].x, tBBvertexPos[4].x, tBBvertexPos[5].x, tBBvertexPos[6].x, tBBvertexPos[7].x, tBBvertexPos[8].x)
local xMax = math.max(tBBvertexPos[1].x, tBBvertexPos[2].x, tBBvertexPos[3].x, tBBvertexPos[4].x, tBBvertexPos[5].x, tBBvertexPos[6].x, tBBvertexPos[7].x, tBBvertexPos[8].x)
local yMin = math.min(tBBvertexPos[1].y, tBBvertexPos[2].y, tBBvertexPos[3].y, tBBvertexPos[4].y, tBBvertexPos[5].y, tBBvertexPos[6].y, tBBvertexPos[7].y, tBBvertexPos[8].y)
local yMax = math.max(tBBvertexPos[1].y, tBBvertexPos[2].y, tBBvertexPos[3].y, tBBvertexPos[4].y, tBBvertexPos[5].y, tBBvertexPos[6].y, tBBvertexPos[7].y, tBBvertexPos[8].y)
local zMin = math.min(tBBvertexPos[1].z, tBBvertexPos[2].z, tBBvertexPos[3].z, tBBvertexPos[4].z, tBBvertexPos[5].z, tBBvertexPos[6].z, tBBvertexPos[7].z, tBBvertexPos[8].z)
local zMax = math.max(tBBvertexPos[1].z, tBBvertexPos[2].z, tBBvertexPos[3].z, tBBvertexPos[4].z, tBBvertexPos[5].z, tBBvertexPos[6].z, tBBvertexPos[7].z, tBBvertexPos[8].z)
if doubleMaxZ then -- detect items placed on chests
zMax = zMax + zMax - zMin
end
local x = refToFind.position.x
local y = refToFind.position.y
local z = refToFind.position.z
-- detect tall objects on small chests
if refToFind.object.boundingBox then
z = refToFind.position.z + refToFind.object.boundingBox.min.z
end
if x > xMin and x < xMax then
if y > yMin and y < yMax then
if z > zMin and z < zMax then
return true
end
end
end
return false
end
local function IsBigStaticAbove(cRef)
-- mwse.log('IsBigStaticAbove %s', cRef.object.id)
local fContHeight = cRef.object.boundingBox.max.z - cRef.object.boundingBox.min.z
local dist = cRef.object.boundingBox.max.z + fContHeight * tContHeightToCheck[GetContainerType(cRef)]
local result = tes3.rayTest{position = cRef.position, direction = v3up, maxDistance = dist, findAll = true, useModelBounds = false, useBackTriangles = true, ignore = {cRef} }
-- local eggPos = tes3vector3.new(cRef.position.x,cRef.position.y,cRef.position.z+dist)
-- local egg = tes3.createReference {object = 'food_kwama_egg_01', position = eggPos, orientation = tes3vector3.new(0,0,0), cell = cRef.cell }
-- egg.scale = 0.2
if result then
for i, hit in pairs(result) do
if hit.reference and BigStatic(cRef, hit.reference) then
-- mwse.log('%s Big Static Above %s', hit.reference.object.id, cRef.object.id)
return true
end
end
end
return false
end
local function SortItems(cRef)
local tRefsToRemove = {}
-- shelf's position can be anywhere so check if it's above
-- if not cRef.data.AC_skipAnim then
-- for ref, _ in pairs(tBigStaticsOnCont[cRef]) do
-- if RayTestUp(cRef, ref) then
-- cRef.data.AC_skipAnim = true
-- cRef.modified = true
-- break
-- end
-- end
-- end
for ref, _ in pairs(tStaticItemsOnCont[cRef]) do
if not IsRefOnChest(cRef, ref) then
table.insert(tRefsToRemove, ref)
end
end
for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
if not IsRefOnChest(cRef, ref) then
table.insert(tRefsToRemove, ref)
end
end
for _, ref in pairs(tRefsToRemove) do
if tMovableItemsOnCont[cRef][ref] then
tMovableItemsOnCont[cRef][ref] = nil
elseif tStaticItemsOnCont[cRef][ref] then
tStaticItemsOnCont[cRef][ref] = nil
end
end
local iTableLength = table.size(tStaticItemsOnCont[cRef])
if iTableLength > 0 then
cRef.data.AC_staticItems = true
cRef.modified = true
elseif iTableLength == 0 then
cRef.modified = true
cRef.data.AC_staticItems = nil
end
iTableLength = table.size(tMovableItemsOnCont[cRef])
if iTableLength > 0 then
cRef.modified = true
cRef.data.AC_movableItems = true
elseif iTableLength == 0 then
cRef.modified = true
cRef.data.AC_movableItems = nil
end
-- if tStaticItemsOnCont[cRef] then
-- for ref, _ in pairs(tStaticItemsOnCont[cRef]) do
-- mwse.log('Static Item On Cont %s %s', cRef.object.id, ref.object.id)
-- end
-- end
-- if tMovableItemsOnCont[cRef] then
-- for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
-- mwse.log('Movable Item On Cont %s %s', cRef.object.id, ref.object.id)
-- end
-- end
end
local function GetItems(cell, cRef)
-- mwse.log('GetItems %s', cRef.object.id)
tStaticItemsOnCont[cRef] = {}
tMovableItemsOnCont[cRef] = {}
tBigStaticsOnCont[cRef] = {}
if not cRef.data.AC_skipAnim and IsBigStaticAbove(cRef) then
cRef.data.AC_skipAnim = true
cRef.modified = true
return
end
for iType, _ in pairs(tObjectTypesToCheck) do
for ref in cell:iterateReferences(iType) do
if ref ~= cRef and not ref.deleted and ref.object.script == nil and not tDontCheck[ref.object.id] then
if not ref.disabled or (ref.disabled and ref.data.AC_disabled) then
-- mwse.log('pos %s %s', cRef.position, ref.position)
local fDistToContainer = cRef.position:distance(ref.position)
-- mwse.log('fDistToContainer %d', fDistToContainer)
if fDistToContainer < idistToCheck and IsAnotherRefInside(cRef, ref, true) then
if not IsRefPickUpable(ref) then
if BigStatic(cRef, ref) then
tBigStaticsOnCont[cRef][ref] = true
else
tStaticItemsOnCont[cRef][ref] = true
end
else -- PickUpable
tMovableItemsOnCont[cRef][ref] = true
end
end
end
end
end
end
SortItems(cRef)
end
local function EnableItems(cRef)
if cRef.data.AC_staticItems then
if not tStaticItemsOnCont[cRef] then -- game reloaded
GetItems(playerRef.cell, cRef)
end
for ref, _ in pairs(tStaticItemsOnCont[cRef]) do
tes3.setEnabled {reference = ref, enabled = true}
ref.modified = true
ref.data.AC_disabled = nil
end
end
if cRef.data.AC_movableItems then
if not tMovableItemsOnCont[cRef] then
GetItems(playerRef.cell, cRef)
end
for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
tes3.setEnabled {reference = ref, enabled = true}
ref.data.AC_disabled = nil
ref.modified = true
end
end
end
local function DisableItems(cRef)
-- mwse.log('DisableItems %s', cRef.object.id)
if cRef.data.AC_staticItems then
for ref, _ in pairs(tStaticItemsOnCont[cRef]) do
ref.data.AC_disabled = true
ref.modified = true
tes3.setEnabled {reference = ref, enabled = false}
end
end
if cRef.data.AC_movableItems then
for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
ref.data.AC_disabled = true
ref.modified = true
tes3.setEnabled {reference = ref, enabled = false}
end
end
end
local function CloseAnimationEnd()
-- tes3.messageBox('Close Animation End %s', containerRef.object.id)
containerRef.data.AC_state = 'closed'
containerRef.modified = true
EnableItems(containerRef)
end
local function PlayCloseAnimation(cRef)
cRef.data.AC_state = 'closing'
cRef.modified = true
tes3.playAnimation {reference = cRef, group = 2, startFlag = 1}
local animDuration = 0.5
if string.find(sContainerType, 'Dwemer') or string.find(sContainerType, 'daedric') or string.find(sContainerType, 'cauldron') then
animDuration = animDuration + animDuration
end
local closeSound = tCloseSounds[sContainerType]
if config.playSound and closeSound then
tes3.playSound {sound = closeSound, reference = cRef}
end
closeTimer = timer.start{duration = animDuration, callback = CloseAnimationEnd }
end
local function OnMenuExit(eventData)
if not config.stayOpen and containerRef.data.AC_state == 'open' then
-- mwse.log("[MWCA] menu exit close")
PlayCloseAnimation(containerRef)
end
event.unregister("menuExit", OnMenuExit)
end
local function OpenAnimationEnd()
if openTimer then
openTimer:cancel() -- timer is still active
end
-- mwse.log('OpenAnimationEnd openTimer state go %d', openTimer.state)
containerRef.data.AC_state = 'openAnimDone'
containerRef.modified = true
-- event.register("menuEnter", OnMenuEnter)
if config.activateMode then
if not config.stayOpen then
event.register("menuExit", OnMenuExit)
end
playerRef:activate(containerRef)
end
end
local function OpenAnimEndGH()
if openTimer then
openTimer:cancel() -- timer is still active
end
-- mwse.log('OpenAnimationEnd openTimer state go %d', openTimer.state)
containerRef.data.AC_state = 'openAnimDone'
containerRef.modified = true
local switchNode = containerRef.sceneNode:getObjectByName("HerbalismSwitch")
if switchNode then
switchNode.switchIndex = 1 -- HARVESTED
end
playerRef:activate(containerRef)
end
local function PlayOpenAnimation(cRef)
-- tes3.messageBox('PlayOpenAnimation %s', cRef.object.id)
cRef.data.AC_state = 'opening'
cRef.modified = true
tes3.playAnimation {reference = cRef, group = 1, startFlag = 1}
-- timer.start{duration = 3, type = timer.simulate, callback = OpenAnimationEnd}
local animDuration = 0.5
if string.find(sContainerType, 'cauldron') or string.find(sContainerType, 'daedric') or string.find(sContainerType, 'Dwemer') then
animDuration = 1.0
end
animDuration = animDuration * config.animTimeToWait / 100
local openSound = tOpenSounds[sContainerType]
if config.playSound and openSound then
tes3.playSound{sound = openSound, reference = cRef}
end
if animDuration == 0 then
OpenAnimationEnd()
else
openTimer = timer.start{duration = animDuration, callback = OpenAnimationEnd }
end
end
local function PlayGHkollopOpenAnimation(cRef)
-- tes3.messageBox('Play kollop Open Animation %s', cRef.object.id)
cRef.data.AC_state = 'opening'
cRef.modified = true
local switchNode = cRef.sceneNode:getObjectByName("HerbalismSwitch")
if switchNode then
switchNode.switchIndex = 2 -- empty
end
tes3.playAnimation{reference = cRef, group = 1, startFlag = 1}
local animDuration = 0.5 * config.animTimeToWait / 100
if animDuration == 0 then
OpenAnimEndGH()
else
openTimer = timer.start{duration = animDuration, callback = OpenAnimEndGH }
end
end
local function HandleActivation(cRef, quick)
if not cRef then
return
end
if cRef.object.objectType ~= iContainerType then
return
end
sContainerType = GetContainerType(cRef)
if not sContainerType then
return
end
-- mwse.log('OnActivateObject %s', sContainerType)
if not cRef:testActionFlag(tes3.actionFlag.useEnabled) then
-- local script has 'onactivate'
return
end
if cRef.data.AC_state == nil then
cRef.data.AC_state = 'closed'
cRef.modified = true
end
local sState = cRef.data.AC_state
--[[
if cRef.object.script ~= nil then
local sScriptID = cRef.object.script.id
-- mwse.log("container with script %s %s",cRef.object.id, cRef.object.script.id)
if not tCompatibleScripts[sScriptID] then
return
end
-- if tOverriddenScripts[sScriptID] and cRef.data.AC_state == 'closed' then
-- if not tLocalScriptsToRun[sScriptID] then
-- mwse.log('run local script %s', sScriptID)
-- tLocalScriptsToRun[sScriptID] = true
-- end
-- end
end
--]]
-- mwse.log("OnActivateObject %s %s", cRef.object.id, sContainerType)
local hasKey = false
if cRef.lockNode and cRef.lockNode.level == 0 and cRef.lockNode.key then
-- tes3.messageBox('lockNode.level == 0 key')
cRef.lockNode.level = 1
cRef.modified = true
end
if tes3.getLocked{reference = cRef} then
-- if autoUnlock then
-- tes3.unlock {reference = cRef}
-- end
if cRef.lockNode.key then
if mwscript.getItemCount{reference = playerRef, item = cRef.lockNode.key.id} > 0 then
local sKeyUsed = cRef.lockNode.key.name..' '..sKeyUsedGMST
tes3.messageBox('%s', sKeyUsed)
tes3.unlock {reference = cRef}
cRef.modified = true
-- cRef.lockNode.locked = false
-- cRef.lockNode.level = 0
tes3.playSound {sound = openLockSound, reference = cRef}
hasKey = true
end
end
if not hasKey then
return
end
end
-- another container is opening
if openTimer and openTimer.state == 0 and containerRef ~= cRef then
openTimer:cancel()
containerRef.data.AC_state = 'open'
containerRef.modified = true
if not config.stayOpen then
-- mwse.log("[MWCA] another container opening close")
PlayCloseAnimation(containerRef)
end
-- tes3.messageBox('cancel timer')
end
-- another container is closing
if closeTimer and closeTimer.state == 0 and containerRef ~= cRef then
EnableItems(containerRef)
closeTimer:cancel()
containerRef.data.AC_state = 'closed'
containerRef.modified = true
-- tes3.messageBox('cancel timer')
end
containerRef = cRef
-- local sState = cRef.data.AC_state or 'closed'
-- if #ref.object.inventory == 0 then
if graphicHerbalism and sContainerType == 'kollop' then
-- tes3.messageBox('GH kollop AC_state %s', cRef.data.AC_state)
local iGHstate = cRef.data.GH or 0
if iGHstate == 1 then -- opened
-- tes3.messageBox('activate opened kollop')
elseif sState == 'closed' and iGHstate == 0 then
PlayGHkollopOpenAnimation(cRef)
elseif sState == 'openAnimDone' then
-- tes3.messageBox('GH kollop openAnimDone AC_state %s', cRef.data.AC_state)
cRef.data.AC_state = 'open'
return -- activate
end
elseif sState == 'closed' then
-- forceInstance(cRef)
iActivationDist = math.max(cRef.position:distance(playerRef.position), iActivationDistGMST)
local trapSpell = tes3.getTrap {reference = cRef}
if trapSpell and not quick then
tes3.playSound{sound = openLockFailSound, reference = cRef}
-- tes3.setTrap {reference = cRef, spell = nil}
cRef.lockNode.trap = nil -- remove trap
-- tes3.messageBox('cast trap %s', trapSpell.id)
-- cast trap spell without waiting for activation
if not hasKey then
local fDistToContainer = cRef.position:distance(playerRef.position)
if tes3.mobilePlayer.telekinesis > 0 and iActivationDist > iActivationDistGMST then -- opened with telekinesis
elseif fDistToContainer <= iActivationDist then
tes3.cast{reference = cRef, target = playerRef, spell = trapSpell}
end
end
end
if tNotSafeCtypes[sContainerType] then
GetItems(playerRef.cell, cRef)
if config.items == itemsConfig.SkipAnim then
if cRef.data.AC_movableItems or cRef.data.AC_staticItems then
return
end
elseif config.items == itemsConfig.TransferToPlayer then
if not cRef.data.AC_skipAnim then
if cRef.data.AC_movableItems then
for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
-- tes3.messageBox('TransferToPlayer %s', ref.object.id)
-- playerRef:activate(ref) -- book will open
tes3.addItem{reference = playerRef, item = ref.object, count = ref.stackSize, playSound = false, updateGUI = false}
tes3.setEnabled {reference = ref, enabled = false}
timer.frame.delayOneFrame(function() mwscript.setDelete{reference = ref, delete = true}; end)
end
tes3ui.forcePlayerInventoryUpdate()
tes3.playSound{sound = pickUpSound, reference = cRef}
-- tes3.playItemPickupSound {reference = cRef}
tMovableItemsOnCont[cRef] = {}
cRef.data.AC_movableItems = nil
cRef.modified = true
end
DisableItems(cRef)
end
end
if cRef.data.AC_skipAnim then
return
elseif cRef.data.AC_staticItems then
DisableItems(cRef)
end
if config.items == itemsConfig.Hide then
DisableItems(cRef)
end
end
PlayOpenAnimation(cRef)
elseif sState == 'open' then
if not config.stayOpen and config.activateMode then
-- mwse.log("[MWCA] is open close")
PlayCloseAnimation(cRef)
end
elseif sState == 'openAnimDone' or sState == 'opening' then
if openTimer then
openTimer:cancel()
end
cRef.data.AC_state = 'open'
cRef.modified = true
local fDistToContainer = cRef.position:distance(playerRef.position)
if fDistToContainer <= iActivationDist then
return -- activate
end
end
return false -- prevent activation
end
-- the old way still works
local function OnActivateObject(eventData)
if not config.activateMode then
return
end
HandleActivation(eventData.target)
end
-- ! this is where the QuickLoot mode happens ! --
local function OnActivationTargetChanged(eventData)
if config.activateMode then return end
-- gets kinda janky when rapidly looking at a container, looking away, then
-- looking back, and running while looking at a container kinda does that, so:
if tes3.mobilePlayer.isRunning and not config.animateWhileRunning then return end
if not config.stayOpen and (containerRef and containerRef ~= eventData.current) then
local oldCState = containerRef.data.AC_state or "closed"
if not eventData.current then
-- not looking at something, or pulling item out of container
if tostring(tes3ui.getMenuOnTop()) == "QuickLoot:Menu" then
-- are we not looking at something for real, or did we just pull something out of the container?
timer.start({ -- delayOneFrame wasn't enough time for the QuickLoot Menu to disappear
type = timer.simulate,
duration = 0.1,
iterations = 1,
callback = function()
if tostring(tes3ui.getMenuOnTop()) ~= "QuickLoot:Menu" then
-- hey we really aren't looking at something
if oldCState ~= "closed" then
-- mwse.log("[MWCA] timer close")
PlayCloseAnimation(containerRef)
end
end
end
})
else
-- definitely not looking at something
if oldCState ~= "closed" then
-- mwse.log("[MWCA] definitely close")
PlayCloseAnimation(containerRef)
end
end
else
-- still looking at something, so close the other thing
if oldCState ~= "closed" then
-- mwse.log("[MWCA] other thing close")
PlayCloseAnimation(containerRef)
end
end
end
HandleActivation(eventData.current, true)
end
local function UpdateContainers()
-- local time_ = os.clock()
local tCellsToCheck = {}
for i, cell in ipairs(tes3.getActiveCells()) do
local sCellName = GetCellName(cell)
if tUpdatedCells[sCellName] == cell then
-- mwse.log('Update Containers skip cell %s', sCellName)
else
tCellsToCheck[sCellName] = cell
end
end
if config.items == itemsConfig.TransferToCont then
tCellsToCheck[GetCellName(playerRef.cell)] = playerRef.cell
end
for cellName, cell in pairs(tCellsToCheck) do
tUpdatedCells[cellName] = cell
-- mwse.log('Update Containers %s', cellName)
for cRef in cell:iterateReferences(iContainerType) do
local sType = GetContainerType(cRef)
if sType and not cRef.deleted and not cRef.disabled and cRef:testActionFlag(tes3.actionFlag.useEnabled) then
-- if not cRef.object.script or (cRef.object.script and tCompatibleScripts[cRef.object.script.id]) then
-- mwse.log('Update Container %s', cRef.object.id)
if cRef.data.AC_state == 'open' or cRef.data.AC_state == 'opening' then
cRef.data.AC_state = 'open'
cRef.modified = true
tes3.playAnimation {reference = cRef, group = 3, startFlag = 1}
end
-- mwse.log('id %s', cRef.object.id)
if cRef.data.AC_state == 'open' then
-- will not work for containers with leveled items, will work with GH
-- mwse.log('open %s', cRef.object.id)
if cRef.isRespawn and not cRef.isEmpty then
-- mwse.log('isRespawn %s %d', cRef.object.id,
cRef.data.AC_state = 'closed'
cRef.modified = true
tes3.playAnimation {reference = cRef, group = 2, startFlag = 1}
end
end
if config.items == itemsConfig.TransferToCont and not cRef.data.AC_skipAnim and tNotSafeCtypes[sType] then
GetItems(cell, cRef)
if cRef.data.AC_movableItems then
for ref, _ in pairs(tMovableItemsOnCont[cRef]) do
tes3.addItem{reference = cRef, item = ref.object, count = ref.stackSize, playSound = false, updateGUI = false}
tes3.setEnabled {reference = ref, enabled = false}
timer.frame.delayOneFrame (function() mwscript.setDelete{reference = ref, delete = true}; end)
end
tMovableItemsOnCont[cRef] = {}
cRef.data.AC_movableItems = nil
cRef.modified = true
end
end
end
end
end
-- mwse.log("UpdateContainers elapsed time: %.4f\n", os.clock() - time_)
end
local function OnCellChanged(eventData)
-- local sCellName = GetCellName(eventData.cell)
-- mwse.log('\n OnCellChanged %s \n', sCellName)
-- tes3.messageBox('OnCellChanged %s', sCellName)
UpdateContainers()
end
local function OnLoaded()
-- mwse.log('OnLoaded')
-- playerRef = tes3.mobilePlayer.reference
playerRef = tes3.player
tStaticItemsOnCont = {}
tMovableItemsOnCont = {}
tBigStaticsOnCont = {}
tUpdatedCells = {}
UpdateContainers()
end
local function Setup()
--[[
-- local tt = {}
-- for obj in tes3.iterateObjects(iContainerType) do
-- if not tt[obj.model] then
-- mwse.log(' %s %s', obj.id, obj.model)
-- tt[obj.model] = 2
-- end
-- end
-- tCompatibleScripts['CharGenFatigueBarrel'] = true
-- tCompatibleScripts['Colony_first_boat'] = true
-- tCompatibleScripts['ColonyDock'] = true
-- tCompatibleScripts['ColonyEquipBag'] = true
-- tCompatibleScripts['Float'] = true
-- tCompatibleScripts['floatAboveStartHeight'] = true
-- tCompatibleScripts['jeannechestScript'] = true -- 'activate' in this script does not make sense
-- tCompatibleScripts['landDeedChest'] = true
-- tCompatibleScripts['MeadScript'] = true
-- tCompatibleScripts['sirilonweChest'] = true
-- tCompatibleScripts['Sound_Boat_Hull'] = true
-- TR scripts
-- tCompatibleScripts['LocalState'] = true
-- tCompatibleScripts['T_ScObj_FGuildSupplyChestTR'] = true
-- tCompatibleScripts['T_ScObj_MGuildSupplyChestTR'] = true
-- tOverriddenScripts['T_ScObj_FGuildSupplyChestTR'] = function(params)
-- if tLocalScriptsToRun[params.script.id] == true then
-- local fightersGuild = tes3.getFaction('Fighters Guild')
-- if fightersGuild and fightersGuild.playerRank == -1 then
-- tes3.messageBox('This chest is reserved for newcomers to the Guild. You need to join the Guild of Fighters in order to be able to legally take its content.')
-- end
-- tLocalScriptsToRun[params.script.id] = false
-- end
-- end
--]]
-- this thing has stupid mesh origin, changes its position with scale
tDontCheck['furn_woodbar_01'] = true
if graphicHerbalism then
tMeshNamesToReplace['f\\furn_shell00.nif'] = 'AC\\anim_kollop_01gh.nif'
tMeshNamesToReplace['f\\furn_shell10.nif'] = 'AC\\anim_kollop_02gh.nif'
tMeshNamesToReplace['f\\furn_shell20.nif'] = 'AC\\anim_kollop_03gh.nif'
tContainerTypes['anim_kollop_01gh'] = 'kollop'
tContainerTypes['anim_kollop_02gh'] = 'kollop'
tContainerTypes['anim_kollop_03gh'] = 'kollop'
else
tMeshNamesToReplace['f\\furn_shell00.nif'] = 'AC\\anim_kollop_01.nif'
tMeshNamesToReplace['f\\furn_shell10.nif'] = 'AC\\anim_kollop_02.nif'
tMeshNamesToReplace['f\\furn_shell20.nif'] = 'AC\\anim_kollop_03.nif'
tContainerTypes['anim_kollop_01'] = 'kollop'
tContainerTypes['anim_kollop_02'] = 'kollop'
tContainerTypes['anim_kollop_03'] = 'kollop'
end
tMeshNamesToReplace['o\\contain_crate_01.nif'] = 'AC\\Anim_Crate_01.nif'
tMeshNamesToReplace['o\\contain_crate_02.nif'] = 'AC\\Anim_Crate_02.nif'
tMeshNamesToReplace['o\\contain_chest_small_01.nif'] = 'AC\\anim_chest_small_01.nif'
tMeshNamesToReplace['o\\contain_chest_small_02.nif'] = 'AC\\anim_chest_small_02.nif'
tMeshNamesToReplace['o\\contain_couldron10.nif'] = 'AC\\Anim_Cauldron.nif'
tMeshNamesToReplace['o\\contain_pot_01.nif'] = 'AC\\Anim_Pot.nif'
tMeshNamesToReplace['o\\contain_com_basket_01.nif'] = 'AC\\Anim_Basket.nif'
tMeshNamesToReplace['o\\contain_com_chest_01.nif'] = 'AC\\anim_com_chest_01.nif'
tMeshNamesToReplace['o\\contain_com_chest_02.nif'] = 'AC\\anim_com_chest_02.nif'
tMeshNamesToReplace['o\\contain_com_closet_01.nif'] = 'AC\\Anim_com_Closet_01.nif'
tMeshNamesToReplace['o\\contain_com_cupboard_01.nif'] = 'AC\\Anim_CupBoard.nif'
tMeshNamesToReplace['o\\contain_com_drawers_01.nif'] = 'AC\\Anim_com_drawers_01.nif'
tMeshNamesToReplace['o\\contain_com_hutch_01.nif'] = 'AC\\Anim_Hutch.nif'
tMeshNamesToReplace['o\\contain_com_sack_01.nif'] = 'AC\\Anim_sack_01.nif'
tMeshNamesToReplace['o\\contain_com_sack_02.nif'] = 'AC\\Anim_sack_02.nif'
tMeshNamesToReplace['o\\contain_com_sack_03.nif'] = 'AC\\Anim_sack_03.nif'
tMeshNamesToReplace['o\\contain_urn_01.nif'] = 'AC\\Anim_Urn_01.nif'
tMeshNamesToReplace['o\\contain_urn_02.nif'] = 'AC\\Anim_Urn_02.nif'
tMeshNamesToReplace['o\\contain_urn_03.nif'] = 'AC\\Anim_Urn_03.nif'
tMeshNamesToReplace['o\\contain_urn_04.nif'] = 'AC\\Anim_Urn_04.nif'
tMeshNamesToReplace['o\\contain_urn_05.nif'] = 'AC\\Anim_Urn_05.nif'
if config.barrelRivet then
tMeshNamesToReplace['o\\contain_barrel_01.nif'] = 'AC\\Anim_Barrel_01.nif'
else
tMeshNamesToReplace['o\\contain_barrel_01.nif'] = 'AC\\Anim_Barrel_noRivet.nif'
end
tMeshNamesToReplace['o\\contain_barrel10.nif'] = 'AC\\Anim_Barrel_02.nif'
tMeshNamesToReplace['o\\contain_de_chest_01.nif'] = 'AC\\anim_de_chest_01.nif'
tMeshNamesToReplace['o\\contain_de_chest_02.nif'] = 'AC\\anim_de_chest_02.nif'
tMeshNamesToReplace['o\\contain_de_closet_01.nif'] = 'AC\\Anim_de_Closet_01.nif'
tMeshNamesToReplace['o\\contain_de_closet_02.nif'] = 'AC\\Anim_de_Closet_02.nif'
tMeshNamesToReplace['o\\contain_de_desk_01.nif'] = 'AC\\Anim_de_desk_01.nif'
tMeshNamesToReplace['o\\contain_de_drawers_01.nif'] = 'AC\\Anim_de_drawers_01.nif'
tMeshNamesToReplace['o\\contain_de_drawers_02.nif'] = 'AC\\Anim_de_drawers_02.nif'
tMeshNamesToReplace['o\\contain_de_table_01.nif'] = 'AC\\Anim_de_table_01.nif'
tMeshNamesToReplace['o\\contain_de_table_02.nif'] = 'AC\\Anim_de_table_02.nif'
tMeshNamesToReplace['o\\contain_dwrv_barrel00.nif'] = 'AC\\Anim_Dw_Barrel_01.nif'
tMeshNamesToReplace['o\\contain_dwrv_barrel10.nif'] = 'AC\\Anim_Dw_Barrel_02.nif'
tMeshNamesToReplace['o\\contain_dwrv_chest00.nif'] = 'AC\\anim_dwrv_chest00.nif'
tMeshNamesToReplace['o\\contain_dwrv_chest10.nif'] = 'AC\\anim_dwrv_chest10.nif'
tMeshNamesToReplace['o\\contain_dwrv_closet00.nif'] = 'AC\\Anim_Dw_Closet.nif'
tMeshNamesToReplace['o\\contain_dwrv_desk00.nif'] = 'AC\\Anim_Dw_Desk.nif'
tMeshNamesToReplace['o\\contain_dwrv_drawers00.nif'] = 'AC\\Anim_Dw_Drawers.nif'
tMeshNamesToReplace['o\\contain_dwrv_table00.nif'] = 'AC\\Anim_Dw_Table.nif'
tMeshNamesToReplace['o\\contain_de_crate_logo.nif'] = 'AC\\Anim_CrateLogo.nif'
tMeshNamesToReplace['f\\furn_dwrv_cabinet00.nif'] = 'AC\\Anim_Dw_Cabinet.nif'
tMeshNamesToReplace['o\\contain_chest10.nif'] = 'AC\\anim_chest10.nif'
-- tMeshNamesToReplace['o\\contain_chest_large_01.nif'] = ' ' -- only in test room
-- tMeshNamesToReplace['o\\contain_sack00.nif'] = ' ' -- not placed in world
-- tMeshNamesToReplace['o\\contain_chest11.nif'] = ' ' -- open contain_chest10
-- mwse.log(' config.barrelRivet %s', config.barrelRivet)
for obj in tes3.iterateObjects(iContainerType) do
local name = obj.model:lower()
local newName = tMeshNamesToReplace[name]
if newName then
-- mwse.log(' replace %s %s %s', obj.id, obj.model, tMeshNamesToReplace[name])
obj.model = newName
end
-- if obj.script then
-- if tOverriddenScripts[sScriptID] then
-- mwse.log('override Script %s %s', obj.id, sScriptID)
-- mwse.overrideScript(sScriptID, tOverriddenScripts[sScriptID])
-- end
-- end
end
local unique = tes3.getObject('com_chest_Daed_crusher')
if unique then -- unique levitating chest in Forgotten Vaults of Anudnabia
unique.model = 'AC\\anim_daedric_chest.nif'
end
pickUpSound = tes3.getSound('Item Misc Up')
openLockFailSound = tes3.getSound('Open Lock Fail')
openLockSound = tes3.getSound('Open Lock')
-- actual distance is often larger
iActivationDistGMST = tes3.findGMST(tes3.gmst.iMaxActivateDist).value
sKeyUsedGMST = tes3.findGMST(tes3.gmst.sKeyUsed).value
tObjectTypesToCheck[tes3.objectType.activator] = true
tObjectTypesToCheck[tes3.objectType.alchemy] = true
tObjectTypesToCheck[tes3.objectType.apparatus] = true
tObjectTypesToCheck[tes3.objectType.armor] = true
tObjectTypesToCheck[tes3.objectType.book] = true
tObjectTypesToCheck[tes3.objectType.clothing] = true
tObjectTypesToCheck[tes3.objectType.container] = true
tObjectTypesToCheck[tes3.objectType.ingredient] = true
tObjectTypesToCheck[tes3.objectType.light] = true
tObjectTypesToCheck[tes3.objectType.lockpick] = true
tObjectTypesToCheck[tes3.objectType.miscItem] = true
tObjectTypesToCheck[tes3.objectType.probe] = true
tObjectTypesToCheck[tes3.objectType.repairItem] = true
tObjectTypesToCheck[tes3.objectType.static] = true
tObjectTypesToCheck[tes3.objectType.weapon] = true
tOpenSounds['barrel'] = tes3.getSound('AC_barrel_open')
tCloseSounds['barrel'] = tes3.getSound('AC_barrel_close')
tOpenSounds['cauldron'] = tes3.getSound('AC_cauldron_open')
tCloseSounds['cauldron'] = tes3.getSound('AC_cauldron_close')
tOpenSounds['pot'] = tes3.getSound('AC_pot_open')
tCloseSounds['pot'] = tes3.getSound('AC_pot_close')
tOpenSounds['daedric'] = tes3.getSound('AC_daed_open')
tCloseSounds['daedric'] = tes3.getSound('AC_daed_close')
tOpenSounds['closet'] = tes3.getSound('AC_closet_open')
tCloseSounds['closet'] = tes3.getSound('AC_closet_close')
tOpenSounds['cupboard'] = tes3.getSound('AC_cupboard_open')
tCloseSounds['cupboard'] = tes3.getSound('AC_cupboard_close')
tOpenSounds['drawer'] = tes3.getSound('AC_drawer_open')
tCloseSounds['drawer'] = tes3.getSound('AC_drawer_close')
tOpenSounds['drawerDunmer'] = tes3.getSound('AC_drawer_de_open')
tCloseSounds['drawerDunmer'] = tes3.getSound('AC_drawer_de_close')
tOpenSounds['basket'] = tes3.getSound('AC_basket_open')
tCloseSounds['basket'] = tes3.getSound('AC_basket_close')
tOpenSounds['chestSmall'] = tes3.getSound('AC_smallChest_open')
tCloseSounds['chestSmall'] = tes3.getSound('AC_smallChest_close')
tOpenSounds['sack'] = tes3.getSound('AC_sack_open')
tCloseSounds['sack'] = tes3.getSound('AC_sack_close')
tOpenSounds['chest'] = tes3.getSound('AC_chest_open')
tCloseSounds['chest'] = tes3.getSound('AC_chest_close')
tOpenSounds['crate'] = tes3.getSound('AC_crate_open')
tCloseSounds['crate'] = tes3.getSound('AC_crate_close')
tOpenSounds['chestDwemer'] = tes3.getSound('AC_dw_chest_open')
tCloseSounds['chestDwemer'] = tes3.getSound('AC_dw_chest_close')
tOpenSounds['closetDwemer'] = tes3.getSound('AC_dw_closet_open')
tCloseSounds['closetDwemer'] = tes3.getSound('AC_dw_closet_close')
tOpenSounds['drawerDwemer'] = tes3.getSound('AC_dw_drawer_open')
tCloseSounds['drawerDwemer'] = tes3.getSound('AC_dw_drawer_close')
tOpenSounds['keg'] = tes3.getSound('AC_keg_open')
tCloseSounds['keg'] = tes3.getSound('AC_keg_close')
tOpenSounds['urn'] = tes3.getSound('AC_urn_open')
tCloseSounds['urn'] = tes3.getSound('AC_urn_close')
tNotSafeCtypes['daedric'] = true
tNotSafeCtypes['barrel'] = true
tNotSafeCtypes['crate'] = true
tNotSafeCtypes['basket'] = true
tNotSafeCtypes['cauldron'] = true
tNotSafeCtypes['chestSmall'] = true
tNotSafeCtypes['keg'] = true
tNotSafeCtypes['chestDwemer'] = true
tNotSafeCtypes['urn'] = true
tNotSafeCtypes['chest'] = true
tContHeightToCheck['daedric'] = 0.33
tContHeightToCheck['barrel'] = 0.2
tContHeightToCheck['crate'] = 0.4
tContHeightToCheck['basket'] = 0.2
tContHeightToCheck['cauldron'] = 0.15
tContHeightToCheck['chestSmall'] = 1
tContHeightToCheck['keg'] = 0.25
tContHeightToCheck['chestDwemer'] = 0.33
tContHeightToCheck['urn'] = 0.2
tContHeightToCheck['chest'] = 0.55
tContainerTypes['anim_daedric_chest'] = 'daedric'
tContainerTypes['anim_barrel_01'] = 'barrel'
tContainerTypes['anim_barrel_norivet'] = 'barrel'
tContainerTypes['anim_barrel_02'] = 'barrel'
tContainerTypes['anim_crate_01'] = 'crate'
tContainerTypes['anim_crate_02'] = 'crate'
tContainerTypes['anim_cratelogo'] = 'crate'
tContainerTypes['anim_basket'] = 'basket'
tContainerTypes['anim_cauldron'] = 'cauldron'
tContainerTypes['anim_chest_small_01'] = 'chestSmall'
tContainerTypes['anim_chest_small_02'] = 'chestSmall'
tContainerTypes['anim_chest10'] = 'chest'
tContainerTypes['anim_com_chest_01'] = 'chest'
tContainerTypes['anim_com_chest_02'] = 'chest'
tContainerTypes['anim_de_chest_01'] = 'chest'
tContainerTypes['anim_de_chest_02'] = 'chest'
tContainerTypes['anim_de_closet_02'] = 'closet'
tContainerTypes['anim_de_closet_01'] = 'closet'
tContainerTypes['anim_com_closet_01'] = 'closet'
tContainerTypes['anim_com_drawers_01'] = 'drawer'
tContainerTypes['anim_de_drawers_01'] = 'drawer'
tContainerTypes['anim_de_table_02'] = 'drawerDunmer'
tContainerTypes['anim_de_table_01'] = 'drawerDunmer'
tContainerTypes['anim_de_drawers_02'] = 'drawerDunmer'
tContainerTypes['anim_de_desk_01'] = 'drawerDunmer'
tContainerTypes['anim_dw_barrel_02'] = 'keg'
tContainerTypes['anim_dw_barrel_01'] = 'keg'
tContainerTypes['anim_dw_table'] = 'drawerDwemer'
tContainerTypes['anim_dw_drawers'] = 'drawerDwemer'
tContainerTypes['anim_dw_desk'] = 'drawerDwemer'
tContainerTypes['anim_dw_cabinet'] = 'drawerDwemer'
tContainerTypes['anim_dwrv_chest10'] = 'chestDwemer'
tContainerTypes['anim_dwrv_chest00'] = 'chestDwemer'
tContainerTypes['anim_dw_closet'] = 'closetDwemer'
tContainerTypes['anim_hutch'] = 'cupboard'
tContainerTypes['anim_cupboard'] = 'cupboard'
tContainerTypes['anim_pot'] = 'pot'
tContainerTypes['anim_sack_01'] = 'sack'
tContainerTypes['anim_sack_02'] = 'sack'
tContainerTypes['anim_sack_03'] = 'sack'
tContainerTypes['anim_urn_01'] = 'urn'
tContainerTypes['anim_urn_02'] = 'urn'
tContainerTypes['anim_urn_03'] = 'urn'
tContainerTypes['anim_urn_04'] = 'urn'
tContainerTypes['anim_urn_05'] = 'urn'
config.version = 2.06
end
local function OnInitialized(eventData)
if not tes3.isModActive('MW Containers Animated.esp') then
return
end
Setup()
event.register("cellChanged", OnCellChanged)
event.register("loaded", OnLoaded)
event.register("activate", OnActivateObject, {priority = 1200})
event.register("activationTargetChanged", OnActivationTargetChanged, {priority = 1200})
mwse.log("[MW Containers Animated v2.06] lua loaded")
end
event.register("initialized", OnInitialized)
-- debug stuff below
local function OnActivationTargetChangedTest(eventData)
if eventData.current then
local ref = eventData.current
if ref.object.objectType == iContainerType then
local sContType = GetContainerType(ref)
-- tes3.messageBox('LEVELED ITEMS %d', CountLeveledItems(ref.object.inventory))
-- tes3.messageBox("%s %s", ref.object.id, ref.isEmpty)
if sContType then
-- tes3.messageBox('orientation.z %f', math.deg(ref.orientation.z))
tes3.messageBox('sContType %s', sContType)
if tNotSafeCtypes[sContType] then
if ref.data.AC_skipAnim then
tes3.messageBox('AC_skipAnim %s', ref.data.AC_skipAnim)
end
if ref.data.AC_staticItems then
tes3.messageBox('AC_staticItems %s', ref.data.AC_staticItems)
end
if ref.data.AC_movableItems then
tes3.messageBox('AC_movableItems %s', ref.data.AC_movableItems)
end
end
-- tes3.messageBox('max y %d', eventData.current.object.boundingBox.max.y)
-- tes3.messageBox('min y %d', eventData.current.object.boundingBox.min.y)
end
end
end
end
-- event.register("activationTargetChanged", OnActivationTargetChangedTest)
-- local switchIndex = 0
local function Test()
local target = tes3.getPlayerTarget()
-- local v = tes3.getPlayerEyeVector()
if target then
GetContainerType(target)
tes3.messageBox('data.GH %s AC_state %s isEmpty %s', target.data.GH, target.data.AC_state, target.isEmpty)
-- tes3.messageBox('%s', target.object.mesh)
local sceneNode = target.sceneNode
if not sceneNode then
tes3.messageBox(' no sceneNode')
return
end
local switchNode = sceneNode:getObjectByName("HerbalismSwitch")
if switchNode then
-- switchIndex = switchIndex + 1
-- if switchIndex == 3 then
-- switchIndex = 0
-- end
-- switchNode.switchIndex = switchIndex
tes3.messageBox('%s', switchNode.children[switchNode.switchIndex+1].name)
else
tes3.messageBox(' no switchNode')
end
-- tes3.messageBox('GH %s', target.data.GH)
-- tes3.messageBox('AC_state %s', target.data.AC_state)
-- local pos = tes3vector3.new(target.position.x,target.position.y,target.position.z +target.object.boundingBox.min.z)
-- local egg = tes3.createReference { object = 'food_kwama_egg_01', position = target.position, orientation = v3up, cell = playerRef.cell }
-- egg.scale = 0.3
-- target.data.AC_skipAnim = true
-- target.lockNode.level = 33
-- tes3.unlock {reference = target}
-- mwse.log('mwse.log test %d', 'q')
-- local result1 = tes3.rayTest{ position = target.position, direction = tes3vector3.new(0,0,1), findAll = true, useBackTriangles = true, ignore = {target} }
-- if result1 then
-- for i, hit in pairs(result1) do
-- if hit.reference then
-- mwse.log('%s RayTestUp hit %s', target.object.id, hit.reference.id)
-- end
-- end
-- end
-- RayTest(target)
-- if target.data.AC_items then
-- for _, ref in pairs(target.data.AC_items) do
-- mwse.log('MWCA items %s %s', target.object.id, ref.object.id)
-- for _, pos in pairs( GGetBoundingBoxVertexPositions(target.position:copy(), target.orientation:copy(), target.object.boundingBox.min:copy(), target.object.boundingBox.max:copy())) do
-- local egg = tes3.createReference { object = 'food_kwama_egg_01', position = pos, orientation = v3up, cell = target.cell }
-- egg.scale = 0.5
-- end
-- local trapSpell = tes3.getTrap {reference = ref}
-- tes3.setTrap {reference = target, spell = 'ghost_snake'}
-- tes3.playAnimation {reference = target, group = 2, startFlag = 0}
-- tes3.messageBox('W %d', target.object.inventory:calculateWeight())
end
end
-- event.register("keyDown", Test, { filter = tes3.scanCode.z })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment