Skip to content

Instantly share code, notes, and snippets.

@walkline
Created June 4, 2012 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save walkline/2869521 to your computer and use it in GitHub Desktop.
Save walkline/2869521 to your computer and use it in GitHub Desktop.
Transmogrification
From 64c327d1393abaced5445b855cfb74ac639d32e3 Mon Sep 17 00:00:00 2001
From: walkline <walkline.ua@gmail.com>
Date: Mon, 4 Jun 2012 19:49:20 +0300
Subject: [PATCH] Imlemented Transmogrification.
diff --git a/sql/updates/fc_updates_characters/fake_items.sql b/sql/updates/fc_updates_characters/fake_items.sql
new file mode 100644
index 0000000..3618ac1
--- /dev/null
+++ b/sql/updates/fc_updates_characters/fake_items.sql
@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `fake_items`;
+CREATE TABLE `fake_items` (
+ `guid` int(11) NOT NULL,
+ `fakeEntry` int(11) NOT NULL,
+ PRIMARY KEY (`guid`)
+);
+
+INSERT INTO `gossip_menu` VALUES (51000, 51000);
+INSERT INTO npc_text (ID, text0_0, em0_1) VALUES
+(51000, 'Put in the first slot of bag item, that you want to transmogrify. In the second slot, put item with perfect display.', 0);
+
diff --git a/sql/updates/fc_updates_world/fake_items.sql b/sql/updates/fc_updates_world/fake_items.sql
new file mode 100644
index 0000000..7cfd4cc
--- /dev/null
+++ b/sql/updates/fc_updates_world/fake_items.sql
@@ -0,0 +1,3 @@
+DELETE FROM creature_template WHERE entry = '190001';
+INSERT INTO creature_template (entry, modelid1, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, Health_mod, Mana_mod, Armor_mod, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, dmg_multiplier, unit_class, unit_flags, type, type_flags, InhabitType, RegenHealth, flags_extra, ScriptName) VALUES
+('190001', '15998', "Transmogrify Master", "", 'Speak', '50000', 71, 71, 1.56, 1.56, 1.56, 35, 35, 3, 1, 1.14286, 1.25, 1, 1, 1, 2, 7, 138936390, 3, 1, 2, 'npc_transmogrify');
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 23a3f50..6521f93 100755
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -251,6 +251,8 @@ Item::Item()
m_refundRecipient = 0;
m_paidMoney = 0;
m_paidExtendedCost = 0;
+
+ m_fakeDisplayEntry = 0;
}
bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
@@ -468,6 +470,9 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr
SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, fields[9].GetUInt32());
SetText(fields[10].GetString());
+ if (QueryResult result = CharacterDatabase.PQuery("SELECT fakeEntry FROM fake_items WHERE guid = %u", guid))
+ SetFakeDisplay((*result)[0].GetUInt32());
+
if (need_save) // normal item changed state set not work at loading
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD);
@@ -491,6 +496,7 @@ void Item::DeleteFromDB(SQLTransaction& trans, uint32 itemGuid)
void Item::DeleteFromDB(SQLTransaction& trans)
{
+ RemoveFakeDisplay();
DeleteFromDB(trans, GetGUIDLow());
}
@@ -1207,3 +1213,48 @@ bool Item::CheckSoulboundTradeExpire()
return false;
}
+
+FakeResult Item::SetFakeDisplay(uint32 iEntry)
+{
+ if (!iEntry)
+ {
+ RemoveFakeDisplay();
+ return FAKE_ERR_OK;
+ }
+
+ ItemTemplate const* myTmpl = GetTemplate();
+ ItemTemplate const* otherTmpl = sObjectMgr->GetItemTemplate(iEntry);
+
+ if (!otherTmpl)
+ return FAKE_ERR_CANT_FIND_ITEM;
+
+ if (myTmpl->InventoryType != otherTmpl->InventoryType)
+ return FAKE_ERR_DIFF_SLOTS;
+
+ if (myTmpl->AllowableClass != otherTmpl->AllowableClass)
+ return FAKE_ERR_DIFF_CLASS;
+
+ if (myTmpl->AllowableRace != otherTmpl->AllowableRace)
+ return FAKE_ERR_DIFF_RACE;
+
+ if (otherTmpl->Quality == ITEM_QUALITY_LEGENDARY || otherTmpl->Quality == ITEM_QUALITY_POOR)
+ return FAKE_ERR_WRONG_QUALITY;
+
+ if (m_fakeDisplayEntry != iEntry)
+ {
+ (!m_fakeDisplayEntry) ? CharacterDatabase.PExecute("INSERT INTO fake_items VALUES (%u, %u)", GetGUIDLow(), iEntry) :
+ CharacterDatabase.PExecute("UPDATE fake_items SET fakeEntry = %u WHERE guid = %u", iEntry, GetGUIDLow());
+ m_fakeDisplayEntry = iEntry;
+ }
+
+ return FAKE_ERR_OK;
+}
+
+void Item::RemoveFakeDisplay()
+{
+ if (GetFakeDisplayEntry())
+ {
+ m_fakeDisplayEntry = 0;
+ CharacterDatabase.PExecute("DELETE FROM fake_items WHERE guid = %u", GetGUIDLow());
+ }
+}
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 1d5fcae..32f1ef6 100755
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -152,6 +152,17 @@ enum SellResult
SELL_ERR_ONLY_EMPTY_BAG = 6 // can only do with empty bags
};
+enum FakeResult
+{
+ FAKE_ERR_CANT_FIND_OWNER,
+ FAKE_ERR_CANT_FIND_ITEM,
+ FAKE_ERR_WRONG_QUALITY,
+ FAKE_ERR_DIFF_SLOTS,
+ FAKE_ERR_DIFF_CLASS,
+ FAKE_ERR_DIFF_RACE,
+ FAKE_ERR_OK
+};
+
// -1 from client enchantment slot number
enum EnchantmentSlot
{
@@ -340,6 +351,10 @@ class Item : public Object
void BuildUpdate(UpdateDataMapType&);
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
+
+ FakeResult SetFakeDisplay(uint32 iEntry);
+ uint32 GetFakeDisplayEntry() { return m_fakeDisplayEntry; }
+ void RemoveFakeDisplay();
private:
std::string m_text;
uint8 m_slot;
@@ -352,5 +367,7 @@ class Item : public Object
uint32 m_paidMoney;
uint32 m_paidExtendedCost;
AllowedLooterSet allowedGUIDs;
+
+ uint32 m_fakeDisplayEntry;
};
#endif
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index dd35dea..fc8e4d0 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -12719,7 +12719,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem)
{
if (pItem)
{
- SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetEntry());
+ SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), (pItem->GetFakeDisplayEntry()) ? pItem->GetFakeDisplayEntry() : pItem->GetEntry());
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0, pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 1, pItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT));
}
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index e5833c5..fa6a6c9 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -38,6 +38,8 @@ void AddSC_ArgentTournament();
void AddSC_dalaran_squirrel();
// Arena Spectator
void AddSC_arena_spectator_script();
+// Transmogrify
+void AddSC_transmogrify_script();
// spells
void AddSC_deathknight_spell_scripts();
@@ -1271,5 +1273,6 @@ void AddCustomScripts()
AddSC_ArgentTournament();
AddSC_dalaran_squirrel();
AddSC_arena_spectator_script();
+ AddSC_transmogrify_script();
#endif
}
diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt
index 24477b0..c5dde7b 100644
--- a/src/server/scripts/Custom/CMakeLists.txt
+++ b/src/server/scripts/Custom/CMakeLists.txt
@@ -15,6 +15,7 @@ set(scripts_STAT_SRCS
Custom/argent_tournament.cpp
Custom/dalaran_squirrel.cpp
Custom/arena_spectator.cpp
+ Custom/npc_transmogrify.cpp
)
message(" -> Prepared: Custom")
diff --git a/src/server/scripts/Custom/npc_transmogrify.cpp b/src/server/scripts/Custom/npc_transmogrify.cpp
new file mode 100644
index 0000000..94c98be
--- /dev/null
+++ b/src/server/scripts/Custom/npc_transmogrify.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* ScriptData
+Name: Transmogrify Npc
+%Complete: 100
+Category: Custom Script
+EndScriptData */
+
+#include "ScriptPCH.h"
+
+enum TransmogrifyActions {
+ ACTION_TRANSMOGRIFY_ADD_DISPLAY,
+ ACTION_TRANSMOGRIFY_REMOVE_DISPLAY
+};
+
+const uint16 PriceInGold = 1000; // 1k golds
+
+class npc_transmogrify : public CreatureScript
+{
+ public:
+ npc_transmogrify() : CreatureScript("npc_transmogrify") { }
+
+ bool OnGossipHello(Player* pPlayer, Creature* pCreature)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "Make exchange!", GOSSIP_SENDER_MAIN, ACTION_TRANSMOGRIFY_ADD_DISPLAY);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "Make item clean.", GOSSIP_SENDER_MAIN, ACTION_TRANSMOGRIFY_REMOVE_DISPLAY);
+ pPlayer->SEND_GOSSIP_MENU(51000, pCreature->GetGUID());
+ return true;
+ }
+
+ bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
+ {
+ player->PlayerTalkClass->SendCloseGossip();
+ switch (action)
+ {
+ case ACTION_TRANSMOGRIFY_ADD_DISPLAY:
+ TransmogrifyItem(player, creature);
+ break;
+ case ACTION_TRANSMOGRIFY_REMOVE_DISPLAY:
+ ClearItem(player, creature);
+ break;
+ }
+ return true;
+ }
+
+ void TransmogrifyItem(Player* player, Creature* creature)
+ {
+ ChatHandler handler(player);
+ Item *trItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, INVENTORY_SLOT_ITEM_START);
+ Item *displayItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, INVENTORY_SLOT_ITEM_START + 1);
+ if (!trItem || !displayItem)
+ {
+ handler.PSendSysMessage("Put item in the first and second slot!");
+ return;
+ }
+
+ if (player->GetMoney() < PriceInGold * 100 * 100)
+ {
+ handler.PSendSysMessage("It costs %u gold!", PriceInGold);
+ return;
+ }
+
+ uint8 result = trItem->SetFakeDisplay(displayItem->GetTemplate()->ItemId);
+ switch (result)
+ {
+ case FAKE_ERR_CANT_FIND_ITEM:
+ handler.PSendSysMessage("Cant find item!");
+ break;
+ case FAKE_ERR_WRONG_QUALITY:
+ handler.PSendSysMessage("Item has wrong quality!");
+ break;
+ case FAKE_ERR_DIFF_SLOTS:
+ handler.PSendSysMessage("Items has different types!");
+ break;
+ case FAKE_ERR_DIFF_CLASS:
+ case FAKE_ERR_DIFF_RACE:
+ handler.PSendSysMessage("Items require different options!");
+ break;
+ case FAKE_ERR_OK:
+ {
+ WorldPacket data;
+ data << uint8(INVENTORY_SLOT_BAG_0);
+ data << uint8(trItem->GetSlot());
+ player->GetSession()->HandleAutoEquipItemOpcode(data);
+
+ player->ModifyMoney(-1 * PriceInGold * 100 * 100);
+ creature->GetAI()->DoCast(63491);
+
+ break;
+ }
+ }
+ }
+
+ void ClearItem(Player *player, Creature* creature)
+ {
+ ChatHandler handler(player);
+ Item *trItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, INVENTORY_SLOT_ITEM_START);
+ if (!trItem)
+ {
+ handler.PSendSysMessage("Put item in the first slot!");
+ return;
+ }
+
+ trItem->RemoveFakeDisplay();
+
+ WorldPacket data;
+ data << uint8(INVENTORY_SLOT_BAG_0);
+ data << uint8(trItem->GetSlot());
+ player->GetSession()->HandleAutoEquipItemOpcode(data);
+
+ creature->GetAI()->DoCast(63491);
+ }
+};
+
+void AddSC_transmogrify_script()
+{
+ new npc_transmogrify;
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment