📜 ⬆️ ⬇️

Writing AddOn to World of Warcraft

On Habré, they somehow wrote about creating bots for WoW , but I didn’t find articles about add-ons and decided to describe this process using the example of one crafts that I wrote long ago when I was still a student and I had enough time to play in World of Warcraft and the creation of add-ons to it. With money then it was tight and I did not play on the official server, but on one of the free ones, which has a lot of imperfections, bugs, features and anomalies.


After the random use of one of them, I was banned, the idea to create an addon, indicating in the game all the differences of this shard from the official server, appeared, with warnings about the penalties for their use.

I put the addon on Google Code and the server forum and it became quite popular (as for a pirate server). Who cares how add-ons are made - Wellcome under the cat.

Introduction


So let's start with the definition. The addon in WoW is a collection of some files that allow the user to change the interface of the client part of the game, but does not affect the server game mechanics. The addons were originally in WoW, which favorably distinguishes this MMORPG from some others, screaming about their superiority, but not having the ability to create official addons to this day. Addonov there are thousands , if not tens of thousands. Why so much? And because the styles of the game and game tasks are exactly the same. And of course, the developers are great, that from the very beginning they gave a way for everyone to create something of their own, and not to impose a single interface, demanding that it be considered convenient.
')
The main source of documentation when creating an addon will be the WoWWiki portal. A couple of related links:

There is still a lot of useful information there, but you can get to it by following links from these four pages in a couple of clicks.

Tools


No special tools for creating add-ons are needed. All of them are text files, so take your favorite text editor and go ahead! If it has a highlight of the syntax of the Lua language (it is on it that add-ons are created), it is generally fine. For example, Notepad ++ meets these requirements.
Moreover, enthusiasts created on the basis of the Free Visual Studio Shell engine a special open-source IDE called AddOn Studio .



The thing is cool and takes on a number of functions, such as:

+ a couple other fun stuff. In general, you can use. Well, you can still view this page , maybe you will find a plugin for your favorite IDE or just something familiar.

A couple of conceptual moments.




What is the addon


1. TOC-file (table of conteset). This is the table of contents of our addon. Explains to the WoW shell who we are, what we call ourselves, who the author is, what we are made up of and a couple of other things. Here, for example, my addon's toc file:
## Interface: 30000 ## Title: Wnet Featurer 1.3 ## Notes: Wnet Server Features List ## RequiredDeps: ## OptionalDeps: ## LoadWith: Blizzard_TalentUI ## SavedVariables: Data.lua WnetWarnings.lua WnetFeaturer.xml 


2. XML files describing changes in the interface that we want to make (frames, buttons, binding events in the interface to certain functions in the code). Here is the xml file of my addon:
 <Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.blizzard.com/wow/ui/" xmlns="http://www.blizzard.com/wow/ui/"> <Script file="WnetFeaturer.lua" /> <Frame name="WnetFeaturerFrame"> <Scripts> <OnLoad> WnetFeaturer_OnLoad(self); </OnLoad> <OnEvent> WnetFeaturer_OnEvent(self, event, ...); </OnEvent> </Scripts> </Frame> <Frame name="GameTooltip" parent="GameTooltip"> <Scripts> <OnUpdate> WnetChecker_GameTooltip_OnUpdate(); </OnUpdate> </Scripts> </Frame> </Ui> 


What is written here? We declare the binding of this interface file to the WnetFeaturer.lua code file, then declare two frames - one purely for being able to hang your event on the plug-in loading events, the second will be used in the game to show your own tooltips (tips) to certain objects of the game world.

3. Lua files . This is the Lua code. It must be admitted that Lua in WoW is somewhat trimmed (details can be read in WoWWiki), but for most tasks it is enough. Here is one of the addon code files (the shortest).

 --     (    ) local before_wnet_featurer_old_QuestFrameDetailPanel_OnShow = QuestFrameDetailPanel_OnShow; function WnetFeaturer_Log( text ) SELECTED_CHAT_FRAME:AddMessage( text ); end function WnetFeaturer_OnLoad(self) if ( not IsAddOnLoaded( "Blizzard_TalentUI" ) ) then _, reason = LoadAddOn( "Blizzard_TalentUI" ); end if ( reason ) then return; end -- Hook the Talent Frame's Update function hooksecurefunc( "TalentFrame_Update", Planner_TalentFrame_AfterUpdate ); -- Register for Loading Variables self:RegisterEvent( "PLAYER_ENTERING_WORLD" ); self:RegisterEvent( "PLAYER_LEAVING_WORLD" ); -- Locale/Gender-neutral class names FTW wnet_featurer_classes = { [1] = "DEATHKNIGHT", [2] = "DRUID", [3] = "HUNTER", [4] = "MAGE", [5] = "PALADIN", [6] = "PRIEST", [7] = "ROGUE", [8] = "SHAMAN", [9] = "WARLOCK", [10] = "WARRIOR", }; end function WnetFeaturer_OnEvent( self, event, ... ) if ( event == "PLAYER_ENTERING_WORLD" ) then tp_name = UnitName( "player" ).." of "..GetRealmName(); _, class = UnitClass( "player" ); for k, v in ipairs( wnet_featurer_classes ) do if ( v == class ) then tp_class = k; end end elseif ( tp_name ) then if ( event == "PLAYER_LEAVING_WORLD" ) then tp_name = nil; tp_class = nil; end end end function Planner_TalentFrame_AfterUpdate( frame ) local page = PanelTemplates_GetSelectedTab( PlayerTalentFrame ); local numTalents = GetNumTalents( page ); local inspect = PlayerTalentFrame.inspect; local pet = PlayerTalentFrame.pet; local _, class = UnitClass( "player" ); if ( pet or tp_standby or not tp_name or not tp_class or frame ~= PlayerTalentFrame or inspect ) then return; end for id = 1, numTalents, 1 do local name, texture, row, col, rank, maxRank = GetTalentInfo( page, id ); local color = nil; if( wnet_talents[tp_class][page][name] ) then color = wnet_talents[tp_class][page][name]; else color = NORMAL_COLOR; end if ( color ) then getglobal( "PlayerTalentFrameTalent"..id.."Slot" ):SetVertexColor( color.r, color.g, color.b ); getglobal( "PlayerTalentFrameTalent"..id.."RankBorder" ):Show(); getglobal( "PlayerTalentFrameTalent"..id.."Rank" ):SetText( rank.."/"..maxRank.." " ); getglobal( "PlayerTalentFrameTalent"..id.."Rank" ):Show(); else getglobal( "PlayerTalentFrameTalent"..id.."RankBorder" ):Hide(); getglobal( "PlayerTalentFrameTalent"..id.."Rank" ):Hide(); end end end function checkIsItemValid( text ) if ( wnet_items[text] ) then return 1; else return nil; end end function checkIsNPCValid( text ) if ( wnet_npc[text] ) then return 1; else return nil; end end WnetChecker_GameTooltip_OnUpdate=function() local errorString = nil; for i=1, GameTooltip:NumLines(), 1 do local currentTooltipStr = getglobal("GameTooltipTextLeft"..i):GetText(); --   NPC   if ( i == 1 ) then -- NPC        .    . if( checkIsNPCValid( currentTooltipStr ) ) then errorString = "Wnet:  NPC   !"; elseif( checkIsItemValid( currentTooltipStr ) ) then errorString = "Wnet:     !"; end end if strfind( currentTooltipStr, "Unique(.)Equipped" ) then errorString = "Wnet:  2   !"; elseif strfind( currentTooltipStr, "Target Dummy" ) then errorString = "Wnet:  2   !"; elseif( strfind( currentTooltipStr, "Chance on hit(.) Stuns target for" ) or strfind( currentTooltipStr, "Chance on hit(.)   " ) ) then errorString = "Wnet:    !"; elseif( strfind( currentTooltipStr, "Chance on hit(.) Knocks target silly for" ) ) then errorString = "Wnet:    !"; elseif( strfind( currentTooltipStr, "Blackblade of Shahram" ) ) then errorString = "Wnet:    !"; elseif( strfind( currentTooltipStr, "Seduction" ) ) then errorString = "Wnet:   !"; elseif( strfind( currentTooltipStr, "Ursius" ) or strfind( currentTooltipStr, "Avian Darkhawk" ) or strfind( currentTooltipStr, "Avian Ripper" ) or strfind( currentTooltipStr, "Windroc Matriarch" ) ) then errorString = "Wnet:   !"; elseif( strfind( currentTooltipStr, "Wnet:") ) then errorString = nil; end end if errorString then GameTooltip:AddLine( errorString, 1, 0, 0 ); local i; local s=10; for i=1, GameTooltip:NumLines(), 1 do s=s+getglobal("GameTooltipTextLeft"..i):GetHeight()+2; end GameTooltip:SetHeight(s+10); GameTooltip:SetWidth( max( GameTooltip:GetWidth(), 300 ) ); end end function checkIsQuestNotValid( questTitle ) if ( wnet_quests[questTitle] ) then return 1; else return nil; end end QuestFrameDetailPanel_OnShow=function() before_wnet_featurer_old_QuestFrameDetailPanel_OnShow(); if( checkIsQuestNotValid( GetTitleText() ) ) then QuestDescription:SetText("|c00ff0000 Wnet:     !|r|n"..GetQuestText()); end end 

This code performs the following tasks:


There are a couple of code files in the project, but for the most part they are simply the base of invalid objects and their signatures. Interest does not cause.
Full source code can be viewed here: http://code.google.com/p/wnet-featurer/downloads/list
But the topic on the forum, where I described in more detail the features of the add-on.

I would be glad if it helps someone. Ask if something is unclear.

Source: https://habr.com/ru/post/119312/


All Articles