Created
May 19, 2013 10:47
-
-
Save SymbolixDEV/5607332 to your computer and use it in GitHub Desktop.
Transmogrification 2.4.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/sql/transmogrification/characters_transmogrification.sql b/sql/transmogrification/characters_transmogrification.sql | |
new file mode 100644 | |
index 0000000..8a73e1b | |
--- /dev/null | |
+++ b/sql/transmogrification/characters_transmogrification.sql | |
@@ -0,0 +1,6 @@ | |
+-- BlizzLikeCore Transmogrification | |
+CREATE TABLE IF NOT EXISTS `custom_transmogrification` ( | |
+ `GUID` int(10) unsigned NOT NULL DEFAULT '0', | |
+ `FakeEntry` int(10) unsigned NOT NULL DEFAULT '0', | |
+ PRIMARY KEY (`GUID`) | |
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='version 1.0'; | |
\ No newline at end of file | |
diff --git a/sql/transmogrification/world_transmogrification.sql b/sql/transmogrification/world_transmogrification.sql | |
new file mode 100644 | |
index 0000000..1d16daf | |
--- /dev/null | |
+++ b/sql/transmogrification/world_transmogrification.sql | |
@@ -0,0 +1,34 @@ | |
+-- BlizzLikeCore Transmogrification | |
+DELETE FROM `creature_template` WHERE `entry` = 91011; | |
+INSERT INTO `creature_template` (`entry`, `heroic_entry`, `modelid_A`, `modelid_A2`, `modelid_H`, `modelid_H2`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `minhealth`, `maxhealth`, `minmana`, `maxmana`, `armor`, `faction_A`, `faction_H`, `npcflag`, `speed`, `scale`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `baseattacktime`, `rangeattacktime`, `unit_flags`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `class`, `race`, `minrangedmg`, `maxrangedmg`, `rangedattackpower`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `PetSpellDataId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `RacialLeader`, `RegenHealth`, `equipment_id`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`) VALUES | |
+(91011, 0, 10216, 0, 10216, 0, 'Willy', 'Transmogrification', NULL, 0, 70, 70, 5000, 5000, 0, 0, 2865, 35, 35, 1, 1, 1, 1, 60, 165, 0, 97, 1500, 1500, 0, 0, 0, 0, 0, 0, 0, 50, 100, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 1, 1, 1, 1, 0, 0, 0, 'transmog'); | |
+DELETE FROM `blizzlike_string` WHERE `id` BETWEEN 11100 AND 11128; | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11100, 'Transmogrifications removed from equipped items', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11101, 'You have no transmogrified items equipped', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11102, '%s transmogrification removed', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11103, 'No transmogrification on %s slot', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11104, '%s transmogrified', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11105, 'Selected items are not suitable', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11106, 'Selected item does not exist', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11107, 'Equipment slot is empty', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11108, 'Head', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11109, 'Shoulders', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11110, 'Shirt', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11111, 'Chest', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11112, 'Waist', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11113, 'Legs', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11114, 'Feet', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11115, 'Wrists', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11116, 'Hands', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11117, 'Back', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11118, 'Main hand', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11119, 'Off hand', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11120, 'Ranged', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11121, 'Tabard', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11122, 'Back..', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11123, 'Remove all transmogrifications', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11124, 'Remove transmogrifications from all equipped items?', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11125, 'Update menu', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11126, 'Remove transmogrification', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11127, 'Remove transmogrification from %s?', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
+INSERT INTO `blizzlike_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (11128, 'Using this item for transmogrify will bind it to you and make it non-refundable and non-tradeable.\r\nDo you wish to continue?\r\n\r\n', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | |
\ No newline at end of file | |
diff --git a/src/game/Item.cpp b/src/game/Item.cpp | |
index 8487537..fb41653 100644 | |
--- a/src/game/Item.cpp | |
+++ b/src/game/Item.cpp | |
@@ -396,6 +396,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result | |
void Item::DeleteFromDB() | |
{ | |
+ DeleteFakeFromDB(GetGUIDLow()); // transmogrification | |
CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'",GetGUIDLow()); | |
} | |
@@ -906,3 +907,42 @@ void Item::BuildUpdate(UpdateDataMapType& data_map) | |
ClearUpdateMask(false); | |
} | |
+uint32 Item::GetFakeEntry() // transmogrification | |
+{ | |
+ItemFakeEntryContainer::const_iterator itr = objmgr._itemFakeEntryStore.find(GetGUIDLow()); | |
+ if (itr == objmgr._itemFakeEntryStore.end()) return NULL; | |
+ return itr->second; | |
+} | |
+ | |
+bool Item::DeleteFakeEntry() // transmogrification | |
+{ | |
+if (!GetFakeEntry()) | |
+ return false; | |
+ //GetOwner()->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_0 + (GetSlot() * MAX_VISIBLE_ITEM_OFFSET), GetEntry()); | |
+ GetOwner()->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_0 + (GetSlot() * 2), GetEntry()); | |
+ DeleteFakeFromDB(GetGUIDLow()); | |
+ return true; | |
+} | |
+ | |
+void Item::DeleteFakeFromDB(uint32 lowGUID) // custom | |
+{ | |
+ objmgr._itemFakeEntryStore.erase(lowGUID); | |
+ CharacterDatabase.PExecute("DELETE FROM custom_transmogrification WHERE GUID = %u", lowGUID); | |
+} | |
+ | |
+void Item::SetFakeEntry(uint32 entry) // custom | |
+{ | |
+ //GetOwner()->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_0 + (GetSlot() * MAX_VISIBLE_ITEM_OFFSET), Entry); | |
+ GetOwner()->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_0 + (GetSlot() * 2), entry); | |
+ objmgr._itemFakeEntryStore[GetGUIDLow()] = entry; | |
+ CharacterDatabase.PExecute("REPLACE INTO custom_transmogrification (GUID, FakeEntry) VALUES (%u, %u)", GetGUIDLow(), entry); | |
+} | |
+ | |
+bool Item::HasGoodFakeQuality() // custom | |
+{ | |
+ uint32 quality = GetProto()->Quality; | |
+ if (quality == ITEM_QUALITY_UNCOMMON || quality == ITEM_QUALITY_RARE || quality == ITEM_QUALITY_EPIC) | |
+ return true; | |
+ return false; | |
+} | |
+ | |
diff --git a/src/game/Item.h b/src/game/Item.h | |
index 4a4663a..51426c7 100644 | |
--- a/src/game/Item.h | |
+++ b/src/game/Item.h | |
@@ -277,6 +277,15 @@ class Item : public Object | |
bool hasInvolvedQuest(uint32 /*quest_id*/) const { return false; } | |
void BuildUpdate(UpdateDataMapType& ); | |
+ | |
+ // transmogrification | |
+ uint32 GetFakeEntry(); | |
+ bool DeleteFakeEntry(); | |
+ static void DeleteFakeFromDB(uint32 lowGUID); | |
+ void SetFakeEntry(uint32 entry); | |
+ bool HasGoodFakeQuality(); | |
+ Bag* ToBag() { if (IsBag()) return reinterpret_cast<Bag*>(this); else return NULL; } | |
+ const Bag* ToBag() const { if (IsBag()) return reinterpret_cast<const Bag*>(this); else return NULL; } | |
private: | |
uint8 m_slot; | |
diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h | |
index d61a62b..d620032 100644 | |
--- a/src/game/ItemPrototype.h | |
+++ b/src/game/ItemPrototype.h | |
@@ -550,6 +550,8 @@ struct ItemPrototype | |
} | |
}; | |
+typedef UNORDERED_MAP<uint32, uint32> ItemFakeEntryContainer; // transmogrification | |
+ | |
struct ItemLocale | |
{ | |
std::vector<std::string> Name; | |
diff --git a/src/game/Language.h b/src/game/Language.h | |
index 44bae6e..a7f3090 100644 | |
--- a/src/game/Language.h | |
+++ b/src/game/Language.h | |
@@ -907,6 +907,39 @@ enum BlizzLikeStrings | |
// Use for custom patches 11000-11999 | |
LANG_AUTO_BROADCAST = 11000, | |
LANG_INVALID_REALMID = 11001, | |
+ | |
+ //transmogrification | |
+ LANG_REM_TRANSMOGRIFICATIONS_ITEMS = 11100, | |
+ LANG_ERR_NO_TRANSMOGRIFICATIONS = 11101, | |
+ LANG_REM_TRANSMOGRIFICATION_ITEM = 11102, | |
+ LANG_ERR_NO_TRANSMOGRIFICATION = 11103, | |
+ LANG_ITEM_TRANSMOGRIFIED = 11104, | |
+ LANG_ERR_NO_ITEM_SUITABLE = 11105, | |
+ LANG_ERR_NO_ITEM_EXISTS = 11106, | |
+ LANG_ERR_EQUIP_SLOT_EMPTY = 11107, | |
+ | |
+ LANG_SLOT_NAME_HEAD = 11108, | |
+ LANG_SLOT_NAME_SHOULDERS = 11109, | |
+ LANG_SLOT_NAME_BODY = 11110, | |
+ LANG_SLOT_NAME_CHEST = 11111, | |
+ LANG_SLOT_NAME_WAIST = 11112, | |
+ LANG_SLOT_NAME_LEGS = 11113, | |
+ LANG_SLOT_NAME_FEET = 11114, | |
+ LANG_SLOT_NAME_WRISTS = 11115, | |
+ LANG_SLOT_NAME_HANDS = 11116, | |
+ LANG_SLOT_NAME_BACK = 11117, | |
+ LANG_SLOT_NAME_MAINHAND = 11118, | |
+ LANG_SLOT_NAME_OFFHAND = 11119, | |
+ LANG_SLOT_NAME_RANGED = 11120, | |
+ LANG_SLOT_NAME_TABARD = 11121, | |
+ | |
+ LANG_OPTION_BACK = 11122, | |
+ LANG_OPTION_REMOVE_ALL = 11123, | |
+ LANG_POPUP_REMOVE_ALL = 11124, | |
+ LANG_OPTION_UPDATE_MENU = 11125, | |
+ LANG_OPTION_REMOVE_ONE = 11126, | |
+ LANG_POPUP_REMOVE_ONE = 11127, | |
+ LANG_POPUP_TRANSMOGRIFY = 11128, | |
// ChatSpy | |
LANG_CHATSPY_APENDED = 11600, | |
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp | |
index 32cf143..4f42cb8 100644 | |
--- a/src/game/ObjectMgr.cpp | |
+++ b/src/game/ObjectMgr.cpp | |
@@ -1482,6 +1482,31 @@ uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const | |
return 0; | |
} | |
+void ObjectMgr::LoadTransmogrifications() //transmogrification | |
+{ | |
+ sLog.outString("Deleting non-existing transmogrification entries..."); | |
+ CharacterDatabase.Execute("DELETE FROM custom_transmogrification WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)"); | |
+ | |
+ uint32 oldMSTime = getMSTime(); | |
+ _itemFakeEntryStore.clear(); | |
+ QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT GUID, FakeEntry FROM custom_transmogrification WHERE EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)"); | |
+ if (result) | |
+ do | |
+ { | |
+ uint32 lowGUID = (*result)[0].GetUInt32(); | |
+ uint32 entry = (*result)[1].GetUInt32(); | |
+ if (GetItemPrototype(entry)) | |
+ _itemFakeEntryStore[lowGUID] = entry; | |
+ else | |
+ { | |
+ sLog.outErrorDb("Item entry (Entry: %u, GUID: %u) does not exist, deleting.", entry, lowGUID); | |
+ CharacterDatabase.PExecute("DELETE FROM custom_transmogrification WHERE GUID = %u", lowGUID); | |
+ } | |
+ } while (result->NextRow()); | |
+ //sLog.outString(">> Loaded %lu Item fake entries in %u ms", (unsigned long)_itemFakeEntryStore.size(), GetMSTimeDiffToNow(oldMSTime)); | |
+ sLog.outString(); | |
+} | |
+ | |
void ObjectMgr::LoadItemLocales() | |
{ | |
mItemLocaleMap.clear(); // need for reload case | |
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h | |
index a978dd9..94a980d 100644 | |
--- a/src/game/ObjectMgr.h | |
+++ b/src/game/ObjectMgr.h | |
@@ -515,6 +515,8 @@ class ObjectMgr | |
public: | |
ObjectMgr(); | |
~ObjectMgr(); | |
+ | |
+ ItemFakeEntryContainer _itemFakeEntryStore; | |
typedef UNORDERED_MAP<uint32, Item*> ItemMap; | |
@@ -741,6 +743,7 @@ class ObjectMgr | |
void LoadGameobjectRespawnTimes(); | |
void LoadItemPrototypes(); | |
void LoadItemLocales(); | |
+ void LoadTransmogrifications(); //transmogrification | |
void LoadQuestLocales(); | |
void LoadNpcTextLocales(); | |
void LoadPageTextLocales(); | |
diff --git a/src/game/Player.cpp b/src/game/Player.cpp | |
index 482db15..d6bc9dd 100644 | |
--- a/src/game/Player.cpp | |
+++ b/src/game/Player.cpp | |
@@ -10822,7 +10822,11 @@ void Player::SetVisibleItemSlot(uint8 slot, Item *pItem) | |
SetUInt64Value(PLAYER_VISIBLE_ITEM_1_CREATOR + (slot * MAX_VISIBLE_ITEM_OFFSET), pItem->GetUInt64Value(ITEM_FIELD_CREATOR)); | |
int VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); | |
- SetUInt32Value(VisibleBase + 0, pItem->GetEntry()); | |
+ //transmogrification | |
+ if (pItem->GetFakeEntry()) | |
+ SetUInt32Value(VisibleBase + 0, pItem->GetFakeEntry()); | |
+ else | |
+ SetUInt32Value(VisibleBase + 0, pItem->GetEntry()); | |
for (int i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; ++i) | |
SetUInt32Value(VisibleBase + 1 + i, pItem->GetEnchantmentId(EnchantmentSlot(i))); | |
@@ -10946,6 +10950,7 @@ void Player::MoveItemFromInventory(uint8 bag, uint8 slot, bool update) | |
{ | |
if (Item* it = GetItemByPos(bag,slot)) | |
{ | |
+ it->DeleteFakeFromDB(it->GetGUIDLow()); //transmogrification | |
ItemRemovedQuestCheck(it->GetEntry(), it->GetCount()); | |
RemoveItem(bag, slot, update); | |
it->RemoveFromUpdateQueueOf(this); | |
@@ -20852,3 +20857,56 @@ void Player::SetMap(Map * map) | |
Unit::SetMap(map); | |
m_mapRef.link(map, this); | |
} | |
+ | |
+uint32 Player::SuitableForTransmogrification(Item* oldItem, Item* newItem) //transmogrification | |
+{ | |
+ if (!newItem->HasGoodFakeQuality()) | |
+ return ERR_FAKE_NEW_BAD_QUALITY; | |
+ if (!oldItem->HasGoodFakeQuality()) | |
+ return ERR_FAKE_OLD_BAD_QUALITY; | |
+ | |
+ if (oldItem->GetProto()->DisplayInfoID == newItem->GetProto()->DisplayInfoID) | |
+ return ERR_FAKE_SAME_DISPLAY; | |
+ if (oldItem->GetFakeEntry()) | |
+ if(const ItemPrototype* FakeItemTemplate = objmgr.GetItemPrototype(oldItem->GetFakeEntry())) | |
+ if(FakeItemTemplate->DisplayInfoID == newItem->GetProto()->DisplayInfoID) | |
+ return ERR_FAKE_SAME_DISPLAY_FAKE; | |
+ if (CanUseItem(newItem, false) != EQUIP_ERR_OK) | |
+ return ERR_FAKE_CANT_USE; | |
+ uint32 newClass = newItem->GetProto()->Class; | |
+ uint32 oldClass = oldItem->GetProto()->Class; | |
+ uint32 newSubClass = newItem->GetProto()->SubClass; | |
+ uint32 oldSubClass = oldItem->GetProto()->SubClass; | |
+ uint32 newInventorytype = newItem->GetProto()->InventoryType; | |
+ uint32 oldInventorytype = oldItem->GetProto()->InventoryType; | |
+ if (newClass != oldClass) | |
+ return ERR_FAKE_NOT_SAME_CLASS; | |
+ if (newClass == ITEM_CLASS_WEAPON && newSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE && oldSubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE) | |
+ { | |
+ if (newSubClass == oldSubClass || ((newSubClass == ITEM_SUBCLASS_WEAPON_BOW || newSubClass == ITEM_SUBCLASS_WEAPON_GUN || newSubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW) && (oldSubClass == ITEM_SUBCLASS_WEAPON_BOW || oldSubClass == ITEM_SUBCLASS_WEAPON_GUN || oldSubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW))) | |
+ if (newInventorytype == oldInventorytype || (newInventorytype == INVTYPE_WEAPON && (oldInventorytype == INVTYPE_WEAPONMAINHAND || oldInventorytype == INVTYPE_WEAPONOFFHAND))) | |
+ return ERR_FAKE_OK; | |
+ else | |
+ return ERR_FAKE_BAD_INVENTORYTYPE; | |
+ else | |
+ return ERR_FAKE_BAD_SUBLCASS; | |
+ } | |
+ else if (newClass == ITEM_CLASS_ARMOR) | |
+ if (newSubClass == oldSubClass) | |
+ if (newInventorytype == oldInventorytype || (newInventorytype == INVTYPE_CHEST && oldInventorytype == INVTYPE_ROBE) || (newInventorytype == INVTYPE_ROBE && oldInventorytype == INVTYPE_CHEST)) | |
+ return ERR_FAKE_OK; | |
+ else | |
+ return ERR_FAKE_BAD_INVENTORYTYPE; | |
+ else | |
+ return ERR_FAKE_BAD_SUBLCASS; | |
+ return ERR_FAKE_BAD_CLASS; | |
+} | |
+ | |
+Bag* Player::GetBagByPos(uint8 bag) const | |
+{ | |
+ if ((bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END) | |
+ || (bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END)) | |
+ if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, bag)) | |
+ return item->ToBag(); | |
+ return NULL; | |
+} | |
diff --git a/src/game/Player.h b/src/game/Player.h | |
index e194d8b..20f6025 100644 | |
--- a/src/game/Player.h | |
+++ b/src/game/Player.h | |
@@ -68,6 +68,20 @@ enum BuyBankSlotResult | |
ERR_BANKSLOT_OK = 3 | |
}; | |
+enum TransmogrificationResult //transmogrification | |
+{ | |
+ ERR_FAKE_NEW_BAD_QUALITY, | |
+ ERR_FAKE_OLD_BAD_QUALITY, | |
+ ERR_FAKE_SAME_DISPLAY, | |
+ ERR_FAKE_SAME_DISPLAY_FAKE, | |
+ ERR_FAKE_CANT_USE, | |
+ ERR_FAKE_NOT_SAME_CLASS, | |
+ ERR_FAKE_BAD_CLASS, | |
+ ERR_FAKE_BAD_SUBLCASS, | |
+ ERR_FAKE_BAD_INVENTORYTYPE, | |
+ ERR_FAKE_OK | |
+}; | |
+ | |
enum PlayerSpellState | |
{ | |
PLAYERSPELL_UNCHANGED = 0, | |
@@ -976,6 +990,7 @@ class Player : public Unit, public GridObject<Player> | |
Item* GetItemByGuid(uint64 guid) const; | |
Item* GetItemByPos(uint16 pos) const; | |
Item* GetItemByPos(uint8 bag, uint8 slot) const; | |
+ Bag* GetBagByPos(uint8 slot) const; //transmogrification | |
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const; | |
Item* GetShield(bool useable = false) const; | |
static uint32 GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot | |
@@ -2107,6 +2122,8 @@ class Player : public Unit, public GridObject<Player> | |
bool HasTitle(uint32 bitIndex); | |
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } | |
void SetTitle(CharTitlesEntry const* title, bool lost = false); | |
+ | |
+ uint32 SuitableForTransmogrification(Item* oldItem, Item* newItem); //transmogrification | |
protected: | |
diff --git a/src/game/World.cpp b/src/game/World.cpp | |
index b3fbd50..80f8b56 100644 | |
--- a/src/game/World.cpp | |
+++ b/src/game/World.cpp | |
@@ -1222,6 +1222,9 @@ void World::SetInitialWorldSettings() | |
sLog.outString("Loading Item Texts..."); | |
objmgr.LoadItemTexts(); | |
+ | |
+ sLog.outString("Loading Transmogrifications..."); //transmogrification | |
+ objmgr.LoadTransmogrifications(); | |
sLog.outString("Loading Creature Model Based Info Data..."); | |
objmgr.LoadCreatureModelInfo(); | |
diff --git a/src/scripts/World/npcs_special.cpp b/src/scripts/World/npcs_special.cpp | |
index ccbc05c..dab48e7 100644 | |
--- a/src/scripts/World/npcs_special.cpp | |
+++ b/src/scripts/World/npcs_special.cpp | |
@@ -29,6 +29,8 @@ EndContentData */ | |
#include "ScriptPCH.h" | |
#include "ScriptedEscortAI.h" | |
+#include "ObjectMgr.h" | |
+#include "Language.h" | |
/*###### | |
## npc_lunaclaw_spirit | |
@@ -1537,6 +1539,245 @@ bool GossipSelect_npc_spiritofazuregos(Player* player, Creature* creature, uint3 | |
return true; | |
} | |
+/* | |
+1.0. | |
+Transmogrification 2.4.3. - Gossip Menu | |
+Original patch by Rochet2. Update by Dirty, thx to lillecarl for GetBagByPos | |
+ | |
+ScriptName for NPC: | |
+transmog | |
+ | |
+TODO: | |
+Make DB saving even better (Deleting)? What about coding? | |
+Make local name for items | |
+Fix the cost formula | |
+ | |
+Cant transmogrify: | |
+rediculus _items // Foereaper: would be fun to stab people with a fish | |
+-- Cant think of any good way to handle this easily | |
+*/ | |
+ | |
+#define GOLD_COST 0 // 0 for no gold cost | |
+#include "Item.h" | |
+ | |
+#if (GOLD_COST) | |
+#define GOLD_COST_FUNCTION GetFakePrice(oldItem) | |
+#else | |
+#define GOLD_COST_FUNCTION 0 | |
+#endif | |
+ | |
+/*## | |
+##TRANSMOGRIFICATION | |
+##*/ | |
+std::string GetItemName(Item* item, WorldSession* session) | |
+ | |
+// local name | |
+{ | |
+ std::string name = item->GetProto()->Name1; | |
+ int loc_idx = session->GetSessionDbLocaleIndex(); | |
+ if (loc_idx >= 0) | |
+ if (ItemLocale const* il = objmgr.GetItemLocale(item->GetEntry())) | |
+ if(il) | |
+ { | |
+ if(il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty()) | |
+ name = il->Name[loc_idx]; | |
+ } | |
+ | |
+ | |
+ return name; | |
+} | |
+ | |
+std::map<uint64, std::map<uint32, Item*> > _items; // _items[lowGUID][DISPLAY] = item | |
+ | |
+const char * GetSlotName(uint8 slot, WorldSession* session) | |
+{ | |
+ switch(slot) | |
+ { | |
+ case EQUIPMENT_SLOT_HEAD : return session->GetBlizzLikeString(LANG_SLOT_NAME_HEAD); | |
+ case EQUIPMENT_SLOT_SHOULDERS : return session->GetBlizzLikeString(LANG_SLOT_NAME_SHOULDERS); | |
+ case EQUIPMENT_SLOT_BODY : return session->GetBlizzLikeString(LANG_SLOT_NAME_BODY); | |
+ case EQUIPMENT_SLOT_CHEST : return session->GetBlizzLikeString(LANG_SLOT_NAME_CHEST); | |
+ case EQUIPMENT_SLOT_WAIST : return session->GetBlizzLikeString(LANG_SLOT_NAME_WAIST); | |
+ case EQUIPMENT_SLOT_LEGS : return session->GetBlizzLikeString(LANG_SLOT_NAME_LEGS); | |
+ case EQUIPMENT_SLOT_FEET : return session->GetBlizzLikeString(LANG_SLOT_NAME_FEET); | |
+ case EQUIPMENT_SLOT_WRISTS : return session->GetBlizzLikeString(LANG_SLOT_NAME_WRISTS); | |
+ case EQUIPMENT_SLOT_HANDS : return session->GetBlizzLikeString(LANG_SLOT_NAME_HANDS); | |
+ case EQUIPMENT_SLOT_BACK : return session->GetBlizzLikeString(LANG_SLOT_NAME_BACK); | |
+ case EQUIPMENT_SLOT_MAINHAND : return session->GetBlizzLikeString(LANG_SLOT_NAME_MAINHAND); | |
+ case EQUIPMENT_SLOT_OFFHAND : return session->GetBlizzLikeString(LANG_SLOT_NAME_OFFHAND); | |
+ case EQUIPMENT_SLOT_RANGED : return session->GetBlizzLikeString(LANG_SLOT_NAME_RANGED); | |
+ case EQUIPMENT_SLOT_TABARD : return session->GetBlizzLikeString(LANG_SLOT_NAME_TABARD); | |
+ default: return NULL; | |
+ } | |
+} | |
+ | |
+bool GossipHello_transmog(Player* player, Creature* creature) | |
+ { | |
+ WorldSession* session = player->GetSession(); | |
+ for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_TABARD; slot++) // EQUIPMENT_SLOT_END | |
+ { | |
+ if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) | |
+ { | |
+ if (newItem->HasGoodFakeQuality()) | |
+ { | |
+ if (const char* slotName = GetSlotName(slot, session)) | |
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, slotName, EQUIPMENT_SLOT_END, slot); | |
+ } | |
+ } | |
+ } | |
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, session->GetBlizzLikeString(LANG_OPTION_REMOVE_ALL), EQUIPMENT_SLOT_END+2, 0, session->GetBlizzLikeString(LANG_POPUP_REMOVE_ALL), 0, false); | |
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, session->GetBlizzLikeString(LANG_OPTION_UPDATE_MENU), EQUIPMENT_SLOT_END+1, 0); | |
+ player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); | |
+ return true; | |
+ } | |
+ | |
+bool GossipSelect_transmog(Player* player, Creature* creature, uint32 sender, uint32 uiAction) | |
+{ | |
+ WorldSession* session = player->GetSession(); | |
+ player->PlayerTalkClass->ClearMenus(); | |
+ switch(sender) | |
+ { | |
+ case EQUIPMENT_SLOT_END: // Show items you can use | |
+ { | |
+ if (Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)) | |
+ { | |
+ uint32 lowGUID = player->GetGUIDLow(); | |
+ _items[lowGUID].clear(); | |
+ uint32 limit = 0; | |
+ for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) | |
+ { | |
+ if (limit > 30) | |
+ break; | |
+ if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) | |
+ { | |
+ uint32 display = newItem->GetProto()->DisplayInfoID; | |
+ if (player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) | |
+ { | |
+ if (_items[lowGUID].find(display) == _items[lowGUID].end()) | |
+ { | |
+ limit++; | |
+ _items[lowGUID][display] = newItem; | |
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, newItem->GetProto()->Name1, uiAction, display, session->GetBlizzLikeString(LANG_POPUP_TRANSMOGRIFY)+GetItemName(newItem, session), 0, false); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) | |
+ { | |
+ if (Bag* bag = player->GetBagByPos(i)) | |
+ { | |
+ for (uint32 j = 0; j < bag->GetBagSize(); j++) | |
+ { | |
+ if (limit > 30) | |
+ break; | |
+ if (Item* newItem = player->GetItemByPos(i, j)) | |
+ { | |
+ uint32 display = newItem->GetProto()->DisplayInfoID; | |
+ if (player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) | |
+ { | |
+ if (_items[lowGUID].find(display) == _items[lowGUID].end()) | |
+ { | |
+ limit++; | |
+ _items[lowGUID][display] = newItem; | |
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, newItem->GetProto()->Name1, uiAction, display, session->GetBlizzLikeString(LANG_POPUP_TRANSMOGRIFY)+GetItemName(newItem, session), GOLD_COST_FUNCTION, false);} | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ char popup[250]; | |
+ snprintf(popup, 250, session->GetBlizzLikeString(LANG_POPUP_REMOVE_ONE), GetSlotName(uiAction, session)); | |
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, session->GetBlizzLikeString(LANG_OPTION_REMOVE_ONE), EQUIPMENT_SLOT_END+3, uiAction, popup, 0, false); | |
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, session->GetBlizzLikeString(LANG_OPTION_BACK), EQUIPMENT_SLOT_END+1, 0); | |
+ player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); | |
+ } | |
+ else | |
+ GossipHello_transmog(player, creature); | |
+ } break; | |
+ case EQUIPMENT_SLOT_END+1: // Back | |
+ { | |
+ GossipHello_transmog(player, creature); | |
+ } break; | |
+ case EQUIPMENT_SLOT_END+2: // Remove Transmogrifications | |
+ { | |
+ bool removed = false; | |
+ for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++) | |
+ { | |
+ if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot)) | |
+ { | |
+ if (newItem->DeleteFakeEntry() && !removed) | |
+ removed = true; | |
+ } | |
+ } | |
+ if (removed) | |
+ { | |
+ session->SendAreaTriggerMessage(session->GetBlizzLikeString(LANG_REM_TRANSMOGRIFICATIONS_ITEMS)); | |
+ player->PlayDirectSound(3337); | |
+ } | |
+ else | |
+ session->SendNotification(session->GetBlizzLikeString(LANG_ERR_NO_TRANSMOGRIFICATIONS)); | |
+ GossipHello_transmog(player, creature); | |
+ } break; | |
+ case EQUIPMENT_SLOT_END+3: // Remove Transmogrification from single item | |
+ { | |
+ if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)) | |
+ { | |
+ if (newItem->DeleteFakeEntry()) | |
+ { | |
+ session->SendAreaTriggerMessage(session->GetBlizzLikeString(LANG_REM_TRANSMOGRIFICATION_ITEM), GetSlotName(uiAction, session)); | |
+ player->PlayDirectSound(3337); | |
+ } | |
+ else | |
+ session->SendNotification(session->GetBlizzLikeString(LANG_ERR_NO_TRANSMOGRIFICATION), GetSlotName(uiAction, session)); | |
+ } | |
+ GossipSelect_transmog(player, creature, EQUIPMENT_SLOT_END, uiAction); | |
+ } break; | |
+ default: // Transmogrify | |
+ { | |
+ uint32 lowGUID = player->GetGUIDLow(); | |
+ if (Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, sender)) | |
+ { | |
+ if (_items[lowGUID].find(uiAction) != _items[lowGUID].end() && _items[lowGUID][uiAction]->IsInWorld()) | |
+ { | |
+ Item* newItem = _items[lowGUID][uiAction]; | |
+ if (newItem->GetOwnerGUID() == player->GetGUIDLow() && (newItem->IsInBag() || newItem->GetBagSlot() == INVENTORY_SLOT_BAG_0) && player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) | |
+ { | |
+#if (GOLD_COST) | |
+ player->ModifyMoney(-1*GetFakePrice(oldItem)); // take cost | |
+#endif | |
+ oldItem->SetFakeEntry(newItem->GetEntry()); | |
+ newItem->SetBinding(true); | |
+ player->PlayDirectSound(3337); | |
+ session->SendAreaTriggerMessage(session->GetBlizzLikeString(LANG_ITEM_TRANSMOGRIFIED), GetSlotName(sender, session)); | |
+ } | |
+ else | |
+ session->SendNotification(session->GetBlizzLikeString(LANG_ERR_NO_ITEM_SUITABLE)); | |
+ } | |
+ else | |
+ session->SendNotification(session->GetBlizzLikeString(LANG_ERR_NO_ITEM_EXISTS)); | |
+ } | |
+ else | |
+ session->SendNotification(session->GetBlizzLikeString(LANG_ERR_EQUIP_SLOT_EMPTY)); | |
+ _items[lowGUID].clear(); | |
+ GossipSelect_transmog(player, creature, EQUIPMENT_SLOT_END, sender); | |
+ } break; | |
+ } | |
+ return true; | |
+} | |
+ | |
+#if (GOLD_COST) | |
+ uint32 GetFakePrice(Item* item) | |
+ { | |
+ uint32 sellPrice = item->GetProto()->SellPrice; | |
+ uint32 minPrice = item->GetProto()->RequiredLevel * 1176; | |
+ if (sellPrice < minPrice) | |
+ sellPrice = minPrice; | |
+ return sellPrice; | |
+ } | |
+#endif | |
+ | |
void AddSC_npcs_special() | |
{ | |
Script *newscript; | |
@@ -1632,12 +1873,18 @@ void AddSC_npcs_special() | |
newscript->Name = "mob_mojo"; | |
newscript->GetAI = &GetAI_mob_mojo; | |
newscript->RegisterSelf(); | |
- | |
+ | |
newscript = new Script; | |
newscript->Name = "npc_spiritofazuregos"; | |
newscript->pGossipHello = &GossipHello_npc_spiritofazuregos; | |
newscript->pGossipSelect = &GossipSelect_npc_spiritofazuregos; | |
newscript->RegisterSelf(); | |
+ | |
+ newscript = new Script; | |
+ newscript->Name = "transmog"; | |
+ newscript->pGossipHello = &GossipHello_transmog; | |
+ newscript->pGossipSelect = &GossipSelect_transmog; | |
+ newscript->RegisterSelf(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment