WCell Addons

From WCell Wiki
Jump to: navigation, search

Introduction

  • WCell uses Addons to extend customization
  • These Addons are external libraries and are completely separate from the core itself. They are limited only by your own imagination. Using WCell's powerful API, you can do almost everything while keeping the core itself untouched (and thus minimizing indirectly caused bugs, also known as regressions)
  • You can easily modify any Spell, Quest, NPC, Instance, Battleground as well as many other things on the RealmServer
  • Addons can also be used to customize the AuthServer
  • Addons are event driven. Nearly all major pieces of code trigger or should trigger events
  • Addons can be written in any .NET supported language, such as: C#, F#, VB, etc

Important Addons

Usage

  • Both RealmServer and AuthServer are capable of loading .NET DLLs (so called Assemblies) at startup and during runtime
  • Addons can not currently be un-loaded or re-loaded once they have been loaded the first time
  • All .dll files within the AddonFolder and its sub folders (by default Run/RealmServerAddons and Run/AuthServerAddons) are automatically to be loaded when the server starts
  • You can specify that you want to exclude certain files or folders by adding them to your Config.xml:
    • IgnoredAddonFiles is a string of files and folders to be ignored, seperated by a semicolon (;)
  • There are two types of Assemblies that can be loaded:
    • Actual Addons that have one class that implements IWCellAddon and can have a configuration and whose global variables can be manipulated at runtime
    • Library files that are used by actual Addons and cannot be configured or manipulated at runtime

Creating Addons

Setup

This guide shows how to create an addon, step by step. We will be using Visual C# Express Edition as our IDE because it is powerful, free and easy to use for every beginner.

PROTIP: Usually you want to create a new solution for every Addon and add all of WCell's projects that you will use (except for maybe WCell.Constants) to it.

Creating a new project

  1. Create a new Project (Screenshot)
    1. Choose Class Library
    2. Name it whatever you want (should be descriptive and you might want to consider embedding "WCell" and "Addon" into the name)
    3. Location: Addons/
    4. Solution: Create new Solution
    5. Uncheck Create directory for solution
  2. Add references
    1. Add the following WCell projects - WCell.Core,WCell.Constants,WCell.RealmServer,WCell.Util.
    2. Expand the references block
    3. Right click on references
    4. Choose the Projects tab and select WCell.Core, WCell.Constants, WCell.RealmServer, WCell.Util and anything else that you might need/want
  3. Set Copy Local of all WCell*, NHibernate, ActiveRecord, logging references and all other references that are part of the WCell core, to False!
  4. Set the Output Path
    1. Right-click your Addon project in the Solution Explorer and select Properties
    2. Go to the Build tab
    3. Set Output Path to: ..\..\Run\RealmServerAddons\
  5. Check twice that all your settings are correct
    • WARNING: The exact location of your files is important - If locations are wrong, WCell will not find your Addon!
    • Make sure that the new csproj file (automatically created by VS) is in the right location
    • For example:
      1. If your Addon's name is: WCellIrcAddon
      2. Then you must have this file: YourWCellFolder/Addons/WCellIrcAddon/WCellIrcAddon.csproj
  6. Test your Addon

Coding

How to develop a WCell-Addon

Implementing IWCellAddon

NOTE: This can be a a completely standalone class, containing no other code than the implementation of WCellAddonBase members.

Initialization

		[Initialization(InitializationPass.Second)]
		public static void FixConeOfCold()
		{
			// Cone of cold is missing Range
			SpellLineId.MageConeOfCold.Apply(spell =>
			{
				spell.Range.MaxDist = 10;
			});
		}

		[Initialization]
		[DependentInitialization(typeof(GOMgr))]
		public static void InitGOs()
		{
                    // do something to GOs
		}

		[Initialization]
		[DependentInitialization(typeof(NPCMgr))]
		[DependentInitialization(typeof(ItemMgr))]
		public static void InitNPCs()
		{
		    // do something to NPCs and Items
		}

NOTE: These methods can be declared in any public Type, as far as it still is a part of the Addon's project and has the aforementioned attribute. The process of essay writing will be much easier with MarvelousEssays.Com as there are a lot of highly professional and talented writers who are always eager to help you out with any sort of academic assignments regardless of the complexity levels. I do know what I�m talking about!

Add content

Addon Configuration

  • Addons have been hooked up to the same configuration system both RealmServer and AuthServer are using.
  • If you want an Addon with a configuration file, declare UseConfig true in the class which implements WCellAddonBase.
       public override bool UseConfig
       {
           get { return true; }
       }
  • If you want certain fields or properties to be configurable, declare it public static and the value in your code will be the default value.
  • The field or parameter can be string, any enum type, primitive type, or array or IList<T> of such
  • An example of 4 nodes: an int, a boolean, a string and an enum:
       public static int ReConnectWaitTimer = 5;
       public static bool ReJoinOnKick = true;
       public static string WCellCmdPrefix = "#";
       public static IrcCmdCallingRange IrcCmdCallingRange = IrcCmdCallingRange.LocalChannel;
  • Properties can be configurable as well:
       public static int SendQueue
       {
           get { return ThrottledSendQueue.CharsPerSecond; }
           set { ThrottledSendQueue.CharsPerSecond = value; }
       }

Changing the Configuration during runtime

You can use the Config command from the console, from inside the game or through any other interface application that is connected to your server, such as the IRC Addon.

An Example Addon

using System.Globalization;

using WCell.Core.Addons;

using WCell.RealmServer.Spells;
using WCell.RealmServer.Entities;
using WCell.Constants.Spells;
using WCell.Core.Initialization;
using WCell.RealmServer.Chat;
using WCell.Util.Graphics;

namespace WCell.Addons
{
	/// <summary>
	/// WCell's own default addon. Contains some useful additions to the WCell RealmServer that should not be part of the Core.
	/// </summary>
	public class DefaultAddon : WCellAddonBase
	{
		public const SpellId TeleSpellId = //SpellId.UnusedNPCPORTTEST;
			SpellId.UnusedDistractTest;

		public override bool UseConfig
		{
			get { return true; }
		}

		#region WCellAddon Members
		public override string Name
		{
			get { return "WCell Default Addon"; }
		}

		public override string ShortName
		{
			get { return "Default"; }
		}

		public override string Author
		{
			get { return "The WCell Team"; }
		}

		public override string Website
		{
			get { return "http://wcell.org"; }
		}

		public override string GetLocalizedName(CultureInfo culture)
		{
			return "WCell Default Addon";
		}

		public override void TearDown()
		{
			// does nothing
		}

		/// <summary>
		/// Add something to the Last Initialization-Step, so that WCell is already fully initialized before this method is called.
		/// </summary>
		[Initialization(InitializationPass.Last, "Initialize Default Addon")]
		public static void Init()
		{
			// Make some deprecated spell (with an area target) an instant teleport spell:
			SpellHandler.Get(TeleSpellId).SpecialCast = delegate(Spell spell, WorldObject caster, WorldObject target, ref Vector3 targetPos)
			{
				if (caster is Unit)
				{
					var unitCaster = caster as Unit;
					unitCaster.TeleportTo(unitCaster.Region, ref targetPos);
				}
			};

			// add the spell to any newly created staff-Character
			Character.Created += chr =>
			{
				if (chr.Account.Role.IsStaff)
				{
					chr.Spells.Add(TeleSpellId);
				}
			};

			// let staff members join the staff channel
			Character.LoggedIn += (chr, firstConnect) =>
			{
				if (firstConnect)
				{
					if (chr.Account.Role.IsStaff && ChatChannel.Staff != null)
					{
						ChatChannel.Staff.TryJoin(chr);
					}
				}
			};
		}
		#endregion
	}
}


Test your Addon

  • Make sure that you followed the Output Path instructions
  • Compile your Addon
  • Run WCell
  • Early during startup you will see a list of all loaded Addons
  • Your Addon must be in that list!
    • If it is not listed, you did something wrong
    • In that case, make sure that YourAddon.dll is in the correct path
    • If it is in the path, consider the <Addon> node in your Configuration, and check that the Addon and it's parent folders are not ignored
    • If you have further questions ask the Community for advice
  • Once loaded, initialization steps in the Addon will be executed and your changes will take effect

Community