mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
599 lines
25 KiB
Lua
599 lines
25 KiB
Lua
|
|
--[[
|
||
|
|
4.0
|
||
|
|
Transmogrification for Classic & TBC & WoTLK - Gossip Menu
|
||
|
|
By Rochet2
|
||
|
|
|
||
|
|
Eluna version
|
||
|
|
|
||
|
|
TODO:
|
||
|
|
Make DB saving even better (Deleting)? What about coding?
|
||
|
|
|
||
|
|
Fix the cost formula
|
||
|
|
|
||
|
|
TODO in the distant future:
|
||
|
|
|
||
|
|
Are the qualities right? Blizzard might have changed the quality requirements.
|
||
|
|
What can and cant be used as source or target..?
|
||
|
|
|
||
|
|
Cant transmogrify:
|
||
|
|
rediculus items -- Foereaper: would be fun to stab people with a fish
|
||
|
|
-- Cant think of any good way to handle this easily
|
||
|
|
|
||
|
|
Cataclysm:
|
||
|
|
Test on cata : implement UI xD?
|
||
|
|
Item link icon to Are You sure text
|
||
|
|
|
||
|
|
-- vmangos
|
||
|
|
INSERT INTO `creature_template` (`entry`, `patch`, `display_id1`, `display_id2`, `display_id3`, `display_id4`, `name`, `subname`, `gossip_menu_id`, `level_min`, `level_max`, `health_min`, `health_max`, `mana_min`, `mana_max`, `armor`, `faction`, `npc_flags`, `speed_walk`, `speed_run`, `scale`, `detection_range`, `call_for_help_range`, `leash_range`, `rank`, `xp_multiplier`, `dmg_min`, `dmg_max`, `dmg_school`, `attack_power`, `dmg_multiplier`, `base_attack_time`, `ranged_attack_time`, `unit_class`, `unit_flags`, `dynamic_flags`, `beast_family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `ranged_dmg_min`, `ranged_dmg_max`, `ranged_attack_power`, `type`, `type_flags`, `loot_id`, `pickpocket_loot_id`, `skinning_loot_id`, `holy_res`, `fire_res`, `nature_res`, `frost_res`, `shadow_res`, `arcane_res`, `spell_id1`, `spell_id2`, `spell_id3`, `spell_id4`, `spell_list_id`, `pet_spell_list_id`, `gold_min`, `gold_max`, `ai_name`, `movement_type`, `inhabit_type`, `civilian`, `racial_leader`, `regeneration`, `equipment_id`, `trainer_id`, `vendor_id`, `mechanic_immune_mask`, `school_immune_mask`, `flags_extra`, `script_name`) VALUES ('70003', '0', '11121', '0', '0', '0', '幻化大师', '外形铸造师', '0', '55', '55', '1500', '1500', '5013', '5013', '1644', '35', '1', '1.1', '1.14286', '0.1', '20', '5', '0', '0', '1', '316', '316', '0', '248', '1', '2000', '2000', '8', '32768', '0', '0', '0', '0', '0', '0', '0', '0', '0', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '', '0', '3', '0', '0', '3', '0', '0', '0', '0', '0', '0', '');
|
||
|
|
|
||
|
|
-- ----------------------------
|
||
|
|
-- Table structure for custom_transmogrification
|
||
|
|
-- ----------------------------
|
||
|
|
DROP TABLE IF EXISTS `custom_transmogrification`;
|
||
|
|
CREATE TABLE `custom_transmogrification` (
|
||
|
|
`GUID` int(10) unsigned NOT NULL COMMENT 'Item guidLow',
|
||
|
|
`FakeEntry` int(10) unsigned NOT NULL COMMENT 'Item entry',
|
||
|
|
`Owner` int(10) unsigned NOT NULL COMMENT 'Player guidLow',
|
||
|
|
PRIMARY KEY (`GUID`)
|
||
|
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='version 4.0';
|
||
|
|
|
||
|
|
-- vmangos v21
|
||
|
|
INSERT INTO `creature_template` (`entry`, `patch`, `display_id1`, `display_id2`, `display_id3`
|
||
|
|
, `display_id4`, `name`, `subname`, `gossip_menu_id`, `level_min`
|
||
|
|
, `level_max`, `faction`, `npc_flags`, `speed_walk`, `speed_run`
|
||
|
|
, `display_scale1`, `detection_range`, `call_for_help_range`, `leash_range`, `rank`
|
||
|
|
, `xp_multiplier`, `damage_school`, `damage_multiplier`, `base_attack_time`, `ranged_attack_time`
|
||
|
|
, `unit_class`, `unit_flags`, `pet_family`, `trainer_type`, `trainer_spell`
|
||
|
|
, `trainer_class`, `trainer_race`, `type`, `type_flags`, `loot_id`
|
||
|
|
, `pickpocket_loot_id`, `skinning_loot_id`, `holy_res`, `fire_res`, `nature_res`
|
||
|
|
, `frost_res`, `shadow_res`, `arcane_res`, `spell_id1`, `spell_id2`
|
||
|
|
, `spell_id3`, `spell_id4`, `spell_list_id`, `pet_spell_list_id`, `gold_min`
|
||
|
|
, `gold_max`, `ai_name`, `movement_type`, `inhabit_type`, `civilian`
|
||
|
|
, `racial_leader`, `regeneration`, `equipment_id`, `trainer_id`, `vendor_id`
|
||
|
|
, `mechanic_immune_mask`, `school_immune_mask`, `flags_extra`, `script_name`)
|
||
|
|
VALUES ('70003', '0', '11121', '0', '0'
|
||
|
|
, '0', '幻化大师', '幻化大师', '0', '55'
|
||
|
|
, '55', '35', '1', '1.1', '1.14286'
|
||
|
|
, '0.1', '20', '5', '0', '0'
|
||
|
|
, '1', '0', '1', '2000', '2000'
|
||
|
|
, '8', '32768', '0', '0', '0'
|
||
|
|
, '0', '0', '7', '0', '0'
|
||
|
|
, '0', '0', '0', '0', '0'
|
||
|
|
, '0', '0', '0', '0', '0'
|
||
|
|
, '0', '0', '0', '0', '0'
|
||
|
|
, '0', '', '0', '3', '0'
|
||
|
|
, '0', '3', '0', '0', '0'
|
||
|
|
, '0', '0', '0', '');
|
||
|
|
|
||
|
|
]]
|
||
|
|
print(">> Transmog")
|
||
|
|
local NPC_Entry = 70003
|
||
|
|
|
||
|
|
local RequireGold = 1
|
||
|
|
local GoldModifier = 1.0
|
||
|
|
local GoldCost = 100000
|
||
|
|
|
||
|
|
local RequireToken = false
|
||
|
|
local TokenEntry = 49426
|
||
|
|
local TokenAmount = 1
|
||
|
|
|
||
|
|
local AllowMixedArmorTypes = false
|
||
|
|
local AllowMixedWeaponTypes = false
|
||
|
|
|
||
|
|
local Qualities =
|
||
|
|
{
|
||
|
|
[0] = false, -- AllowPoor
|
||
|
|
[1] = false, -- AllowCommon
|
||
|
|
[2] = true , -- AllowUncommon
|
||
|
|
[3] = true , -- AllowRare
|
||
|
|
[4] = true , -- AllowEpic
|
||
|
|
[5] = false, -- AllowLegendary
|
||
|
|
[6] = false, -- AllowArtifact
|
||
|
|
[7] = true , -- AllowHeirloom
|
||
|
|
}
|
||
|
|
|
||
|
|
local EQUIPMENT_SLOT_START = 0
|
||
|
|
local EQUIPMENT_SLOT_HEAD = 0
|
||
|
|
local EQUIPMENT_SLOT_NECK = 1
|
||
|
|
local EQUIPMENT_SLOT_SHOULDERS = 2
|
||
|
|
local EQUIPMENT_SLOT_BODY = 3
|
||
|
|
local EQUIPMENT_SLOT_CHEST = 4
|
||
|
|
local EQUIPMENT_SLOT_WAIST = 5
|
||
|
|
local EQUIPMENT_SLOT_LEGS = 6
|
||
|
|
local EQUIPMENT_SLOT_FEET = 7
|
||
|
|
local EQUIPMENT_SLOT_WRISTS = 8
|
||
|
|
local EQUIPMENT_SLOT_HANDS = 9
|
||
|
|
local EQUIPMENT_SLOT_FINGER1 = 10
|
||
|
|
local EQUIPMENT_SLOT_FINGER2 = 11
|
||
|
|
local EQUIPMENT_SLOT_TRINKET1 = 12
|
||
|
|
local EQUIPMENT_SLOT_TRINKET2 = 13
|
||
|
|
local EQUIPMENT_SLOT_BACK = 14
|
||
|
|
local EQUIPMENT_SLOT_MAINHAND = 15
|
||
|
|
local EQUIPMENT_SLOT_OFFHAND = 16
|
||
|
|
local EQUIPMENT_SLOT_RANGED = 17
|
||
|
|
local EQUIPMENT_SLOT_TABARD = 18
|
||
|
|
local EQUIPMENT_SLOT_END = 19
|
||
|
|
|
||
|
|
local INVENTORY_SLOT_BAG_START = 19
|
||
|
|
local INVENTORY_SLOT_BAG_END = 23
|
||
|
|
|
||
|
|
local INVENTORY_SLOT_ITEM_START = 23
|
||
|
|
local INVENTORY_SLOT_ITEM_END = 39
|
||
|
|
|
||
|
|
local INVTYPE_CHEST = 5
|
||
|
|
local INVTYPE_WEAPON = 13
|
||
|
|
local INVTYPE_ROBE = 20
|
||
|
|
local INVTYPE_WEAPONMAINHAND = 21
|
||
|
|
local INVTYPE_WEAPONOFFHAND = 22
|
||
|
|
|
||
|
|
local ITEM_CLASS_WEAPON = 2
|
||
|
|
local ITEM_CLASS_ARMOR = 4
|
||
|
|
|
||
|
|
local ITEM_SUBCLASS_WEAPON_BOW = 2
|
||
|
|
local ITEM_SUBCLASS_WEAPON_GUN = 3
|
||
|
|
local ITEM_SUBCLASS_WEAPON_CROSSBOW = 18
|
||
|
|
local ITEM_SUBCLASS_WEAPON_FISHING_POLE = 20
|
||
|
|
|
||
|
|
local EXPANSION_WOTLK = 2
|
||
|
|
local EXPANSION_TBC = 1
|
||
|
|
local PLAYER_VISIBLE_ITEM_1_ENTRYID
|
||
|
|
local ITEM_SLOT_MULTIPLIER
|
||
|
|
if GetCoreExpansion() < EXPANSION_TBC then
|
||
|
|
PLAYER_VISIBLE_ITEM_1_ENTRYID = 260
|
||
|
|
ITEM_SLOT_MULTIPLIER = 12
|
||
|
|
elseif GetCoreExpansion() < EXPANSION_WOTLK then
|
||
|
|
PLAYER_VISIBLE_ITEM_1_ENTRYID = 346
|
||
|
|
ITEM_SLOT_MULTIPLIER = 16
|
||
|
|
else
|
||
|
|
PLAYER_VISIBLE_ITEM_1_ENTRYID = 283
|
||
|
|
ITEM_SLOT_MULTIPLIER = 2
|
||
|
|
end
|
||
|
|
|
||
|
|
local INVENTORY_SLOT_BAG_0 = 255
|
||
|
|
|
||
|
|
local SlotNames = {
|
||
|
|
[EQUIPMENT_SLOT_HEAD ] = {"头盔", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_SHOULDERS ] = {"肩甲", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_BODY ] = {"衬衣", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_CHEST ] = {"胸甲", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_WAIST ] = {"腰带", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_LEGS ] = {"腿铠", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_FEET ] = {"靴子", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_WRISTS ] = {"手腕", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_HANDS ] = {"护手", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_BACK ] = {"披风", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_MAINHAND ] = {"主手", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_OFFHAND ] = {"副手", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_RANGED ] = {"远程武器", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
[EQUIPMENT_SLOT_TABARD ] = {"战袍", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
}
|
||
|
|
local Locales = {
|
||
|
|
{"更新菜单", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"移除所有幻化", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"移除所有幻化?", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"使用该物品幻化将板顶并无法退货和交易. \n 确认继续?", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"移除幻化 %s?", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"返回..", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"移除幻化", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"移除幻化已经从装备上的物品上移除", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"你没有装备幻化物品", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"%s 的幻化移除", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"在 %s 槽没有幻化", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"%s 幻化成功", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"选择的物品不合适", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"选择的物品不存在", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"装备插槽为空", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"你没有足够的 %ss", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
{"你没有足够的金币", nil, nil, nil, nil, nil, nil, nil, nil},
|
||
|
|
}
|
||
|
|
local function LocText(id, p) -- "%s":format("test")
|
||
|
|
if Locales[id] then
|
||
|
|
local s = Locales[id][p:GetDbcLocale()+1] or Locales[id][1]
|
||
|
|
if s then
|
||
|
|
return s
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return "Text not found: "..(id or 0)
|
||
|
|
end
|
||
|
|
--[[
|
||
|
|
typedef UNORDERED_MAP<uint32, uint32> transmogData
|
||
|
|
typedef UNORDERED_MAP<uint32, transmogData> transmogMap
|
||
|
|
static transmogMap entryMap -- entryMap[pGUID][iGUID] = entry
|
||
|
|
static transmogData dataMap -- dataMap[iGUID] = pGUID
|
||
|
|
]]
|
||
|
|
local entryMap = {}
|
||
|
|
local dataMap = {}
|
||
|
|
|
||
|
|
local function GetSlotName(slot, locale)
|
||
|
|
if not SlotNames[slot] then return end
|
||
|
|
return locale and SlotNames[slot][locale+1] or SlotNames[slot][1]
|
||
|
|
end
|
||
|
|
|
||
|
|
local function GetFakePrice(item)
|
||
|
|
local sellPrice = item:GetSellPrice()
|
||
|
|
local minPrice = 10000
|
||
|
|
if sellPrice < minPrice then
|
||
|
|
sellPrice = minPrice
|
||
|
|
end
|
||
|
|
return sellPrice
|
||
|
|
end
|
||
|
|
|
||
|
|
local function GetFakeEntry(item)
|
||
|
|
local guid = item and item:GetGUIDLow()
|
||
|
|
if guid and dataMap[guid] then
|
||
|
|
if entryMap[dataMap[guid]] then
|
||
|
|
return entryMap[dataMap[guid]][guid]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function DeleteFakeFromDB(itemGUID)
|
||
|
|
if dataMap[itemGUID] then
|
||
|
|
if entryMap[dataMap[itemGUID]] then
|
||
|
|
entryMap[dataMap[itemGUID]][itemGUID] = nil
|
||
|
|
end
|
||
|
|
dataMap[itemGUID] = nil
|
||
|
|
end
|
||
|
|
CharDBExecute("DELETE FROM custom_transmogrification WHERE GUID = "..itemGUID)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function DeleteFakeEntry(item)
|
||
|
|
if not GetFakeEntry(item) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
item:GetOwner():UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), item:GetEntry())
|
||
|
|
DeleteFakeFromDB(item:GetGUIDLow())
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SetFakeEntry(item, entry)
|
||
|
|
local player = item:GetOwner()
|
||
|
|
if player then
|
||
|
|
local pGUID = player:GetGUIDLow()
|
||
|
|
local iGUID = item:GetGUIDLow()
|
||
|
|
player:UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), entry)
|
||
|
|
if not entryMap[pGUID] then
|
||
|
|
entryMap[pGUID] = {}
|
||
|
|
end
|
||
|
|
entryMap[pGUID][iGUID] = entry
|
||
|
|
dataMap[iGUID] = pGUID
|
||
|
|
CharDBExecute("REPLACE INTO custom_transmogrification (GUID, FakeEntry, Owner) VALUES ("..iGUID..", "..entry..", "..pGUID..")")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function IsRangedWeapon(Class, SubClass)
|
||
|
|
return Class == ITEM_CLASS_WEAPON and (
|
||
|
|
SubClass == ITEM_SUBCLASS_WEAPON_BOW or
|
||
|
|
SubClass == ITEM_SUBCLASS_WEAPON_GUN or
|
||
|
|
SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SuitableForTransmogrification(player, transmogrified, transmogrifier)
|
||
|
|
if not transmogrified or not transmogrifier then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if not Qualities[transmogrifier:GetQuality()] then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if not Qualities[transmogrified:GetQuality()] then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if transmogrified:GetDisplayId() == transmogrifier:GetDisplayId() then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
local fentry = GetFakeEntry(transmogrified)
|
||
|
|
if fentry and fentry == transmogrifier:GetEntry() then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if not player:CanUseItem(transmogrifier) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
local fierClass = transmogrifier:GetClass()
|
||
|
|
local fiedClass = transmogrified:GetClass()
|
||
|
|
local fierSubClass = transmogrifier:GetSubClass()
|
||
|
|
local fiedSubClass = transmogrified:GetSubClass()
|
||
|
|
local fierInventorytype = transmogrifier:GetInventoryType()
|
||
|
|
local fiedInventorytype = transmogrified:GetInventoryType()
|
||
|
|
|
||
|
|
if fiedInventorytype == INVTYPE_BAG or
|
||
|
|
fiedInventorytype == INVTYPE_RELIC or
|
||
|
|
-- fiedInventorytype == INVTYPE_BODY or
|
||
|
|
fiedInventorytype == INVTYPE_FINGER or
|
||
|
|
fiedInventorytype == INVTYPE_TRINKET or
|
||
|
|
fiedInventorytype == INVTYPE_AMMO or
|
||
|
|
fiedInventorytype == INVTYPE_QUIVER then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if fierInventorytype == INVTYPE_BAG or
|
||
|
|
fierInventorytype == INVTYPE_RELIC or
|
||
|
|
-- fierInventorytype == INVTYPE_BODY or
|
||
|
|
fierInventorytype == INVTYPE_FINGER or
|
||
|
|
fierInventorytype == INVTYPE_TRINKET or
|
||
|
|
fierInventorytype == INVTYPE_AMMO or
|
||
|
|
fierInventorytype == INVTYPE_QUIVER then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if fierClass ~= fiedClass then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if IsRangedWeapon(fiedClass, fiedSubClass) ~= IsRangedWeapon(fierClass, fierSubClass) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
if fierSubClass ~= fiedSubClass and not IsRangedWeapon(fiedClass, fiedSubClass) then
|
||
|
|
if fierClass == ITEM_CLASS_ARMOR and not AllowMixedArmorTypes then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
if fierClass == ITEM_CLASS_WEAPON and not AllowMixedWeaponTypes then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if (fierInventorytype ~= fiedInventorytype) then
|
||
|
|
if (fierClass == ITEM_CLASS_WEAPON and not ((IsRangedWeapon(fiedClass, fiedSubClass) or
|
||
|
|
((fiedInventorytype == INVTYPE_WEAPON or fiedInventorytype == INVTYPE_2HWEAPON) and
|
||
|
|
(fierInventorytype == INVTYPE_WEAPON or fierInventorytype == INVTYPE_2HWEAPON)) or
|
||
|
|
((fiedInventorytype == INVTYPE_WEAPONMAINHAND or fiedInventorytype == INVTYPE_WEAPONOFFHAND) and
|
||
|
|
(fierInventorytype == INVTYPE_WEAPON or fierInventorytype == INVTYPE_2HWEAPON))))) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
if (fierClass == ITEM_CLASS_ARMOR and
|
||
|
|
not ((fierInventorytype == INVTYPE_CHEST or fierInventorytype == INVTYPE_ROBE) and
|
||
|
|
(fiedInventorytype == INVTYPE_CHEST or fiedInventorytype == INVTYPE_ROBE))) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
local menu_id = math.random(1000)
|
||
|
|
|
||
|
|
local function OnGossipHello(event, player, creature)
|
||
|
|
player:GossipClearMenu()
|
||
|
|
for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
|
||
|
|
local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
|
||
|
|
if transmogrified then
|
||
|
|
if Qualities[transmogrified:GetQuality()] then
|
||
|
|
local slotName = GetSlotName(slot, player:GetDbcLocale())
|
||
|
|
if slotName then
|
||
|
|
player:GossipMenuAddItem(3, slotName, EQUIPMENT_SLOT_END, slot)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
player:GossipMenuAddItem(4, LocText(2, player), EQUIPMENT_SLOT_END+2, 0, false, LocText(3, player), 0)
|
||
|
|
player:GossipMenuAddItem(7, LocText(1, player), EQUIPMENT_SLOT_END+1, 0)
|
||
|
|
player:GossipSendMenu(100, creature, menu_id)
|
||
|
|
end
|
||
|
|
|
||
|
|
local _items = {}
|
||
|
|
local function OnGossipSelect(event, player, creature, slotid, uiAction)
|
||
|
|
if slotid == EQUIPMENT_SLOT_END then -- Show items you can use
|
||
|
|
local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)
|
||
|
|
if transmogrified then
|
||
|
|
local lowGUID = player:GetGUIDLow()
|
||
|
|
_items[lowGUID] = {} -- Remove this with logix
|
||
|
|
local limit = 0
|
||
|
|
local price = 0
|
||
|
|
if RequireGold == 1 then
|
||
|
|
price = GetFakePrice(transmogrified)*GoldModifier
|
||
|
|
elseif RequireGold == 2 then
|
||
|
|
price = GoldCost
|
||
|
|
end
|
||
|
|
|
||
|
|
for i = INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END-1 do
|
||
|
|
if limit > 30 then
|
||
|
|
break
|
||
|
|
end
|
||
|
|
local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, i)
|
||
|
|
if transmogrifier then
|
||
|
|
local display = transmogrifier:GetDisplayId()
|
||
|
|
if SuitableForTransmogrification(player, transmogrified, transmogrifier) then
|
||
|
|
if not _items[lowGUID][display] then
|
||
|
|
limit = limit + 1
|
||
|
|
_items[lowGUID][display] = {transmogrifier:GetBagSlot(), transmogrifier:GetSlot()}
|
||
|
|
local popup = LocText(4, player).."\n\n"..transmogrifier:GetItemLink(player:GetDbcLocale()).."\n"
|
||
|
|
if RequireToken then
|
||
|
|
popup = popup.."\n"..TokenAmount.." x "..GetItemLink(TokenEntry, player:GetDbcLocale())
|
||
|
|
end
|
||
|
|
player:GossipMenuAddItem(4, transmogrifier:GetItemLink(player:GetDbcLocale()), uiAction, display, false, popup, price)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
for i = INVENTORY_SLOT_BAG_START, INVENTORY_SLOT_BAG_END-1 do
|
||
|
|
local bag = player:GetItemByPos(INVENTORY_SLOT_BAG_0, i)
|
||
|
|
if bag then
|
||
|
|
for j = 0, bag:GetBagSize()-1 do
|
||
|
|
if limit > 30 then
|
||
|
|
break
|
||
|
|
end
|
||
|
|
local transmogrifier = player:GetItemByPos(i, j)
|
||
|
|
if transmogrifier then
|
||
|
|
local display = transmogrifier:GetDisplayId()
|
||
|
|
if SuitableForTransmogrification(player, transmogrified, transmogrifier) then
|
||
|
|
if not _items[lowGUID][display] then
|
||
|
|
limit = limit + 1
|
||
|
|
_items[lowGUID][display] = {transmogrifier:GetBagSlot(), transmogrifier:GetSlot()}
|
||
|
|
player:GossipMenuAddItem(4, transmogrifier:GetItemLink(player:GetDbcLocale()), uiAction, display, false, popup, price)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
player:GossipMenuAddItem(4, LocText(7, player), EQUIPMENT_SLOT_END+3, uiAction, false, LocText(5, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
|
||
|
|
player:GossipMenuAddItem(7, LocText(6, player), EQUIPMENT_SLOT_END+1, 0)
|
||
|
|
player:GossipSendMenu(100, creature, menu_id)
|
||
|
|
else
|
||
|
|
OnGossipHello(event, player, creature)
|
||
|
|
end
|
||
|
|
elseif slotid == EQUIPMENT_SLOT_END+1 then -- Back
|
||
|
|
OnGossipHello(event, player, creature)
|
||
|
|
elseif slotid == EQUIPMENT_SLOT_END+2 then -- Remove Transmogrifications
|
||
|
|
local removed = false
|
||
|
|
for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
|
||
|
|
local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
|
||
|
|
if transmogrifier then
|
||
|
|
if DeleteFakeEntry(transmogrifier) and not removed then
|
||
|
|
removed = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if removed then
|
||
|
|
player:SendAreaTriggerMessage(LocText(8, player))
|
||
|
|
-- player:PlayDirectSound(3337)
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(9, player))
|
||
|
|
end
|
||
|
|
OnGossipHello(event, player, creature)
|
||
|
|
elseif slotid == EQUIPMENT_SLOT_END+3 then -- Remove Transmogrification from single item
|
||
|
|
local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)
|
||
|
|
if transmogrifier then
|
||
|
|
if DeleteFakeEntry(transmogrifier) then
|
||
|
|
player:SendAreaTriggerMessage(LocText(10, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
|
||
|
|
-- player:PlayDirectSound(3337)
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(11, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
OnGossipSelect(event, player, creature, EQUIPMENT_SLOT_END, uiAction)
|
||
|
|
else -- Transmogrify
|
||
|
|
local lowGUID = player:GetGUIDLow()
|
||
|
|
if not RequireToken or player:GetItemCount(TokenEntry) >= TokenAmount then
|
||
|
|
local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slotid)
|
||
|
|
if transmogrified then
|
||
|
|
if _items[lowGUID] and _items[lowGUID][uiAction] and _items[lowGUID][uiAction] then
|
||
|
|
local transmogrifier = player:GetItemByPos(_items[lowGUID][uiAction][1], _items[lowGUID][uiAction][2])
|
||
|
|
if transmogrifier:GetOwnerGUID() == player:GetGUID() and (transmogrifier:IsInBag() or transmogrifier:GetBagSlot() == INVENTORY_SLOT_BAG_0) and SuitableForTransmogrification(player, transmogrified, transmogrifier) then
|
||
|
|
local price
|
||
|
|
if RequireGold == 1 then
|
||
|
|
price = GetFakePrice(transmogrified)*GoldModifier
|
||
|
|
elseif RequireGold == 2 then
|
||
|
|
price = GoldCost
|
||
|
|
end
|
||
|
|
if price then
|
||
|
|
if player:GetCoinage() >= price then
|
||
|
|
player:ModifyMoney(-1*price)
|
||
|
|
if RequireToken then
|
||
|
|
player:RemoveItem(TokenEntry, TokenAmount)
|
||
|
|
end
|
||
|
|
SetFakeEntry(transmogrified, transmogrifier:GetEntry())
|
||
|
|
-- transmogrifier:SetNotRefundable(player)
|
||
|
|
transmogrifier:SetBinding(true)
|
||
|
|
-- player:PlayDirectSound(3337)
|
||
|
|
player:SendAreaTriggerMessage(LocText(12, player):format(GetSlotName(slotid, player:GetDbcLocale())))
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(17, player))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(13, player))
|
||
|
|
end
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(14, player))
|
||
|
|
end
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(15, player))
|
||
|
|
end
|
||
|
|
else
|
||
|
|
player:SendNotification(LocText(16, player):format(GetItemLink(TokenEntry, player:GetDbcLocale())))
|
||
|
|
end
|
||
|
|
_items[lowGUID] = {}
|
||
|
|
OnGossipSelect(event, player, creature, EQUIPMENT_SLOT_END, slotid)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnLogin(event, player)
|
||
|
|
local playerGUID = player:GetGUIDLow()
|
||
|
|
entryMap[playerGUID] = {}
|
||
|
|
local result = CharDBQuery("SELECT GUID, FakeEntry FROM custom_transmogrification WHERE Owner = "..playerGUID)
|
||
|
|
if result then
|
||
|
|
repeat
|
||
|
|
local itemGUID = result:GetUInt32(0)
|
||
|
|
local fakeEntry = result:GetUInt32(1)
|
||
|
|
-- if sObjectMgr:GetItemTemplate(fakeEntry) then
|
||
|
|
-- {
|
||
|
|
dataMap[itemGUID] = playerGUID
|
||
|
|
entryMap[playerGUID][itemGUID] = fakeEntry
|
||
|
|
-- }
|
||
|
|
-- else
|
||
|
|
-- sLog:outError(LOG_FILTER_SQL, "Item entry (Entry: %u, itemGUID: %u, playerGUID: %u) does not exist, deleting.", fakeEntry, itemGUID, playerGUID)
|
||
|
|
-- Transmogrification::DeleteFakeFromDB(itemGUID)
|
||
|
|
-- end
|
||
|
|
until not result:NextRow()
|
||
|
|
|
||
|
|
for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
|
||
|
|
local item = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
|
||
|
|
if item then
|
||
|
|
if entryMap[playerGUID] then
|
||
|
|
if entryMap[playerGUID][item:GetGUIDLow()] then
|
||
|
|
player:UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), entryMap[playerGUID][item:GetGUIDLow()])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnLogout(event, player)
|
||
|
|
local pGUID = player:GetGUIDLow()
|
||
|
|
entryMap[pGUID] = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnEquip(event, player, item, bag, slot)
|
||
|
|
local fentry = GetFakeEntry(item)
|
||
|
|
if fentry then
|
||
|
|
if item:GetOwnerGUID() ~= player:GetGUID() then
|
||
|
|
DeleteFakeFromDB(item:GetGUIDLow())
|
||
|
|
return
|
||
|
|
end
|
||
|
|
player:SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * ITEM_SLOT_MULTIPLIER), fentry)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Note, Query is instant when Execute is delayed
|
||
|
|
CharDBQuery([[
|
||
|
|
CREATE TABLE IF NOT EXISTS `custom_transmogrification` (
|
||
|
|
`GUID` INT(10) UNSIGNED NOT NULL COMMENT 'Item guidLow',
|
||
|
|
`FakeEntry` INT(10) UNSIGNED NOT NULL COMMENT 'Item entry',
|
||
|
|
`Owner` INT(10) UNSIGNED NOT NULL COMMENT 'Player guidLow',
|
||
|
|
PRIMARY KEY (`GUID`)
|
||
|
|
)
|
||
|
|
COMMENT='version 4.0'
|
||
|
|
COLLATE='latin1_swedish_ci'
|
||
|
|
ENGINE=InnoDB;
|
||
|
|
]])
|
||
|
|
|
||
|
|
print("Deleting non-existing transmogrification entries...")
|
||
|
|
CharDBQuery("DELETE FROM custom_transmogrification WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)")
|
||
|
|
|
||
|
|
RegisterPlayerEvent(3, OnLogin)
|
||
|
|
RegisterPlayerEvent(4, OnLogout)
|
||
|
|
RegisterPlayerEvent(29, OnEquip)
|
||
|
|
|
||
|
|
-- Test code
|
||
|
|
--RegisterPlayerEvent(18, function(e,p,m,t,l) if m == "test" then OnGossipHello(e,p,p) end end)
|
||
|
|
--RegisterPlayerGossipEvent(menu_id, 2, OnGossipSelect)
|
||
|
|
|
||
|
|
RegisterCreatureGossipEvent(NPC_Entry, 1, OnGossipHello)
|
||
|
|
RegisterCreatureGossipEvent(NPC_Entry, 2, OnGossipSelect)
|
||
|
|
|
||
|
|
local plrs = GetPlayersInWorld()
|
||
|
|
if plrs then
|
||
|
|
for k, player in ipairs(plrs) do
|
||
|
|
OnLogin(k, player)
|
||
|
|
end
|
||
|
|
end
|