[REQ] Reforging

So, I’ve been trying to update a Custom script for Reforging without much success; any help would be appreciated.

I’m stuck in Objectmgr.h

Here’s what I have so far…

Reforging.cpp

[SPOILER]#include “ScriptPCH.h”
struct accepted_stat_format {uint32 stat_type; char* stat_name; int32 base_stat_change; };

// ########################################################################################
// Reforging config
// ########################################################################################
static const uint32 tokenEntry = 65717; // token entry
static const uint8 maxTokenAmount = 3; // max token cost (multiplies the max stat amount also)
static const uint8 maxReforges = 3; // maximum reforges for one item
static const bool send_cache_packets = true; // change player cache?

static const accepted_stat_format accepted_stat_types[] =
{
// See ItemPrototype.h for ItemModType definitions. You can add more rows for more stats.
{ITEM_MOD_HEALTH, “Health”, 7500},
{ITEM_MOD_STRENGTH, “Strength”, 900},
{ITEM_MOD_INTELLECT, “Intellect”, 900},
{ITEM_MOD_AGILITY, “Agility”, 300},
{ITEM_MOD_SPIRIT, “Spirit”, 1250},
{ITEM_MOD_STAMINA, “Stamina”, 1000},
{ITEM_MOD_ATTACK_POWER, “Attack power”, 1250},
{ITEM_MOD_SPELL_POWER, “Spell power”, 1000},
};

// ########################################################################################

static const uint32 accepted_stat_types_max = sizeof(accepted_stat_types) / sizeof(accepted_stat_format);
struct playerItems_format {uint32 Entry, lowGUID;};
static UNORDERED_MAP<uint32, std::vector<playerItems_format> > playerItems;

static const void SendReforgePackets(Player* player)
{
if(!send_cache_packets)
return;

uint32 pGUID = player->GetGUIDLow();
if(playerItems.find(pGUID) == playerItems.end())
    return;

for (std::vector<playerItems_format>::iterator it = playerItems[pGUID].begin(); it != playerItems[pGUID].end(); it++)
{
    // See how enchanthing is done
    // Update player cache (self only) pure visual.
    // HandleItemQuerySingleOpcode copy paste:
    const ItemTemplate* proto = sObjectMgr->GetItemTemplate(it->Entry);
    std::string Name        = proto->Name1;
    std::string Description = proto->Description;
    int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
    if (loc_idx >= 0)
    {
        if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId))
        {
            ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
            ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
        }
    }
    WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
    data << proto->ItemId;
    data << proto->Class;
    data << proto->SubClass;
    data << int32(proto->SoundOverrideSubclass);
    data << Name;
    data << uint8(0x00);
    data << uint8(0x00);
    data << uint8(0x00);
    data << proto->DisplayInfoID;
    data << proto->Quality;
    data << proto->Flags;
    data << proto->Flags2;
    data << proto->BuyPrice;
    data << proto->SellPrice;
    data << proto->InventoryType;
    data << proto->AllowableClass;
    data << proto->AllowableRace;
    data << proto->ItemLevel;
    data << proto->RequiredLevel;
    data << proto->RequiredSkill;
    data << proto->RequiredSkillRank;
    data << proto->RequiredSpell;
    data << proto->RequiredHonorRank;
    data << proto->RequiredCityRank;
    data << proto->RequiredReputationFaction;
    data << proto->RequiredReputationRank;
    data << int32(proto->MaxCount);
    data << int32(proto->Stackable);
    data << proto->ContainerSlots;
    data << proto->StatsCount;
    for (uint32 i = 0; i < proto->StatsCount; ++i)
    {
        data << proto->ItemStat[i].ItemStatType;
        if(sObjectMgr->_itemFakeStatStore[it->lowGUID].find(i) != sObjectMgr->_itemFakeStatStore[it->lowGUID].end())
            data << proto->ItemStat[i].ItemStatValue + sObjectMgr->_itemFakeStatStore[it->lowGUID][i];
        else
            data << proto->ItemStat[i].ItemStatValue;
    }
    data << proto->ScalingStatDistribution;
    data << proto->ScalingStatValue;
    for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
    {
        data << proto->Damage[i].DamageMin;
        data << proto->Damage[i].DamageMax;
        data << proto->Damage[i].DamageType;
    }
    data << proto->Armor;
    data << proto->HolyRes;
    data << proto->FireRes;
    data << proto->NatureRes;
    data << proto->FrostRes;
    data << proto->ShadowRes;
    data << proto->ArcaneRes;
    data << proto->Delay;
    data << proto->AmmoType;
    data << proto->RangedModRange;
    for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
    {
        SpellInfo const* spell = sSpellMgr->GetSpellInfo(proto->Spells[s].SpellId);
        if (spell)
        {
            bool db_data = proto->Spells[s].SpellCooldown >= 0 || proto->Spells[s].SpellCategoryCooldown >= 0;
            data << proto->Spells[s].SpellId;
            data << proto->Spells[s].SpellTrigger;
            data << uint32(-abs(proto->Spells[s].SpellCharges));
            if (db_data)
            {
                data << uint32(proto->Spells[s].SpellCooldown);
                data << uint32(proto->Spells[s].SpellCategory);
                data << uint32(proto->Spells[s].SpellCategoryCooldown);
            }
            else
            {
                data << uint32(spell->RecoveryTime);
                data << uint32(spell->Category);
                data << uint32(spell->CategoryRecoveryTime);
            }
        }
        else
        {
            data << uint32(0);
            data << uint32(0);
            data << uint32(0);
            data << uint32(-1);
            data << uint32(0);
            data << uint32(-1);
        }
    }
    data << proto->Bonding;
    data << Description;
    data << proto->PageText;
    data << proto->LanguageID;
    data << proto->PageMaterial;
    data << proto->StartQuest;
    data << proto->LockID;
    data << int32(proto->Material);
    data << proto->Sheath;
    data << proto->RandomProperty;
    data << proto->RandomSuffix;
    data << proto->Block;
    data << proto->ItemSet;
    data << proto->MaxDurability;
    data << proto->Area;
    data << proto->Map;
    data << proto->BagFamily;
    data << proto->TotemCategory;
    for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
    {
        data << proto->Socket[s].Color;
        data << proto->Socket[s].Content;
    }
    data << proto->socketBonus;
    data << proto->GemProperties;
    data << proto->RequiredDisenchantSkill;
    data << proto->ArmorDamageModifier;
    data << proto->Duration;
    data << proto->ItemLimitCategory;
    data << proto->HolidayId;
    player->GetSession()->SendPacket(&data);
}

}

class REFORGING_DATA_HANDLER : public PlayerScript
{
public:
REFORGING_DATA_HANDLER() : PlayerScript(“REFORGING_DATA_HANDLER”)
{
// DB cleanup on startup
CharacterDatabase.Execute(“DELETE FROM custom_reforges WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_reforges.iGUID)”);
}

// Called when a player logs out.
void OnLogout(Player* player)
{
    DeleteSavedReforges(player->GetGUIDLow()); // delete stored reforges from the player (not DB)
}

void OnLogin(Player* player)
{
    uint32 pGUID = player->GetGUIDLow();

    DeleteSavedReforges(pGUID); // delete saved reforges from the player before loading them
    QueryResult result = CharacterDatabase.PQuery("SELECT `iGUID`, `stat_count_id`, `stat_diff`, `Entry` FROM `custom_reforges` WHERE pGUID = %u and EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_reforges.iGUID)", pGUID);
    if (result)
    {
        UNORDERED_MAP<uint32, std::map<uint32, int32> > stat_temp_container; // iGUID <stat_count, stat_diff>
        std::set<uint32> sent_error_message;
        do
        {
            uint32 lowGUID = (*result)[0].GetUInt32();
            if(sObjectMgr->_itemFakeStatStore.find(lowGUID) != sObjectMgr->_itemFakeStatStore.end() && sObjectMgr->_itemFakeStatStore[lowGUID].size() >= maxReforges)
            {
                if(sent_error_message.find(lowGUID) != sent_error_message.end())
                    continue;
                sLog->outErrorDb("Too many reforges for item lowGUID %u, ignoring extra reforges.", lowGUID);
                sent_error_message.insert(lowGUID);
            }
            else
            {
                stat_temp_container[lowGUID][(*result)[1].GetUInt32()] = (*result)[2].GetInt32();
                playerItems_format temp = {(*result)[3].GetUInt32(), lowGUID}; // temp var so we can insert our stuff
                playerItems[pGUID].push_back(temp);
            }
        } while (result->NextRow());

        // apply stat changes for all reforged items equipped and save them to container
        for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
        {
            if(Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
            {
                uint32 invGUID = invItem->GetGUIDLow();
                if(stat_temp_container.find(invGUID) != stat_temp_container.end())
                {
                    player->_ApplyItemMods(invItem, slot, false);
                    for(std::map<uint32, int32>::iterator stat_count_id = stat_temp_container[invGUID].begin(); stat_count_id != stat_temp_container[invGUID].end(); stat_count_id++)
                    {
                        sObjectMgr->_itemFakeStatStore[invGUID][stat_count_id->first] = stat_count_id->second;
                    }
                    player->_ApplyItemMods(invItem, slot, true);
                    stat_temp_container.erase(invGUID); // saved reforges for this item, delete from temp
                }
            }
        }

        // save the rest of the player's reforges to the container if more exist
        if(!stat_temp_container.empty())
        {
            for(UNORDERED_MAP<uint32, std::map<uint32, int32> >::iterator iGUID = stat_temp_container.begin(); iGUID != stat_temp_container.end(); iGUID++)
            {
                for(std::map<uint32, int32>::iterator stat_count_id = iGUID->second.begin(); stat_count_id != iGUID->second.end(); stat_count_id++)
                {
                    sObjectMgr->_itemFakeStatStore[iGUID->first][stat_count_id->first] = stat_count_id->second;
                }
            }
        }
    }

    SendReforgePackets(player);
}

private:

void DeleteSavedReforges(uint32 pGUID)
{
    if(playerItems.find(pGUID) == playerItems.end())
        return; // Already empty!
    for (std::vector<playerItems_format>::iterator it = playerItems[pGUID].begin(); it != playerItems[pGUID].end(); it++)
    {
        if(sObjectMgr->_itemFakeStatStore.find(it->lowGUID) != sObjectMgr->_itemFakeStatStore.end())
            sObjectMgr->_itemFakeStatStore.erase(it->lowGUID);
    }
    playerItems.erase(pGUID);
}

};

class REFORGER_NPC : public CreatureScript
{
public:
REFORGER_NPC() : CreatureScript(“REFORGER_NPC”)
{
for(uint32 i = 0; i < accepted_stat_types_max; i++)
{
stat_format temp = {accepted_stat_types[i].stat_name, accepted_stat_types[i].base_stat_change};
stat_types[accepted_stat_types[i].stat_type] = temp;
}
}

bool OnGossipHello(Player* player, Creature* creature)
{
    if(selectedItem.find(player->GetGUIDLow()) != selectedItem.end())
        selectedItem.erase(player->GetGUIDLow());

    player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Buy Reforge Tokens.", VENDOR, 0);
    player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select equipped item in slot:", MAIN_MENU, 0);
    for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
    {
        if(Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
            if(IsReforgable(invItem, player))
                if(char* slotname = GetSlotName(slot, player->GetSession()))
                    player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, slotname, SELECT_STAT_INCREASE, slot);
    }
    player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Update menu", MAIN_MENU, 0);
    player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
    return true;
}

bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action)
{
    player->PlayerTalkClass->ClearMenus();
    switch(sender)
    {
    case VENDOR: 
        player->GetSession()->SendListInventory(creature->GetGUID());
        break;
    case MAIN_MENU: OnGossipHello(player, creature); break;
    case SELECT_STAT_INCREASE:
        // action = slot
        if (Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action))
        {
            if(IsReforgable(invItem, player))
            {
                selectedItem[player->GetGUIDLow()] = invItem;
                const ItemTemplate* proto = invItem->GetTemplate();
                char label[250];

                snprintf(label, 250, "Selected item:n%s", invItem->GetTemplate()->Name1.c_str());
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select stat to increase:", sender, action);
                bool hasfakestats = ((sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end()) ? true : false);
                for (uint32 i = 0; i < proto->StatsCount; ++i)
                {
                    if(hasfakestats && sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].find(i) != sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].end())
                        continue; // already modded this stat, skip.
                    if(char* stat_name = GetStatName(proto->ItemStat[i].ItemStatType))
                        player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, stat_name, SELECT_TOKEN_COST, i);
                }
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", MAIN_MENU, 0);
                player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
            }
            else
            {
                player->GetSession()->SendNotification("Item not reforgable");
                OnGossipHello(player, creature);
            }
        }
        else
        {
            player->GetSession()->SendNotification("No item selected");
            OnGossipHello(player, creature);
        }
        break;
    case SELECT_TOKEN_COST:
        // action = stat_count_id
        {
            Item* invItem = selectedItem[player->GetGUIDLow()];
            if (invItem && invItem->IsInWorld() && IsReforgable(invItem, player))
            {
                const ItemTemplate* proto = invItem->GetTemplate();
                char label[250];
                char popup[250];

                snprintf(label, 250, "Selected item:n%s", invItem->GetTemplate()->Name1.c_str());
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
                snprintf(label, 250, "Selected stat: %s", stat_types[proto->ItemStat[action].ItemStatType].stat_name);
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, label, sender, action);
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select amount to increase:", sender, action);
                for (uint32 i = 1; i <= maxTokenAmount; ++i)
                {
                    snprintf(label, 250, "Increase by %i for %u x %s", stat_types[proto->ItemStat[action].ItemStatType].stat_base_value*i, i, GetItemName(tokenEntry, player->GetSession()).c_str());
                    snprintf(popup, 250, "Are you sure?nThe item is set untradeable and non-refundablennCosts %u x %s", i, GetItemName(tokenEntry, player->GetSession()).c_str());
                    player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_TRAINER, label, i, action, popup, 0, false); // sender = token_count, action = stat_count_id
                }
                player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", SELECT_STAT_INCREASE, invItem->GetSlot());
                player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
            }
            else
            {
                player->GetSession()->SendNotification("Invalid item selected");
                OnGossipHello(player, creature);
            }
        }
        break;
    default: // Reforge
        // sender = token_count, action = stat_count_id
        {
            Item* invItem = selectedItem[player->GetGUIDLow()];
            if (invItem && invItem->IsInWorld() && IsReforgable(invItem, player))
            {
                if(sender && sender <= maxTokenAmount)
                {
                    if(player->HasItemCount(tokenEntry, sender))
                    {
                        player->DestroyItemCount(tokenEntry, sender, true);
                        UpdatePlayerReforgeStats(invItem, player, action, sender);
                    }
                    else
                    {
                        player->GetSession()->SendNotification("Not enough tokens");
                        OnGossipSelect(player, creature, SELECT_TOKEN_COST, action);
                        return true;
                    }
                }
                else
                    player->GetSession()->SendNotification("Invalid token count");
            }
            else
                player->GetSession()->SendNotification("Invalid item selected");
            OnGossipHello(player, creature);
        }
    }
    return true;
}

private:

enum Senders
{
    MAIN_MENU = GOSSIP_ACTION_INFO_DEF+1,
    SELECT_ITEM,
    SELECT_STAT_INCREASE,
    SELECT_TOKEN_COST,
 VENDOR = GOSSIP_ACTION_INFO_DEF+2,
    REFORGE,
};

struct stat_format {char* stat_name; int32 stat_base_value; };
UNORDERED_MAP<uint32, struct stat_format> stat_types;
UNORDERED_MAP<uint32, Item*> selectedItem;

char* GetStatName(uint32 stat_type)
{
    if(stat_types.find(stat_type) != stat_types.end())
        return stat_types[stat_type].stat_name;
    return NULL;
}

char * GetSlotName(uint8 slot, WorldSession* session)
{
    switch (slot)
    {
    case EQUIPMENT_SLOT_HEAD      : return "Head";
    case EQUIPMENT_SLOT_NECK      : return "Neck";
    case EQUIPMENT_SLOT_SHOULDERS : return "Shoulders";
    case EQUIPMENT_SLOT_BODY      : return "Shirt";
    case EQUIPMENT_SLOT_CHEST     : return "Chest";
    case EQUIPMENT_SLOT_WAIST     : return "Waist";
    case EQUIPMENT_SLOT_LEGS      : return "Legs";
    case EQUIPMENT_SLOT_FEET      : return "Feet";
    case EQUIPMENT_SLOT_WRISTS    : return "Wrists";
    case EQUIPMENT_SLOT_HANDS     : return "Hands";
    case EQUIPMENT_SLOT_FINGER1   : return "Right finger";
    case EQUIPMENT_SLOT_FINGER2   : return "left finger";
    case EQUIPMENT_SLOT_TRINKET1  : return "Right trinket";
    case EQUIPMENT_SLOT_TRINKET2  : return "Left trinket";
    case EQUIPMENT_SLOT_BACK      : return "Back";
    case EQUIPMENT_SLOT_MAINHAND  : return "Main hand";
    case EQUIPMENT_SLOT_OFFHAND   : return "Off hand";
    case EQUIPMENT_SLOT_RANGED    : return "Ranged";
    case EQUIPMENT_SLOT_TABARD    : return "Tabard";
    default: return NULL;
    }
}

std::string GetItemName(uint32 entry, WorldSession* session)
{
    const ItemTemplate* itemTemplate = sObjectMgr->GetItemTemplate(entry);
    std::string name = itemTemplate->Name1;
    int loc_idx = session->GetSessionDbLocaleIndex();
    if (loc_idx >= 0)
        if (ItemLocale const* il = sObjectMgr->GetItemLocale(itemTemplate->ItemId))
            sObjectMgr->GetLocaleString(il->Name, loc_idx, name);
    return name;
}

bool IsReforgable(Item* invItem, Player* player)
{
    if(invItem->IsEquipped() && invItem->GetOwnerGUID() == player->GetGUID())
    {
        if(sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
            if(sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].size() >= maxReforges)
                return false;
        const ItemTemplate* proto = invItem->GetTemplate();
        // block heirlooms necessary? probably. (their stats are handled differently)
        if(proto->Quality != ITEM_QUALITY_HEIRLOOM && proto->StatsCount > 0)
        {
            for (uint32 i = 0; i < proto->StatsCount; ++i)
            {
                if(stat_types.find(proto->ItemStat[i].ItemStatType) == stat_types.end())
                    continue;
                if(proto->ItemStat[i].ItemStatValue == 0)
                    continue;
                if(sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
                {
                    if(sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].find(i) == sObjectMgr->_itemFakeStatStore[invItem->GetGUIDLow()].end())
                        return true; // found a stat that is not increased yet and is accepted by the script
                }
                else
                    return true; // the item is not reforged yet and a good stat was found
            }
        }
    }
    return false;
}

void UpdatePlayerReforgeStats(Item* invItem, Player* player, uint32 stat_count_id, uint32 token_count)
{
    const ItemTemplate* proto = invItem->GetTemplate();
    uint32 stat_diff = stat_types[proto->ItemStat[stat_count_id].ItemStatType].stat_base_value * token_count;
    uint32 guidlow = invItem->GetGUIDLow();

    // non tradeable and refundable
    invItem->SetNotRefundable(player);
    invItem->SetBinding(true);

    // Update player stats
    player->_ApplyItemMods(invItem, invItem->GetSlot(), false);
    sObjectMgr->_itemFakeStatStore[guidlow][stat_count_id] = stat_diff; // save to container for item stats applying (used a lot)
    playerItems_format temp = {invItem->GetEntry(), guidlow};           // temp var so we can insert our stuff to playerItems_format
    playerItems[player->GetGUIDLow()].push_back(temp);                  // save entry and guid of the item so we can delete the item data on logout
    player->_ApplyItemMods(invItem, invItem->GetSlot(), true);

    // save to DB
    player->SaveToDB(); // save player to DB too, since if a crash comes by, he will get a free reforge and no token removing is saved.
    CharacterDatabase.PExecute("REPLACE INTO `custom_reforges` (`pGUID`, `Entry`, `iGUID`, `stat_count_id`, `stat_diff`) VALUES (%u, %u, %u, %u, %i)", player->GetGUIDLow(), invItem->GetEntry(), guidlow, stat_count_id, stat_diff);

    SendReforgePackets(player);
}

};

void AddSC_REFORGER_NPC()
{
new REFORGER_NPC;
new REFORGING_DATA_HANDLER;
}
And I added in objectmgr.h Around 1190

static void AddLocaleString(const std::string& s, LocaleConstant locale, StringVector& data);
static inline void GetLocaleString(const StringVector& data, int loc_idx, std::string& value)
{
if (data.size() > size_t(loc_idx) && !data[loc_idx].empty())
value = data[loc_idx];
}

    CharacterConversionMap FactionChange_Achievements;
    CharacterConversionMap FactionChange_Items;
    CharacterConversionMap FactionChange_Spells;
    CharacterConversionMap FactionChange_Reputation;

    void LoadFactionChangeAchievements();
    void LoadFactionChangeItems();
    void LoadFactionChangeSpells();
    void LoadFactionChangeReputations();
	
ItemFakeStatContainer _itemFakeStatStore; // Custom: Reforging Test

private:
    // first free id for selected id type
    uint32 _auctionId;
    uint64 _equipmentSetGuid;
    uint32 _itemTextId;
    uint32 _mailId;
    uint32 _hiPetNumber;[/SPOILER]

So, that’s about as far as I got… I didn’t write the script, so I’m not sure where to go from here…

Reforging is workin’ bro. At least on the 4.3.4 branch.

I am sure he is trying to implement it as 3.3.5a custom feature /emoticons/default_smile.png

I know…

Yes, not successfully as of yet, but yes this ^

He didn’t steal any credit, he said he didn’t write it, he just didn’t give proper credit, probably because he didn’t know who wrote it, also, no illegal public server names…

Ok, I dont get it.

This script is mine and I have not shared it with anyone, except one.

I guess he shared it forward … hmm? (then its ok)

Its not blizzlike btw.

I was going to make a more blizzlike one, but didnt have the motivation or time.

As I dont now.

I got the full diff for it.

No I didn’t kow who made it. Only the reforge.cpp was given to me.

I was just trying to get it working correctly, not trying to start anything with anyone. That’s why I posted everything I had clearly for anyone who wanted to work on it.

Was NOT trying to claim it as my work, and had I know it would upset people to post it, I would have continued to quietly work on it on my own. Honestly, I thought that was what this section was for.

Since I know now this was your script, Rochet2, if you don’t want it posted here, I"ll happily take it down.

Nah, its fine, as long as the other party agrees with it.

But I still have the diff, so if you want it … hmh

Yes, I’m sure the diff would be very helpful towards updating it to a more recent build of trinity.