Core: Server-Played Characters menu

User Tag List

Results 1 to 14 of 14
  1. #1
    DWord's Avatar Private
    Reputation
    33
    Join Date
    Jun 2011
    Posts
    5
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Core: Server-Played Characters

    ArcEmu Core Customization: Server-Player Characters
    Background:
    Before I begin with the setup, I would like to give credit to iindigo for the conceptual component which serves as the basis of this core customization. On his original thread entitled: An intriguing possibility, there was discussion of utilizing the Mirror Image client-server-message/packet to implement NPCs who appeared exactly as players on the client. However, it appears that no action was actually taken to implement this concept.

    The aim of the customization is to implement exactly this functionality such that NPCs will be able to mirror the visuals of legitimate players. This serves as an ArcEmu alternative to the third-party Trinity content which enables "scripted" players. The advantages of this particular approach include:

    1) The implementation is light-weight involving only a few minor core edits.
    2) It's structured dynamically, taking advantage of MySQL tables.
    3) The units used are NPCs and thus can be integrated with ArcEmu's powerful scripting subsystem.


    Setup:
    To use this customization you'll need:
    a) A MySQL database management tool (i.e. Navicat/HeidiSQL)
    b) A C++ Integrated Development Environment such as Visual Studio C++ or the equivalent components (i.e. compiler, assembler, linker)
    c) The ArcEmu core (any remotely modern revision will suffice; however, I'm using a slightly older revision)


    Breakdown: The customization is relatively simple. To the core we will add a single header file which I have named ServerPlayedCharacter.h, a single source file which I have named ServerPlayedCharacter.cpp and we will be slightly modifying the World.cpp, WorldSession.cpp and Unit.cpp source files as well as the StdAfx.h header. In addition, we will be adding a table to the world MySQL database which must be named: server_played_character for which I will provide the SQL structure.


    Core Modifications:

    We'll first begin with the core modifications. The first step is to create two files (a header file and a source file, respectively). The code for ServerPlayedCharacter.h and ServerPlayedCharacter.cpp is given below.

    ServerPlayedCharacter.h Body:

    Code:
    #ifndef __SERVER_PLAYED_CHARACTER_H_
    #define __SERVER_PLAYED_CHARACTER_H_
    
    class TaskList;
    class Unit;
    
    enum PlayerRace
    {
    	P_RACE_HUMAN				= 1,
        P_RACE_ORC					= 2,
        P_RACE_DWARF				= 3,
        P_RACE_NIGHTELF				= 4,
        P_RACE_UNDEAD				= 5,
        P_RACE_TAUREN				= 6,
        P_RACE_GNOME				= 7,
        P_RACE_TROLL				= 8,
    	P_RACE_GOBLIN				= 9,
        P_RACE_BLOODELF				= 10,
        P_RACE_DRAENEI				= 11,
    	P_RACE_FELORC				= 12,
    	P_RACE_NAGA					= 13,
    	P_RACE_BROKEN				= 14,
    	P_RACE_SKELETON				= 15,
    	P_RACE_VRYKUL				= 16,
    	P_RACE_TUSKARR				= 17,
    	P_RACE_FORESTTROLL			= 18,
    	P_RACE_TAUNKA				= 19,
    	P_RACE_NORTHRENDSKELETON	= 20,
    	P_RACE_ICETROLL				= 21,
    	P_NUM_RACES					= 21
    
    };
    
    enum PlayerGender
    {
    	GENDER_MALE					= 0,
    	GENDER_FEMALE				= 1
    };
    
    enum PlayerClass
    {
    	CLASS_WARRIOR				= 1,
        CLASS_PALADIN				= 2,
        CLASS_HUNTER				= 3,
        CLASS_ROGUE					= 4,
        CLASS_PRIEST				= 5,
        CLASS_DEATHKNIGHT			= 6,
        CLASS_SHAMAN				= 7,
        CLASS_MAGE					= 8,
        CLASS_WARLOCK				= 9,
        CLASS_DRUID					= 11
    };
    
    enum UnitItemSlot
    {
    	ITEM_SLOT_HEAD				= 0,
    	ITEM_SLOT_SHOULDER			= 1,
    	ITEM_SLOT_BODY				= 2,
    	ITEM_SLOT_CHEST				= 3,
    	ITEM_SLOT_WAIST				= 4,
    	ITEM_SLOT_LEGS				= 5,
    	ITEM_SLOT_FEET				= 6,
    	ITEM_SLOT_WRITST			= 7,
    	ITEM_SLOT_HAND				= 8,
    	ITEM_SlOT_BACK				= 9,
    	ITEM_SLOT_TABARD			= 10,
    	ITEM_SLOT_MAINHAND			= 11,
    	ITEM_SLOT_OFFHAND			= 12,
    	ITEM_SLOT_RANGED			= 13,
    	NUM_ITEM_SLOTS				= 14
    };
    
    struct ServerPlayedCharacter
    {
    	uint32 entry;
    	uint8 raceId;		// also serves as the character's display index
    	uint8 gender;
    	uint8 classId;
    	uint8 skinId;
    	uint8 faceId;
    	uint8 hairStyleId;
    	uint8 hairColorId;
    	uint8 facialHairId;
    	uint32 itemId[14];
    };
    
    void LoadServerPlayedNPCFromDB(TaskList&);
    void UnitLoadMiDisplayInfo(Unit* pUnit);
    WorldPacket MirrorImagePacketHook(Unit* pUnit);
    void ServerPlayedNPCCleanup(void);
    
    #endif


    ServerPlayedCharacter.cpp Body:

    Code:
    #include "StdAfx.h"
    
    // Table format
    const char* gServerPlayedCreatureFormat = "uccccccccuuuuuuuuuuuuuu";
    // Table storage
    SERVER_DECL SQLStorage< ServerPlayedCharacter, HashMapStorageContainer<ServerPlayedCharacter> > ServerPlayedNpcStorage;
    stdext::hash_set<uint32> mirrorImagePacketHookSet;
    
    static uint32 RaceDisplayMap[P_NUM_RACES * 2 + 2] =
    {
    	0U, 0U, 49U, 50U, 51U, 52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U,
    	60U, 1563U, 1564U, 1478U, 1479U, 6894U, 6895U, 15476U, 15475U,
    	16125U, 16126U, 16981U, 16980U, 17402U, 17403U, 17576U,
    	17577U, 17578U, 17579U, 21685U, 21686U, 21780U,21780U,21963U,
    	21964U, 26316U, 26317U, 26871U, 26872U, 26873U, 26874U
    }; // maps the race index/gender in the DB to the actual display ID
    
    void LoadServerPlayedNPCFromDB(TaskList& tl)
    {
    	tl.AddTask( new Task( new CallbackP2<SQLStorage< ServerPlayedCharacter, HashMapStorageContainer<ServerPlayedCharacter> >, const char *, const char *>(&ServerPlayedNpcStorage, &SQLStorage<ServerPlayedCharacter, HashMapStorageContainer<ServerPlayedCharacter> >::Load,  "server_played_character", gServerPlayedCreatureFormat) ) );
    }
    
    void UnitLoadMiDisplayInfo(Unit* pUnit)
    {
    	ServerPlayedCharacter* infoSpc = ServerPlayedNpcStorage.LookupEntry(pUnit->GetEntry());
    	if (!infoSpc)
    		return;
    
    	if (infoSpc->raceId > (uint8)P_NUM_RACES)
    	{
    		std::cout << "Server-Player NPC with entry ID " << infoSpc->entry
    				  << " used an invalid race id: " << infoSpc->raceId << std::endl;
    		infoSpc->raceId = 0;
    	}
    	infoSpc->gender &= 0x1;
    	pUnit->SetDisplayId( RaceDisplayMap[(infoSpc->raceId << 1) | infoSpc->gender] );
    	pUnit->setRace(infoSpc->raceId);
    	pUnit->setGender(infoSpc->gender);
    	mirrorImagePacketHookSet.insert(pUnit->GetEntry());
    	pUnit->SetUInt32Value(UNIT_FIELD_FLAGS_2, pUnit->GetUInt32Value(UNIT_FIELD_FLAGS_2) | UNIT_FLAG2_MIRROR_IMAGE);
    }
    
    WorldPacket MirrorImagePacketHook(Unit* pUnit)
    {
    	ServerPlayedCharacter* infoSpc = ServerPlayedNpcStorage.LookupEntry(pUnit->GetEntry());
    	Arcemu::Util::ARCEMU_ASSERT(infoSpc != 0);
    
    	WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68);
    	data << pUnit->GetGUID();
    	data << RaceDisplayMap[(infoSpc->raceId << 1) | infoSpc->gender];
    	data << infoSpc->raceId;
    	data << infoSpc->gender;
    	if (infoSpc->classId == 10 || infoSpc->classId > 11)
    	{
    		std::cout << "Server-Played NPC with entry ID " << infoSpc->entry
    				  << " used an invalid class id: " << infoSpc->classId << std::endl;
    		infoSpc->classId = 0;
    	}
    	data << infoSpc->classId;
    	data << infoSpc->skinId;
    	data << infoSpc->faceId;
    	data << infoSpc->hairStyleId;
    	data << infoSpc->hairColorId;
    	data << infoSpc->facialHairId;
    	data << static_cast<uint32>(0);
    
    	for (uint8 i = 0; i < NUM_ITEM_SLOTS - 3; i++)
    	{
    		data << infoSpc->itemId[i];
    	}
    
    	pUnit->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, infoSpc->itemId[ITEM_SLOT_MAINHAND]);
    	pUnit->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0x1, infoSpc->itemId[ITEM_SLOT_OFFHAND]);
    	pUnit->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0x2, infoSpc->itemId[ITEM_SLOT_RANGED]);
    
    	return data;
    }
    
    void ServerPlayedNPCCleanup(void)
    {
    	ServerPlayedNpcStorage.Cleanup();
    }

    You'll need to make sure that both of these files are compiled/linked with the world-server's main code (i.e. in an IDE they are included as part of the main "world" project).


    StdAfx.h Edits:

    Next, we'll modify the StdAfx.h header file. You'll simply need to add an #include pre-processor directive (the location of which is irrelevant), including the ServerPlayedCharacter.h header so that the identifiers declared within it will be available throughout the world-server code. Within StdAfx.h, simply add the following directive:
    Code:
    #include "ServerPlayedCharacter.h"
    Below is the segment of interest of the StdAfx.h header-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg


    World.cpp Edits:

    Now we're ready to move onto the database loading/releasing in World.cpp. First, look for the function (defined/declared in global scope) called SetInitialWorldSettings(). Within that function, look for the definition of a variable of type TaskList. Below that, there should be a call to the database loader function Storage_FillTaskList() with the TaskList local as its parameter. Right below that call, add the following statement:
    Code:
    LoadServerPlayedNPCFromDB(tl);
    It should be noted that the actual argument passed to the function (here, tl) should be the TaskList local variable declared above. Below is the segment of interest of the SetInitialWorldSettings() function-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg

    The next function of interest in World.cpp is the World class' destructor method (World::~World()). In this function, we need to call our ServerPlayedNPCCleanup() function to handle closing the table, and releasing the heap-memory used to store its contents. Directly below the call to Storage_Cleanup(), you can insert the following statement:
    Code:
    ServerPlayedNPCCleanup();
    Below is an image of the segment of interest in the World class' destructor definition-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg


    Unit.cpp Edits:

    Now we can move onto the Unit.cpp for some more edits. In Unit.cpp we're looking for the Unit::OnPushToWorld method. As the final statement of this method, we'll call our UnitLoadMiDisplayInfo() function with the invoking Unit object as the parameter. This call should be added as the final statement in the Unit::OnPushToWorld method:
    Code:
    UnitLoadMiDisplayInfo(this);
    Below is an image of the (entire) updated Unit::OnPushToWorld method-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg


    WorldSession.cpp Edits:

    Now we are onto our final core edit: in WorldSession.cpp. First we are going to add a hook mechanism for the client mirror image query opcode handler. At the very top of the file (but below the #include directive for StdAfx.h) add the following external variable declaration:
    Code:
    extern stdext::hash_set<uint32> mirrorImagePacketHookSet;
    Below is an image of what the new WorldSession.cpp file should look like-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg
    Next, we are looking for the WorldSession client message handler for the CMSG_GET_MIRRORIMAGE_DATA query opcode. Conveniently, this happens to be named HandleMirrorImageOpcode, and its qualified name (i.e. the name you're looking for is): WorldSession::HandleMirrorImageOpcode. In this method, there should be code that looks like this:
    Code:
    Unit* Image = _player->GetMapMgr()->GetUnit(GUID);
    	if(Image == NULL)
    		return;

    Directly below that, add the following code:
    Code:
    stdext::hash_set<uint32>::iterator iter = mirrorImagePacketHookSet.find(Image->GetEntry());
    	if (iter != mirrorImagePacketHookSet.end())
    	{
    		WorldPacket data = MirrorImagePacketHook(Image);
    		SendPacket(&data);
    		return;
    	}

    Below is an image of the segment of interest of the WorldSession::HandleMirrorImageOpcode-- the code to insert is highlighted:
    Core: Server-Played Characters-screen-jpg


    Database Modifications:

    Into your world database, you'll need to execute the following SQL, which should insert a table named server_played_creature into the world database:
    Code:
    /*
    Navicat MySQL Data Transfer
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for `server_played_character`
    -- ----------------------------
    DROP TABLE IF EXISTS `server_played_character`;
    CREATE TABLE `server_played_character` (
      `entry` int(10) unsigned NOT NULL,
      `race_id` tinyint(4) NOT NULL,
      `gender` tinyint(1) unsigned NOT NULL,
      `class_index_id` tinyint(4) unsigned NOT NULL,
      `skin_id` tinyint(4) unsigned NOT NULL,
      `face_id` tinyint(4) unsigned NOT NULL,
      `hair_style_id` tinyint(4) unsigned NOT NULL,
      `hair_color_id` tinyint(4) unsigned NOT NULL,
      `facial_hair_id` tinyint(4) unsigned NOT NULL,
      `item_head_id` int(10) unsigned NOT NULL,
      `item_shoulder_id` int(10) unsigned NOT NULL,
      `item_body_id` int(10) unsigned NOT NULL,
      `item_chest_id` int(10) unsigned NOT NULL,
      `item_waist_id` int(10) unsigned NOT NULL,
      `item_legs_id` int(10) unsigned NOT NULL,
      `item_feet_id` int(10) unsigned NOT NULL,
      `item_wrist_id` int(10) unsigned NOT NULL,
      `item_hand_id` int(10) unsigned NOT NULL,
      `item_back_id` int(10) unsigned NOT NULL,
      `item_tabard_id` int(10) unsigned NOT NULL,
      `item_mainhand_id` int(10) unsigned NOT NULL,
      `item_offhand_id` int(10) unsigned NOT NULL,
      `item_ranged_id` int(10) unsigned NOT NULL,
      PRIMARY KEY (`entry`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


    Usage and Other Information:

    Usage:

    The new world database table, server_played_character has the following structure:
    Code:
    entry (uint32): The entry ID of the npc who will look like a player
    
    race_id (uint8): The race_id that the npc will take on; this determines the display ID of the npc (enumerated in ServerPlayedCharacter.h and Player.h
    
    gender (uint8): The gender the npc will take on: 0 = male, 1 = female
    
    class_index_id (uint8): the class that the npc will take on (enumerated in ServerPlayedCharacter.h and Player.h)
    
    skin_id (uint8): the skin identifier (i.e. skin color)
    
    face_id (uint8): the identifier that will determine what facial characteristics the npc will have
    
    hair_style_id (uint8): the identifier that will determine the style of hair the npc has
    
    facial_hair_id (uint8): the identifier that will determine what kind of facial-hair the npc will have
    
    item_displays (uint32): the display id of the item corresponding to the specific slot; the armor IDs reference into ItemDisplayInfo.dbc while the mainhand, offhand and ranged weapon IDs reference directly into Item.dbc

    Essentially, when the NPC is spawned on the client, its entry is first looked up in this table. If the entry provided corresponds to one of the entries in the server_played_character table, the information in the server_played_character will override all of the npc's display information in the creature_spawns and/or the creature_info tables.


    Low-Level Details:

    When the player update opcode is sent from the server to the client and it updates an npc's FIELD_FLAGS_2 and bit 5 in that uint32 is set in the update packet but, for the specific unit, is cleared on the client and the unit's display ID is a player display ID (i.e. dwarf, human, gnome etc.) then the client sends a packet to the server (with opcode CMSG_GET_MIRRORIMAGE_DATA). At this time (and only this time), the server needs to respond with the proper data to service the request (with the SMSG_MIRRORIMAGE_DATA opcode). Attempting to send any mirror image data to the client when the npc's display ID is not of a native player type or when its MIRROR_IMAGE field flag is cleared will merely cause the npc to become "invisible."


    Core: Server-Played Characters-screen-jpg
    I'll leave it to the scripters from here. Have fun and be sure to post any questions or suggestions below.

    Updates:

    I have added various races (although I'm not sure as to whether their client models are valid) and added support for female display IDs. In addition, it should be noted that the armor items in the SQL tables are references into the ItemDisplayInfo.dbc dbc file. However, the mainhand, offhand and ranged items are references into Item.dbc



    Attached Thumbnails Attached Thumbnails Core: Server-Played Characters-screen-jpg   Core: Server-Played Characters-screen-jpg   Core: Server-Played Characters-screen-jpg   Core: Server-Played Characters-screen-jpg   Core: Server-Played Characters-screen-jpg  

    Core: Server-Played Characters-screen-jpg  
    Last edited by DWord; 10-08-2011 at 02:14 PM. Reason: Appended to Thread

    Core: Server-Played Characters
  2. #2
    stoneharry's Avatar Moderator Harry

    Authenticator enabled
    Reputation
    1613
    Join Date
    Sep 2007
    Posts
    4,554
    Thanks G/R
    151/146
    Trade Feedback
    0 (0%)
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Excellent! Excellent work I say!

    Bravo for this, the release in its self is good, and you have guided through everything that needs to be done in a nicely formatted post.

    +Rep x7

  3. #3
    DWord's Avatar Private
    Reputation
    33
    Join Date
    Jun 2011
    Posts
    5
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by stoneharry View Post
    Excellent! Excellent work I say!

    Bravo for this, the release in its self is good, and you have guided through everything that needs to be done in a nicely formatted post.

    +Rep x7
    Thanks Harry! I really appreciate the positive comment, especially from you

  4. #4
    Reflection's Avatar Legendary
    Reputation
    783
    Join Date
    Mar 2008
    Posts
    3,377
    Thanks G/R
    1/2
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Agree with stoneharry. This is a very, very good post! Amazing work. Rep +7 from me as well!

    Freelance Digital Artist
    https://reflectionartwork.deviantart.com
    You did not desert me
    My brothers in arms


  5. #5
    AZO's Avatar Banned
    Reputation
    370
    Join Date
    Mar 2007
    Posts
    621
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Even though I'm running a different server, I'm giving rep for this. This took a lot of time, and it's very well put together. Thanks a lot for the post, man. You deserve more rep. + 5 rep from me.

  6. #6
    ZxOxZ21's Avatar Sergeant
    Reputation
    12
    Join Date
    Feb 2010
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's an exceptional work, Dword! I couldn't ever imagine it will be possible.

    The only problem I encountered was on compiling ServerPlayedCharacter.Cpp.

    There was an error on that line:

    Arcemu::Util::ARCEMU_ASSERT(infoSpc != 0);

    And I changed it with:

    ARCEMU_ASSERT(infoSpc != 0);

    And actually worked, I said that in case anyone else encounter that problem.

    Regards, ZxOxZ.

  7. #7
    reins's Avatar Private
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    4
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    good repack +rep

  8. #8
    DWord's Avatar Private
    Reputation
    33
    Join Date
    Jun 2011
    Posts
    5
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by reins View Post
    good repack +rep
    This isn't a repack, it's a core customization
    template<class _Ty> void quantum_bogosort(_Ty* list) { shuffle(list); if ( !is_sorted(list) ) /* O(n) */ destroy_the_universe(); /* O(1) */ }
    Quatnum Bogosort: The fastest sorting algorithm in the universe... until it's destroyed.

  9. #9
    Ravenware's Avatar Member
    Reputation
    6
    Join Date
    Dec 2011
    Posts
    19
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What is this?

  10. #10
    stoneharry's Avatar Moderator Harry

    Authenticator enabled
    Reputation
    1613
    Join Date
    Sep 2007
    Posts
    4,554
    Thanks G/R
    151/146
    Trade Feedback
    0 (0%)
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Ravenware View Post
    What is this?
    You can take any player model template, including Naga, Broken, Fel Orc etc, and then set the skin tone/facial features/hair style etc, and the armor it should wear and which weapons to equip. Using all this information (stored in the database) you can spawn a creature that looks like the details you have set, and thus have 'custom creatures', or 'fake players' depending on which route you go down.

  11. #11
    craigy109's Avatar Active Member
    Reputation
    72
    Join Date
    Feb 2009
    Posts
    79
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hi i just tried to work this all out
    please can someone help me sorry for the big bump...
    error log for world...
    Build Log Build started: Project: world, Configuration: Release|Win32 Com - Pastebin.com
    what i want help with is how to fix the errors

  12. #12
    Stige's Avatar Contributor
    Reputation
    115
    Join Date
    May 2009
    Posts
    1,325
    Thanks G/R
    7/13
    Trade Feedback
    1 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My eyes hurt so much trying to read that O_O

    Maybe you should make sure your post is readable on other themes aswell :l
    Super Unicum

  13. #13
    craigy109's Avatar Active Member
    Reputation
    72
    Join Date
    Feb 2009
    Posts
    79
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i think its like this coz it was made on an older theme a while ago
    "hi i just tried to work this all out
    please can someone help me sorry for the big bump...
    error log for world...Build Log Build started: Project: world, Configuration: Release|Win32 Com - Pastebin.com
    what i want help with is how to fix the errors"

  14. #14
    Sprigg's Avatar Sergeant
    Reputation
    6
    Join Date
    Jun 2011
    Posts
    37
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hard to read. But this is really really excellent job.

    I just can't deny it.
    +rep

Similar Threads

  1. Brand New Trinity Core Server + Project needs developers
    By Overdestined in forum WoW EMU Questions & Requests
    Replies: 6
    Last Post: 08-14-2010, 01:16 AM
  2. [Server/SQL] Character Transfer
    By SuicideBunny in forum WoW EMU Questions & Requests
    Replies: 5
    Last Post: 05-11-2010, 12:08 PM
  3. Playing Character Switching Factions
    By yellowd in forum World of Warcraft General
    Replies: 0
    Last Post: 07-31-2009, 02:35 AM
  4. Error when trying to start private server play.
    By abaraikenshi in forum World of Warcraft Emulator Servers
    Replies: 3
    Last Post: 05-18-2008, 02:28 PM
All times are GMT -5. The time now is 09:03 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search