Reagera på WoW-event Att använda OnUpdate Introduktion Att kapa funktioner Automatisering och AI
Introduktion pptplex Section Divider The slides after this divider will be grouped into a section and given the label you type above. Feel free to move this slide to any position in the deck.
In i spelvärlden Det händer en massa saker i WoW Förutsättningarna förändras hela tiden Hur kan man koppla sin kod till vad som händer? Om du vill Uppdatera din inventory-lista när man plockar upp nya saker Samla statistik på allt som händer i strid Reagera på text som kommer i chatten Ändra hur din addon funkar när man byter till Stealth-läge
Några möjligheter Reagera på signaler från WoW (events) En mängd sådana signaler skickas när saker händer/ändras Kolla läget själv hela tiden Kör din kod om och om igen och hämta färsk information Kapa funktioner WoW använder själv en massa Lua-funktioner Möjligt att ersätta dessa
Reagera på WoW-event pptplex Section Divider The slides after this divider will be grouped into a section and given the label you type above. Feel free to move this slide to any position in the deck.
Events = händelser WoW genererar en massa event för händelser och förändringar i spelvärlden Vi kan säga till WoW att vi vill få en signal när detta händer D.v.s., vi kan registrera ett intresse för ett event Funkar på motsvarande sätt som när du registrerar att en viss funktion skall köras när en knapp klickas på Istället kan en funktion anropas t.ex. när du går in i strid
Några exempel på WoW-event BAG_UPDATE Innehållet i dina bags har ändrats ADDON_LOADED En ny addon har laddats PLAYER_TARGET_CHANGED Din target har ändrats COMBAT_LOG_EVENT_UNFILTERED Något händer i strid komplex event med mycket information De flesta innehåller väldigt lite information i sig själva Använd andra funktioner för att kolla upp detaljerna Använd /eventtrace för att se hur dessa skickas i praktiken!
Hur man registrerar sitt intresse Använd self:registerevent för att registrera intresse self:registerevent( PLAYER_TARGET_CHANGED ) Jämför med self:registerforclicks för musklick En script/event-hanterare kopplas till OnEvent för en frame Motsvarar alltså OnClick för klick på en knapp En event-hanterare för OnEvent får self (framen) och namnet på eventet som argument, plus fler beroende på eventet function MyFrame_OnEvent(self,event, ) print( Fick event:.. event) end
Hur man registrerar sitt intresse Kör self:registerevent flera gånger för att lägga till flera event self:registerevent( PLAYER_TARGET_CHANGED ) self:registerevent( UNIT_COMBAT ) Man kan använda self:unregisterevent för att avregistrera intresse av ett event Dessa metoderna sätter alltså intresset för varje event för sig Man kan använda self:registerallevents och self:unregisterallevents för att för att (av)registrera intresse för alla event samtidigt Använd bara dessa om ni verkligen skall lyssna på många events
En event-hanterare Eftersom alla event kommer till samma funktion måste man kolla namnet på eventet function MyFrame_OnEvent(self,event, ) if event == PLAYER_TARGET_CHANGED then print( Vi har en ny target! ) elseif event == UNIT_COMBAT then MyFrame_OnEvent_UNIT_COMBAT(self, ) se nedan end end Kan vara smidigt att skicka vidare till andra funktioner T.ex. för att få argumenten rätt function MyFrame_OnEvent_UNIT_COMBAT( self,unitid,action,descriptor,damage,damagetype)... end
Exempel: Beräkna DPS En närmare titt på hur vi kan få information om skada i strid Om vi vill räkna ut DPS behöver vi veta exakt när vi strider När vi börjar, slutar, och tiden däremellan Dessutom vill vi veta när vi gör eller tar skada Några lovande event för detta är: PLAYER_REGEN_DISABLED/ENABLED Ett säkert tecken på att vi är i strid, oavsett vem som startade den UNIT_COMBAT Information om händelser i strid som t.ex. skada, helande, duckar, osv PLAYER_ENTER/LEAVE_COMBAT Spelaren går in/ut ur i närstrid (melee) Det är endast UNIT_COMBAT av dessa som har argument
Exempel: Beräkna DPS Enklast att skriva ut DPS för en strid när den är slut Spara undan starttiden när striden startar Addera ihop skada under striden Räkna ut den totala tiden när striden slutar Dividera skada med tid DPS! Vi kan använda PLAYER_REGEN_DISABLED/ENABLED och GetTime() för att få/räkna ut tiden Skadan på från argumentet damage till UNIT_COMBAT när de andra argumenten är action == WOUND unitid == player
Exempel: Beräkna DPS
Att använda OnUpdate pptplex Section Divider The slides after this divider will be grouped into a section and given the label you type above. Feel free to move this slide to any position in the deck.
Vad är OnUpdate? En speciell sorts event som skickas varje bild-frame D.v.s. med en frekvens motsvarande din fps/framerate T.ex. 60 ggr per sekund Kopplas till en egen script-hanterare (OnUpdate) på en frame <OnUpdate> </OnUpdate> på samma vis som OnClick, OnEvent, osv
Användningsområden I princip skulle du kunna kolla hur det ligger till hela tiden T.ex. kolla varje frame om du är i strid för att se när det ändras Detta är dock oftast en dålig lösning Tar mycket prestanda i onödan eftersom det körs ofta Anpassade events är mycket bättre! Kan passa bra ibland! När du vill göra något med en fördröjning Spara en starttid och kolla tiden varje frame tills det har gått önskad tid Göra något flera gånger med lagom tid emellan När du vill se hur något ändras dynamiskt hela tiden Samla ihop (gruppera) andra events som kommer i snabb följd
Tips Kör inte OnUpdate-skript i onödan Leta efter specifika events först Du kan starta och stoppa OnUpdate vid behov genom att Visa/gömma den tillhörande framen (behöver inte synas) Sätta skript-hanteraren till din funktion eller till nil Detta kan användas till att t.ex. stoppa OnUpdate efter en fördröjning eller efter att en övervakad situation är över T.ex. för att starta en OnUpdate-bevakare när du går in i strid och stäng av den när du går ut ur strid Kan även användas för att skapa animeringar och effekter T.ex. om man vill göra små spel
Att kapa funktioner pptplex Section Divider The slides after this divider will be grouped into a section and given the label you type above. Feel free to move this slide to any position in the deck.
Enkel grundprincip WoW använder själv många Lua-funktioner för att göra saker Alla funktioner i Lua är variabler Vi kan ändra vad variabler innehåller Stoppa dit en annan (egen) funktion istället för den tidigare T.ex. definiera om print() så att den skriver allt till en egen message-frame print = function ( ) -- (din kod) end Att kapa en funktion på detta sätt kallas för att hooka den
Bevara existerande funktionalitet Om du ersätter en funktion rakt av kommer mycket annan kod som använder den antagligen att sluta fungera Normalt sparar du den gamla funktionen och använder den som en del av din nya funktion original_print = print print = function ( ) original_print( Min print:, ) end Du kan ändra på argument till och returvärden från orginalfunktionen
Funkar även på skript-hanterare Använd :GetScript( ) för att få den tidigare funktionen Spara den gamla hanteraren och använd den som tidigare original_onclick = frame:getscript( OnClick ) function MyOnClick( ) -- min kod original_onclick( ) end frame:setscript( OnClick,MyOnClick) Ser alltså till att det som den som satte den första hanteraren förväntar sig fortfarande händer
Komplikationer Komplicerat att hålla reda på alla argument Svårt att överblicka konsekvenserna för alla ställen där en funktion används Vi vet inte var den används, eller hur Andra addons kan redan ha hookat funktionen Blir kedjor som är svåra att kontrollera Om funktionen används av säker kod blir det fel Vi återkommer mer till säker kod nästa vecka
Hooka säkert Det finns speciella funktioner för att hooka säkert Det innebär dock restriktioner på vad man kan göra hooksecurefunc Hooka vilken funktion som helst utan att få problem med säker kod frame:hookscript Hooka script säkert För båda dessa gäller att Du behöver inte spara undan orginalfunktionen Den anropas alltid före din funktion ändå Du kan inte ändra på argument eller returvärden Funkar alltså i princip som en extra sorts event-hanterare
Sällan bästa alternativet Många potentiella problem som sagt Finns oftast alternativ Event som passar är bättre Kan skapa en osynlig frame och koppla till en annan Om ni måste hooka en funktion Använd hooksecurefunc eller frame:hookscript om möjligt Annars var försiktig!
Automatisering och AI pptplex Section Divider The slides after this divider will be grouped into a section and given the label you type above. Feel free to move this slide to any position in the deck.
Automatisering gillas inte i WoW Blizzard har bestämt sig för att inte tillåta automatisering Tanken är att spelaren alltid skall behöva vara aktiv Om man hade velat hade automatisering varit enkelt Tänk er funktioner för att springa åt ett håll, eller till en koordinat Det finns inga tekniska hinder för detta Events för enheter, mineraler, osv, som kommer inom räckhåll Låta program planera exakt i vilken ordning spells skall kastas för att få ihjäl en enhet så snabbt som möjligt Och utföra planen automatiskt
Två grova indelningar av AI Reaktiv och/eller planerande AI (Artificiell Intelligens) Reaktiv AI är i princip event-drivet beteende En enhet kommer inom range spring direkt mot den Planerande AI innebär att man överväger många olika handlingar och bygger upp en plan som man sedan följer Vad skulle hända om (som i schack) Modern AI är oftast en kombination Man gör en plan men är beredd att ändra den reaktivt Kombinerar planer på högre nivåer med reaktioner på lägre
Artificiell perception Generellt sett ett svårt problem Om man börjar ha många enheter som ser långt blir det mycket att testa Svårt att bedöma vad man verkligen borde se Med väggar och liknande hinder WoW är relativt glest befolkat och enheter har oftast en relativt kort range Man rör sig relativt långsamt behöver inte uppdatera så ofta Enheter bryr sig sällan om varandra kollisioner ignoreras