WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   SecureHandlerState (https://www.wowinterface.com/forums/showthread.php?t=52950)

Resike 12-04-15 02:11 PM

SecureHandlerState
 
I would like to create a state handler for the vehicle state when the player is in vehicle and has a vehicle UI.

I have tried:

Lua Code:
  1. RegisterStateDriver(self.frame.state, "vehicleupdate", "[target=player, nohelp, noharm] invehicle; none")

However there are some issues with this one since there are some flight masters which incorrectly returns invehicle, even when you are not in one. (Like the dragons in Dragon Soul and in some other instances.)

I have also tried this one, which works better, however it also returns invehicle when the user has no vehicle ui.

Lua Code:
  1. RegisterStateDriver(self.frame.state, "vehicleupdate", "[target=vehicle, exists] invehicle; none")

If someone could help me merge the two methods somehow, or if someone has a proper state driver for this i would be greatful.

Lombra 12-04-15 02:24 PM

[vehicleui]

10charshello

Resike 12-04-15 02:33 PM

Quote:

Originally Posted by Lombra (Post 312144)
[vehicleui]

10charshello

I hate you. :) JK thanks.

Taudier 01-11-16 09:21 AM

you can 'WrapScript' the 'OnShow' & 'OnHide' vehicule ui. more reliable than [vehicleui].


Code:

for i=1, 6 do
        local button = _G["OverrideActionBarButton"..i]
        handler:WrapScript(button, "OnShow", your function)
        handler:WrapScript(button, "OnHide", your function)
end

or just the first button

Resike 01-11-16 09:52 AM

Quote:

Originally Posted by Taudier (Post 312522)
you can 'WrapScript' the 'OnShow' & 'OnHide' vehicule ui. more reliable than [vehicleui].


Code:

for i=1, 6 do
        local button = _G["OverrideActionBarButton"..i]
        handler:WrapScript(button, "OnShow", your function)
        handler:WrapScript(button, "OnHide", your function)
end

or just the first button

What about vehicles without a button?

SDPhantom 01-11-16 02:29 PM

On a side note, you can use @player and @vehicle to specify the target of the condition rather than the old target= syntax. This option was implemented as a more intuitive way to define the target of a condition since people were trying to use the old syntax for checking if your target was a specified unit.

Resike 01-11-16 03:40 PM

Quote:

Originally Posted by SDPhantom (Post 312524)
On a side note, you can use @player and @vehicle to specify the target of the condition rather than the old target= syntax. This option was implemented as a more intuitive way to define the target of a condition since people were trying to use the old syntax for checking if your target was a specified unit.

My current handler works fine i only have a small issue.
When the player have a pet summoned and have a pet frame, then i switch the pet frame to the player frame when the UNIT_ENTERED_VEHICLE gets triggeted with a vehicle ui.
However sometimes from UNIT_ENTERING_VEHICLE to UNIT_ENTERED_VEHICLE and from UNIT_EXITING_VEHICLE to UNIT_EXITED_VEHICLE, the pet frame instead of showing the player or the pet shows the vehicle frame for a second for no reason. I'm not sure how to dodge that securely.

I wrote a workaround to unregisted and reregister the pet frame between this events, but thats not gonna work in combat:

Lua Code:
  1. function PlayerPet:UNIT_ENTERING_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  2.     if showVehicleUI then
  3.         if not InCombatLockdown() then
  4.             UnregisterUnitWatch(self.frame)
  5.             self.frame:Hide()
  6.         end
  7.         self.frame.unit = "player"
  8.         self:UpdateDisplay()
  9.     end
  10. end
  11.  
  12. function PlayerPet:UNIT_ENTERED_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  13.     if showVehicleUI then
  14.         if not InCombatLockdown() then
  15.             RegisterUnitWatch(self.frame)
  16.         end
  17.         self.frame.unit = "player"
  18.         self:UpdateDisplay()
  19.     end
  20. end
  21.  
  22. function PlayerPet:UNIT_EXITING_VEHICLE()
  23.     if self.frame.unit ~= "pet" then
  24.         if not InCombatLockdown() then
  25.             UnregisterUnitWatch(self.frame)
  26.             self.frame:Hide()
  27.         end
  28.         self.frame.unit = "pet"
  29.         self:UpdateDisplay()
  30.     end
  31. end
  32.  
  33. function PlayerPet:UNIT_EXITED_VEHICLE()
  34.     --if self.frame.unit ~= "pet" then
  35.         --self.frame:Show()
  36.         if not InCombatLockdown() then
  37.             RegisterUnitWatch(self.frame)
  38.         end
  39.         --self.frame.unit = "pet"
  40.         self:UpdateDisplay()
  41.     --end
  42. end

Taudier 01-11-16 04:42 PM

Quote:

Originally Posted by Resike (Post 312523)
What about vehicles without a button?

hook another secure frame maybe

this is the script i use for the pet action bar :

RegisterStateDriver(myframe, "visibility", "[target=pet,exists, novehicleui, nopossessbar] show; hide;")

hope it can help.

you can also see in RestrictedEnvironment.lua there are functions about vehiculeui that you can use in the handler

SDPhantom 01-11-16 06:00 PM

Quote:

Originally Posted by Resike (Post 312525)
However sometimes from UNIT_ENTERING_VEHICLE to UNIT_ENTERED_VEHICLE and from UNIT_EXITING_VEHICLE to UNIT_EXITED_VEHICLE, the pet frame instead of showing the player or the pet shows the vehicle frame for a second for no reason. I'm not sure how to dodge that securely.

My guess is you're trying to swap the artwork before the game as officially applied the changes between vehicle and player modes. Have you tried limiting all the visual stuff to UNIT_ENTERED_VEHICLE and UNIT_EXITED_VEHICLE? From what I can tell, the UNIT_*ING_VEHICLE events trigger hiding the old UI and UNIT_*ED_VEHICLE events trigger showing the new one. At least that's how the default UI handles it.

Also, if you're using the SecureStateDriver system, they don't necessarily listen to these events and are delayed by at least 200ms. You might be able to hook into the OnAttributeChanged script to act on when RegisterUnitWatch() triggers. If you leave it to show/hide the frame itself, it changes the statehidden attribute to a true/nil value.



At this point, I'm just running off a list of what could be going on. I don't see what self:UpdateDisplay() is doing or how unit switching is being handled not only from the artwork aspect, but how the SecureUnitButton template is being used. All that's being shown is debug code that isn't really going to work in the end product.

Resike 01-11-16 07:19 PM

Quote:

Originally Posted by SDPhantom (Post 312528)
My guess is you're trying to swap the artwork before the game as officially applied the changes between vehicle and player modes. Have you tried limiting all the visual stuff to UNIT_ENTERED_VEHICLE and UNIT_EXITED_VEHICLE? From what I can tell, the UNIT_*ING_VEHICLE events trigger hiding the old UI and UNIT_*ED_VEHICLE events trigger showing the new one. At least that's how the default UI handles it.

Also, if you're using the SecureStateDriver system, they don't necessarily listen to these events and are delayed by at least 200ms. You might be able to hook into the OnAttributeChanged script to act on when RegisterUnitWatch() triggers. If you leave it to show/hide the frame itself, it changes the statehidden attribute to a true/nil value.



At this point, I'm just running off a list of what could be going on. I don't see what self:UpdateDisplay() is doing or how unit switching is being handled not only from the artwork aspect, but how the SecureUnitButton template is being used. All that's being shown is debug code that isn't really going to work in the end product.

My secure state looks like this:

Lua Code:
  1. self.frame.state = CreateFrame("Frame", nil, nil, "SecureHandlerStateTemplate")
  2.     self.frame.state:SetFrameRef("ZPerlPlayerPet", self.frame)
  3.     self.frame.state:SetAttribute("_onstate-vehicleupdate", [[
  4.         --print(newstate)
  5.         if newstate == "invehicle" then
  6.             self:GetFrameRef("ZPerlPlayerPet"):SetAttribute("unit", "player")
  7.         else
  8.             self:GetFrameRef("ZPerlPlayerPet"):SetAttribute("unit", "pet")
  9.         end
  10.     ]])
  11.     RegisterStateDriver(self.frame.state, "vehicleupdate", "[vehicleui] invehicle; none")

By default i only use the *ED events but thats when the issue happens, thats why i added the *ING events to hide the frame between them.

The UpdateDisplay() funtion is noting special just updates the frame, name level buffs etc. Also my SecureUnitButton has nothing special it's using the RegisterUnitWatch method.

The whole code:

https://github.com/Resike/Z-Perl2/bl.../PlayerPet.lua

SDPhantom 01-11-16 09:20 PM

You can use RegisterAttributeDriver() to securely swap the unit of a SecureUnitFrame. Just use this to replace the entire self.frame.state block.
Code:

RegisterAttributeDriver(self.frame,"unit","[vehicleui] player; pet")


Updating the frame when this happens can be done with an OnAttributeChanged script hook. Since I highly doubt you're doing anything protected in PlayerPet:UpdateDisplay(), you can just call that.
Code:

self.frame:HookScript("OnAttributeChanged",function() PlayerPet:UpdateDisplay(); end)

Resike 01-12-16 04:51 AM

Quote:

Originally Posted by SDPhantom (Post 312533)
You can use RegisterAttributeDriver() to securely swap the unit of a SecureUnitFrame. Just use this to replace the entire self.frame.state block.
Code:

RegisterAttributeDriver(self.frame,"unit","[vehicleui] player; pet")


Updating the frame when this happens can be done with an OnAttributeChanged script hook. Since I highly doubt you're doing anything protected in PlayerPet:UpdateDisplay(), you can just call that.
Code:

self.frame:HookScript("OnAttributeChanged",function() PlayerPet:UpdateDisplay(); end)

Thanks, gonna try it.

Resike 01-12-16 06:07 AM

It looks pretty cool now, however it's still a bit out of sync. Would it be possible to write a driver which gets triggered exactly at UNIT_ENTERED_VEHICLE and UNIT_EXITING_VEHICLE?

https://www.youtube.com/watch?v=QxNeWByv4b4

SDPhantom 01-12-16 02:27 PM

As far as I know, you can register the events yourself without tainting the secure driver system, but I'm not 100% sure.
Code:

SecureStateDriverManager:RegisterEvent("UNIT_ENTERED_VEHICLE");
SecureStateDriverManager:RegisterEvent("UNIT_EXITING_VEHICLE");

While it doesn't exactly trigger at that moment, it'll run on the next OnUpdate immediately following the event.

Resike 01-12-16 03:09 PM

Quote:

Originally Posted by SDPhantom (Post 312560)
As far as I know, you can register the events yourself without tainting the secure driver system, but I'm not 100% sure.
Code:

SecureStateDriverManager:RegisterEvent("UNIT_ENTERED_VEHICLE");
SecureStateDriverManager:RegisterEvent("UNIT_EXITING_VEHICLE");

While it doesn't exactly trigger at that moment, it'll run on the next OnUpdate immediately following the event.

How can i use this exactly?

SDPhantom 01-12-16 03:20 PM

Just add those lines as-is to your code. It registers those events to the secure frame that manages RegisterAttributeDriver().
This frame is found in SecureStateDriver.lua.

Resike 01-12-16 03:32 PM

Quote:

Originally Posted by SDPhantom (Post 312563)
Just add those lines as-is to your code. It registers those events to the secure frame that manages RegisterAttributeDriver().

Tried it but it looks same.

The problem is that the vehicleui trigger gets triggered before those events so it pointless to scan the state again after. It would be nice to only scan on this two events.

SDPhantom 01-12-16 04:45 PM

RegisterAttributeDriver() is just handling what unit is selected when you click on the frame and should handle RegisterUnitWatch() fine on its own. It's just a more direct approach to what you were already doing. The display code, you can do whatever you want and it isn't going to hurt the SecureUnitFrame. The problem is still located there. Try taking the code back to the basics and replace the 4 vehicle event blocks with this. Don't forget to unregister UNIT_ENTERING_VEHICLE and UNIT_EXITED_VEHICLE.
Lua Code:
  1. function Player:UNIT_ENTERED_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  2.     if showVehicleUI then
  3.         self.frame.unit = "player"
  4.         self:UpdateDisplay()
  5.     end
  6. end
  7.  
  8. function Player:UNIT_EXITING_VEHICLE()
  9.     if self.frame.unit ~= "pet" then
  10.         self.frame.unit = "pet"
  11.         self:UpdateDisplay()
  12.     end
  13. end
(Code taken from Player.lua and modified)

Resike 01-12-16 06:47 PM

Quote:

Originally Posted by SDPhantom (Post 312569)
RegisterAttributeDriver() is just handling what unit is selected when you click on the frame and should handle RegisterUnitWatch() fine on its own. It's just a more direct approach to what you were already doing. The display code, you can do whatever you want and it isn't going to hurt the SecureUnitFrame. The problem is still located there. Try taking the code back to the basics and replace the 4 vehicle event blocks with this. Don't forget to unregister UNIT_ENTERING_VEHICLE and UNIT_EXITED_VEHICLE.
Lua Code:
  1. function Player:UNIT_ENTERED_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  2.     if showVehicleUI then
  3.         self.frame.unit = "player"
  4.         self:UpdateDisplay()
  5.     end
  6. end
  7.  
  8. function Player:UNIT_EXITING_VEHICLE()
  9.     if self.frame.unit ~= "pet" then
  10.         self.frame.unit = "pet"
  11.         self:UpdateDisplay()
  12.     end
  13. end
(Code taken from Player.lua and modified)

But this is pretty much the code i had in the first place, which i had the original issue with.

Here is a video about it:

https://www.youtube.com/watch?v=IgjRxkEk5TM

Resike 01-12-16 07:32 PM

I figured i can dodge the entering issue if i unregister and reregister some events:

Lua Code:
  1. function PlayerPet:UNIT_ENTERING_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  2.     if showVehicleUI then
  3.         --[[if not InCombatLockdown() then
  4.             UnregisterUnitWatch(self.frame)
  5.             self.frame:Hide()
  6.         end]]
  7.         self.events:UnregisterEvent("UNIT_AURA")
  8.         self.events:UnregisterEvent("UNIT_HEALTH_FREQUENT")
  9.         self.events:UnregisterEvent("UNIT_POWER_FREQUENT")
  10.         self.events:UnregisterEvent("UNIT_NAME_UPDATE")
  11.         self.events:UnregisterEvent("UNIT_FACTION")
  12.         self.events:UnregisterEvent("UNIT_PET")
  13.         self.events:UnregisterEvent("UNIT_FLAGS")
  14.         --self.frame.unit = "player"
  15.         --self:UpdateDisplay()
  16.     end
  17. end
  18.  
  19. function PlayerPet:UNIT_ENTERED_VEHICLE(unit, showVehicleUI, arg3, vehicleType, vehicleID, arg6, vehicleGUID, arg8, arg9)
  20.     if showVehicleUI then
  21.         self:RegisterEvents()
  22.         --[[if not InCombatLockdown() then
  23.             RegisterUnitWatch(self.frame)
  24.         end]]
  25.         self.frame.unit = "player"
  26.         self:UpdateDisplay()
  27.     end
  28. end

Still not sure about what could be done with the exiting issue.


All times are GMT -6. The time now is 02:11 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI