Thread Tools Display Modes
12-04-15, 02:11 PM   #1
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
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.
  Reply With Quote
12-04-15, 02:24 PM   #2
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
[vehicleui]

10charshello
__________________
Grab your sword and fight the Horde!
  Reply With Quote
12-04-15, 02:33 PM   #3
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Lombra View Post
[vehicleui]

10charshello
I hate you. JK thanks.
  Reply With Quote
01-11-16, 09:21 AM   #4
Taudier
A Wyrmkin Dreamwalker
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 53
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

Last edited by Taudier : 01-11-16 at 09:34 AM.
  Reply With Quote
01-11-16, 09:52 AM   #5
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by Taudier View Post
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?
  Reply With Quote
01-11-16, 02:29 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
01-11-16, 03:40 PM   #7
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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
  Reply With Quote
01-11-16, 04:42 PM   #8
Taudier
A Wyrmkin Dreamwalker
AddOn Author - Click to view addons
Join Date: Apr 2008
Posts: 53
Originally Posted by Resike View Post
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

Last edited by Taudier : 01-11-16 at 05:02 PM.
  Reply With Quote
01-11-16, 06:00 PM   #9
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Resike View Post
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 01-11-16 at 06:19 PM.
  Reply With Quote
01-11-16, 07:19 PM   #10
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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
  Reply With Quote
01-11-16, 09:20 PM   #11
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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)
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 01-11-16 at 09:58 PM.
  Reply With Quote
01-12-16, 04:51 AM   #12
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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.
  Reply With Quote
01-12-16, 06:07 AM   #13
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
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
  Reply With Quote
01-12-16, 02:27 PM   #14
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 01-12-16 at 02:30 PM.
  Reply With Quote
01-12-16, 03:09 PM   #15
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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?

Last edited by Resike : 01-12-16 at 03:13 PM.
  Reply With Quote
01-12-16, 03:20 PM   #16
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 01-12-16 at 03:34 PM.
  Reply With Quote
01-12-16, 03:32 PM   #17
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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.

Last edited by Resike : 01-12-16 at 03:55 PM.
  Reply With Quote
01-12-16, 04:45 PM   #18
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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)
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 01-12-16 at 04:53 PM.
  Reply With Quote
01-12-16, 06:47 PM   #19
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
Originally Posted by SDPhantom View Post
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

Last edited by Resike : 01-12-16 at 07:18 PM.
  Reply With Quote
01-12-16, 07:32 PM   #20
Resike
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,290
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.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » SecureHandlerState

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off