Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- USER CONFIGURABLE VARIABLES
- AURA_RADIUS = 25 -- in meters
- VALUE_THRESHOLD = 25 -- gold
- WEIGHT_THRESHOLD = 2 -- grams
- -- performance options, if needed
- UPDATE_INTERVAL = 250 -- milliseconds
- PHASE_DIVISOR = 4 -- look for new items every nth update
- -- END OF USER CONFIGURABLE VARIABLES
- -- GLOBAL VARIABLES
- toggle = false
- toggle_tiny = false
- toggle_container = false
- toggle_default = false
- toggle_stealing = false
- -- CONSTANTS
- PING_TIMER = "REVEALING_AURA_PING"
- EFFECT_IGNORE = -2
- EFFECT_UNDEFINED = -1
- EFFECT_NONE = 0
- EFFECT_DEFAULT = 1
- EFFECT_TINY = 2
- EFFECT_UNIMPORTANT = 3
- EFFECT_CONTAINER = 4
- EFFECT_CONTAINER_VALUABLE = 5
- EFFECT_CONTAINER_UNOPENED = 6
- EFFECT_VALUABLE = 7
- EFFECT_LOCKED = 8
- EFFECT_STEALING = 9
- EFFECT_SWD = 10
- EFFECTS = {
- [EFFECT_DEFAULT] = "2b440364-c5b7-4243-d3a6-0684052f4d89",
- [EFFECT_TINY] = "1ca4cbbb-1738-4dae-85cd-b63e4d3d0689",
- [EFFECT_UNIMPORTANT] = "34e00416-686c-48d9-a17c-525d07dacb5d",
- [EFFECT_CONTAINER] = "328c4552-ed80-4d3a-8481-fbc036e97750",
- [EFFECT_CONTAINER_VALUABLE] = "770335e9-ad2c-453a-972c-74a116be94b3",
- [EFFECT_CONTAINER_UNOPENED] = "b0a765e2-d287-4e92-8740-4cd78dc63d6d",
- [EFFECT_VALUABLE] = "770335e9-ad2c-453a-972c-74a116be94b3",
- [EFFECT_LOCKED] = "8d965c39-6e1e-467f-bbd0-38ab9d19764d",
- [EFFECT_STEALING] = "e2f96cad-5343-481a-b023-cead49549ad7",
- [EFFECT_SWD] = "b7a2491e-4d4e-6c7d-d469-060ed81b17c0",
- }
- component_layers = {
- IsItem={1, 2, 3},
- IsCharacter={1, 2}
- }
- TAGS = {
- IGNORE_PLATFORM_DESTRUCTION = "cf60d691-4307-4a8c-af4d-0e8781ea2503",
- JUNK = "99f4e322-ab2f-48e9-8294-b87ea62212b0",
- HIGHLIGHTITEM = "2782dd9d-a96c-48e9-a850-73c79f54bfb6",
- SCROLL = "dd86c045-0370-4ec9-b7c5-b0b160706f09",
- -- Speak With Dead conditions
- HASSWDDIALOG = "21be1053-c642-4081-b64b-56678ae11594",
- BEAST = "890b5a2a-e773-48df-b191-c887d87bec16",
- UNDEAD = "33c625aa-6982-4c27-904f-e47029a9b140",
- CORPSE_SPOKEN = "249ba319-6652-47ec-9f31-ef5be55429c3",
- BLOCK_SPEAK_WITH_DEAD = "70f9d685-b791-4ea2-88e4-fc8fc48b4234",
- }
- -- CHARACTER EVENTS
- Ext.Osiris.RegisterListener("LevelGameplayStarted", 2, "after", function (levelName, isEditorMode)
- for _,c in pairs(Osi.DB_PartyMembers:Get(nil)) do
- _P("Assigning to " .. c[1])
- AddPassive(c[1], "REVEALING_AURA_Passive")
- AddPassive(c[1], "REVEALING_AURA_Passive_Tiny")
- AddPassive(c[1], "REVEALING_AURA_Passive_Container")
- AddPassive(c[1], "REVEALING_AURA_Passive_Default")
- AddPassive(c[1], "REVEALING_AURA_Passive_Unimportant")
- end
- Osi.TimerLaunch(PING_TIMER, 1000)
- end)
- Ext.Osiris.RegisterListener("CharacterJoinedParty", 1, "after", function (char)
- AddPassive(char, "REVEALING_AURA_Passive")
- AddPassive(char, "REVEALING_AURA_Passive_Tiny")
- AddPassive(char, "REVEALING_AURA_Passive_Container")
- AddPassive(char, "REVEALING_AURA_Passive_Default")
- AddPassive(char, "REVEALING_AURA_Passive_Unimportant")
- local p = Ext.Entity.Get(GetHostCharacter()).ServerToggledPassives.Passives
- local c = Ext.Entity.Get(char)
- c.ServerToggledPassives.Passives.REVEALING_AURA_Passive = p.REVEALING_AURA_Passive or false
- c.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Tiny = p.REVEALING_AURA_Passive_Tiny or false
- c.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Container = p.REVEALING_AURA_Passive_Container or false
- c.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Default = p.REVEALING_AURA_Passive_Default or false
- c.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Unimportant = p.REVEALING_AURA_Passive_Unimportant or false
- end)
- Ext.Osiris.RegisterListener("CharacterLeftParty", 1, "before", function (char)
- RemovePassive(char, "REVEALING_AURA_Passive")
- RemovePassive(char, "REVEALING_AURA_Passive_Tiny")
- RemovePassive(char, "REVEALING_AURA_Passive_Container")
- RemovePassive(char, "REVEALING_AURA_Passive_Default")
- RemovePassive(char, "REVEALING_AURA_Passive_Unimportant")
- RemoveStatus(char, "REVEAL_INTERACTIVES")
- end)
- Ext.Osiris.RegisterListener("LevelUnloading", 1, "before", function (levelName)
- Osi.TimerCancel(PING_TIMER)
- end)
- -- HELPERS
- function FastHasStatus(item, status)
- if item.StatusContainer ~= nil then
- for _,s in pairs(item.StatusContainer.Statuses) do
- if s == status then
- return true
- end
- end
- end
- return false
- end
- function FastHasTag(item, tag)
- if item.Tag ~= nil then
- for _,t in pairs(item.Tag.Tags) do
- if t == tag then
- return true
- end
- end
- end
- return false
- end
- function HasAnyActionType(item)
- if item.ActionType ~= nil then
- for a,actiontype in pairs(item.ActionType.ActionTypes) do
- if actiontype > 0 then
- return true
- end
- end
- end
- return false
- end
- function HasActionType(item, action)
- if item.ActionType ~= nil then
- for a,actiontype in pairs(item.ActionType.ActionTypes) do
- if actiontype == action then
- return true
- end
- end
- end
- return false
- end
- function IsValuable(item)
- return (
- item.ServerItem.ItemType == "VeryRare" or
- item.ServerItem.ItemType == "Legendary" or
- item.ServerItem.StoryItem or
- item.Value.Unique or
- item.Value.Value >= VALUE_THRESHOLD or
- FastHasTag(item, TAGS["HIGHLIGHTITEM"]) or
- FastHasTag(item, TAGS["SCROLL"])
- )
- end
- function IsValuableIventories(item, depth)
- if depth > 5 then
- _P("RevealingAuraSE - Inventory recursion limit reached")
- return 0
- end
- local alljunk = true
- for _,inv in pairs(item.InventoryOwner.Inventories) do
- for _,v in pairs(inv.InventoryContainer.Items) do
- local i = v.Item.ServerItem.Item
- if IsValuable(v.Item) then
- return 2
- end
- if alljunk and not FastHasTag(v.Item, TAGS["JUNK"]) then
- alljunk = false
- end
- if v.Item.InventoryOwner ~= nil then
- -- nested container
- local container = IsValuableIventories(v.Item, depth + 1)
- if container == 2 then
- return 2
- elseif alljunk and container == 1 then
- alljunk = false
- end
- end
- end
- end
- if alljunk then
- return 0
- end
- return 1
- end
- -- ASSIGN EFFECTS
- function GetEffect(item, i, last)
- if item.IsItem ~= nil then
- if last == EFFECT_UNDEFINED then
- if FastHasTag(item, TAGS["IGNORE_PLATFORM_DESTRUCTION"]) then
- return EFFECT_IGNORE
- end
- end
- -- just in case this is applied to an item rather than character
- if FastHasStatus(item, 'SPEAK_WITH_DEAD_INTERESTING') then
- return EFFECT_NONE
- end
- if i == 1 then
- if item.InventoryOwner ~= nil then
- -- container
- local v = IsValuableIventories(item, 0)
- if toggle_tiny and v == 2 then
- return EFFECT_CONTAINER_VALUABLE
- elseif toggle_container and v > 0 then
- return EFFECT_CONTAINER
- end
- elseif toggle_tiny and IsValuable(item) then
- return EFFECT_VALUABLE
- elseif toggle_tiny and item.Data.Weight ~= nil and
- item.ServerItem.CanBePickedUp and
- item.Data.Weight > 0 and
- item.Data.Weight < WEIGHT_THRESHOLD then
- return EFFECT_TINY
- end
- -- if item.ServerItem.Template.Unimportant then
- -- return toggle_unimportant and EFFECT_UNIMPORTANT or EFFECT_NONE
- -- return EFFECT_NONE
- -- end
- if item.InventoryOwner ~= nil then
- return EFFECT_NONE
- else
- return toggle_default and EFFECT_DEFAULT or EFFECT_NONE
- end
- elseif i == 2 then
- if item.OwneeCurrent ~= nil and
- item.OwneeCurrent.Ownee ~= nil and
- Osi.IsPlayer(item.OwneeCurrent.Ownee.Uuid.EntityUuid) == 0 then
- if toggle_stealing then
- return EFFECT_STEALING
- else
- if item.InventoryOwner ~= nil then
- -- container
- local v = IsValuableIventories(item, 0)
- if toggle_tiny and v == 2 then
- -- return EFFECT_CONTAINER_VALUABLE
- return EFFECT_STEALING
- elseif toggle_container and v > 0 then
- -- return EFFECT_CONTAINER
- return EFFECT_NONE
- end
- return EFFECT_NONE
- elseif toggle_tiny and IsValuable(item) then
- return EFFECT_STEALING
- elseif toggle_tiny and item.Data.Weight ~= nil and
- item.ServerItem.CanBePickedUp and
- item.Data.Weight > 0 and
- item.Data.Weight < WEIGHT_THRESHOLD then
- -- return EFFECT_TINY
- return EFFECT_STEALING
- end
- -- if item.ServerItem.Template.Unimportant then
- -- return toggle_unimportant and EFFECT_UNIMPORTANT or EFFECT_NONE
- -- return EFFECT_NONE
- -- end
- return EFFECT_NONE
- end
- end
- if item.InventoryOwner ~= nil and item.HasOpened == nil then
- local v = IsValuableIventories(item, 0)
- if v > 0 then
- return EFFECT_CONTAINER_UNOPENED
- end
- end
- return EFFECT_NONE
- elseif i == 3 then
- if Osi.IsLocked(item.Uuid.EntityUuid) > 0 and not FastHasStatus(item, 'ARCANE_LOCK') then
- return EFFECT_LOCKED
- end
- return EFFECT_NONE
- end
- elseif item.IsCharacter ~= nil then
- if not (Osi.IsDead(item.Uuid.EntityUuid) > 0 or
- FastHasStatus(item, 'KNOCKED_OUT') or
- FastHasStatus(item, 'KNOCKED_OUT_PERMANENTLY') or
- FastHasStatus(item, 'KNOCKED_OUT_TEMPORARILY')
- ) then
- return EFFECT_NONE
- end
- if i == 1 then
- if FastHasStatus(item, 'SPEAK_WITH_DEAD_INTERESTING') then
- return EFFECT_NONE
- end
- if FastHasTag(item, TAGS['HASSWDDIALOG']) and
- Osi.IsPlayer(item.Uuid.EntityUuid) == 0 and
- Osi.IsFreshCorpse(item.Uuid.EntityUuid) > 0 and
- not FastHasTag(item, TAGS['BEAST']) and
- not FastHasTag(item, TAGS['UNDEAD']) and
- not FastHasTag(item, TAGS['CORPSE_SPOKEN']) and
- not FastHasTag(item, TAGS['BLOCK_SPEAK_WITH_DEAD']) then
- return EFFECT_SWD
- end
- if item.InventoryOwner ~= nil and
- item.CanBeLooted ~= nil and
- item.Loot ~= nil then
- local v = IsValuableIventories(item, 0)
- if toggle_tiny and v == 2 then
- return EFFECT_CONTAINER_VALUABLE
- elseif toggle_container and v > 0 then
- return EFFECT_CONTAINER
- end
- end
- if item.InventoryOwner ~= nil then
- return EFFECT_NONE
- else
- return toggle_default and EFFECT_DEFAULT or EFFECT_NONE
- end
- end
- if i == 2 then
- if item.Loot ~= nil and item.Loot.Flags & 4 > 0 then
- if toggle_stealing then
- return EFFECT_STEALING
- else
- if item.InventoryOwner ~= nil then
- -- container
- local v = IsValuableIventories(item, 0)
- if toggle_tiny and v == 2 then
- -- return EFFECT_CONTAINER_VALUABLE
- return EFFECT_STEALING
- elseif toggle_container and v > 0 then
- -- return EFFECT_CONTAINER
- return EFFECT_NONE
- end
- return EFFECT_NONE
- elseif toggle_tiny and IsValuable(item) then
- return EFFECT_STEALING
- elseif toggle_tiny and item.Data.Weight ~= nil and
- item.ServerItem.CanBePickedUp and
- item.Data.Weight > 0 and
- item.Data.Weight < WEIGHT_THRESHOLD then
- -- return EFFECT_TINY
- return EFFECT_STEALING
- end
- -- if item.ServerItem.Template.Unimportant then
- -- -- return toggle_unimportant and EFFECT_UNIMPORTANT or EFFECT_NONE
- -- return EFFECT_NONE
- -- end
- return EFFECT_NONE
- end
- end
- if item.InventoryOwner ~= nil and
- item.CanBeLooted ~= nil and
- item.Loot ~= nil and
- item.Loot.Flags & 2 == 0 then
- local v = IsValuableIventories(item, 0)
- if v > 0 then
- return EFFECT_CONTAINER_UNOPENED
- end
- end
- return EFFECT_NONE
- end
- end
- end
- function InRanges(transform, positions)
- for k,v in pairs(positions) do
- if InRange(transform, v[1], v[2], v[3]) then
- return true
- end
- end
- return false
- end
- function InRange(transform, x, y, z)
- local delx = math.abs(transform[1] - x)
- if delx > AURA_RADIUS then
- return false
- end
- local dely = math.abs(transform[2] - y)
- if dely > AURA_RADIUS then
- return false
- end
- local delz = math.abs(transform[3] - z)
- if delz > AURA_RADIUS then
- return false
- end
- return math.sqrt(delx^2 + dely^2 + delz^2) < AURA_RADIUS
- end
- function UpdateEffects(effects, item, layers)
- for _,i in pairs(layers) do
- if effects[i]["effect_idx"] ~= EFFECT_IGNORE then
- local effect_idx = GetEffect(item, i, effects[i]["effect_idx"])
- if effects[i]["effect_idx"] ~= effect_idx then
- if effects[i]["effect_id"] ~= 0 then
- StopLoopEffect(effects[i]["effect_id"])
- effects[i]["effect_id"] = 0
- end
- effects[i]["effect_idx"] = effect_idx
- if effect_idx > EFFECT_NONE then
- local effect_id = PlayLoopEffect(item.Uuid.EntityUuid, EFFECTS[effect_idx], "", 1)
- if effect_id ~= nil then
- effects[i]["effect_id"] = effect_id
- end
- end
- end
- end
- end
- end
- function RemoveEffects(effects, item, layers)
- for _,i in pairs(layers) do
- local effect_id = effects[i]["effect_id"]
- if effect_id > 0 then
- StopLoopEffect(effect_id)
- end
- end
- end
- -- MAIN EVENT LOOP
- timer_phase = 0
- Ext.Osiris.RegisterListener("TimerFinished", 1, "after", function (timer)
- if timer == PING_TIMER then
- Osi.TimerLaunch(PING_TIMER, UPDATE_INTERVAL)
- local start = Ext.Utils.MonotonicTime()
- local count = 0
- local e = Ext.Entity.Get(GetHostCharacter())
- local p = e.ServerToggledPassives.Passives
- if not p.REVEALING_AURA_Passive then
- if not toggle then
- return
- end
- for component,layers in pairs(component_layers) do
- for _,item in pairs(Ext.Entity.GetAllEntitiesWithComponent(component)) do
- if item.Vars.Revealing_Aura_Effects then
- RemoveEffects(item.Vars.Revealing_Aura_Effects, item, layers)
- end
- item.Vars.Revealing_Aura_Effects = nil
- end
- end
- toggle = false
- return
- end
- toggle = e.ServerToggledPassives.Passives.REVEALING_AURA_Passive
- toggle_tiny = e.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Tiny
- toggle_container = e.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Container
- toggle_default = e.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Default
- toggle_stealing = e.ServerToggledPassives.Passives.REVEALING_AURA_Passive_Unimportant
- if timer_phase ~= 0 then
- -- fast update loop for existing effects
- for component,layers in pairs(component_layers) do
- for _,item in pairs(Ext.Entity.GetAllEntitiesWithComponent(component)) do
- local effects = item.Vars.Revealing_Aura_Effects
- if effects ~= nil then
- UpdateEffects(effects, item, layers)
- item.Vars.Revealing_Aura_Effects = effects
- count = count + 1
- end
- end
- end
- else
- local positions = {}
- for _,c in pairs(Osi.DB_PartyMembers:Get(nil)) do
- local x,y,z = GetPosition(c[1])
- if x ~= nil then
- table.insert(positions, {x,y,z})
- end
- end
- for component,layers in pairs(component_layers) do
- for _,item in pairs(Ext.Entity.GetAllEntitiesWithComponent(component)) do
- if item.Transform ~= nil then
- local transform = item.Transform.Transform.Translate
- local effects = item.Vars.Revealing_Aura_Effects
- if item.InventoryMember == nil and InRanges(item.Transform.Transform.Translate, positions) then
- count = count + 1
- if effects == nil then
- effects = {}
- for i in pairs(layers) do
- effects[i] = {
- effect_idx = EFFECT_UNDEFINED,
- effect_id = 0
- }
- end
- item.Vars.Revealing_Aura_Effects = effects
- end
- UpdateEffects(effects, item, layers)
- -- ensure syncing
- item.Vars.Revealing_Aura_Effects = effects
- else
- if effects ~= nil then
- RemoveEffects(effects, item, layers)
- item.Vars.Revealing_Aura_Effects = nil
- end
- end
- end
- end
- end
- end
- timer_phase = (timer_phase + 1) % PHASE_DIVISOR
- -- print performance info to the console
- -- _P("phase " .. timer_phase .. " loop: " .. count .. ", " .. (Ext.Utils.MonotonicTime() - start) / 1000)
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement