Логин:
Пароль:
 
 
Главная | Форум | Статьи | Фaйлы| Картинки WoW | Профиль | Регистрация | Вход

[ Новые сообщения · Правила форума · Поиск · RSS ]

WoW-Info — информационный World of Warcraft портал

Reforging - Форум

Страница 1 из 11
Форум » TrinityCore » Патчи в ядро Trinity » Reforging
Reforging
Infе[R]noSДата: Вторник, 15.07.2014, 14:39 | Сообщение # 1



Infе[R]noS
Скаут
Группа: Пользователи
Сообщений: 11

Замечания:

Оффлайн
Цитата
From 22e7789601c08c45f424f8c1f0959d963ee65198 Mon Sep 17 00:00:00 2001
From: LordPsyan <realmsofwarcraft@gmail.com>
Date: Sun, 29 Jun 2014 10:13:49 -0400
Subject: [PATCH] Reforging

---
.../Reforging/char_db_reforges.sql | 11 +
sql/TrinityCore-Patches/Reforging/reforger_npc.sql | 1 +
src/server/game/Entities/Item/ItemPrototype.h | 9 +-
src/server/game/Entities/Player/Player.cpp | 30 +-
src/server/game/Globals/ObjectMgr.h | 2 +
src/server/game/Scripting/ScriptLoader.cpp | 2 +
src/server/scripts/Custom/CMakeLists.txt | 4 +-
src/server/scripts/Custom/Reforging.cpp | 548 ++++++++++++++++++++
8 files changed, 603 insertions(+), 4 deletions(-)
create mode 100644 sql/TrinityCore-Patches/Reforging/char_db_reforges.sql
create mode 100644 sql/TrinityCore-Patches/Reforging/reforger_npc.sql
create mode 100644 src/server/scripts/Custom/Reforging.cpp

diff --git a/sql/TrinityCore-Patches/Reforging/char_db_reforges.sql b/sql/TrinityCore-Patches/Reforging/char_db_reforges.sql
new file mode 100644
index 0000000..0a7673f
--- /dev/null
+++ b/sql/TrinityCore-Patches/Reforging/char_db_reforges.sql
@@ -0,0 +1,11 @@
+CREATE TABLE `custom_reforges` (
+ `GUID` INT(10) UNSIGNED NOT NULL COMMENT 'item guid low',
+ `increase` INT(10) UNSIGNED NOT NULL COMMENT 'stat_type',
+ `decrease` INT(10) UNSIGNED NOT NULL COMMENT 'stat_type',
+ `stat_value` INT(10) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`GUID`)
+)
+COMMENT='version 0.1'
+COLLATE='latin1_swedish_ci'
+ENGINE=InnoDB
+ROW_FORMAT=COMPACT;
diff --git a/sql/TrinityCore-Patches/Reforging/reforger_npc.sql b/sql/TrinityCore-Patches/Reforging/reforger_npc.sql
new file mode 100644
index 0000000..64b2636
--- /dev/null
+++ b/sql/TrinityCore-Patches/Reforging/reforger_npc.sql
@@ -0,0 +1 @@
+INSERT INTO `creature_template` (`entry`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `dmg_multiplier`, `baseattacktime`, `rangeattacktime`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `minrangedmg`, `maxrangedmg`, `rangedattackpower`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `Health_mod`, `Mana_mod`, `Armor_mod`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES (190011, 20988, 0, 0, 0, 'Thaumaturge Vashreen', 'Arcane Reforger', NULL, 0, 80, 80, 2, 35, 1, 1, 1.14286, 1, 0, 500, 500, 0, 350, 1, 2000, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 138936390, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 'REFORGER_NPC', 0);
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index bdf956f..c10b378 100644
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -745,7 +745,14 @@ struct ItemTemplate

// Benchmarked: Faster than std::map (insert/find)
typedef std::unordered_map<uint32, ItemTemplate> ItemTemplateContainer;
-
+// Reforging
+struct FakeStatStruct
+{
+ uint32 increase, decrease;
+ int32 stat_value;
+};
+typedef std::unordered_map<uint32, FakeStatStruct> ItemFakeStatContainer; // custom
+// end Reforging
struct ItemLocale
{
StringVector Name;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8653106..628a232 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7819,6 +7819,20 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (only_level_scale && !ssv)
return;

+ uint32 statcount = proto->StatsCount;
+ uint32 lowGUID = 0;
+ bool decreased = false;
+ if (statcount < MAX_ITEM_PROTO_STATS)
+ {
+ if (Item* invItem = GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
+ {
+ if (sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
+ {
+ lowGUID = invItem->GetGUIDLow();
+ statcount++;
+ }
+ }
+ }
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
uint32 statType = 0;
@@ -7833,10 +7847,24 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
}
else
{
- if (i >= proto->StatsCount)
+ if (i >= statcount)
continue;
statType = proto->ItemStat[i].ItemStatType;
val = proto->ItemStat[i].ItemStatValue;
+
+ if (lowGUID)
+ {
+ if(i == statcount-1)
+ {
+ statType = sObjectMgr->_itemFakeStatStore[lowGUID].increase;
+ val = sObjectMgr->_itemFakeStatStore[lowGUID].stat_value;
+ }
+ else if(!decreased && sObjectMgr->_itemFakeStatStore[lowGUID].decrease == statType)
+ {
+ val -= sObjectMgr->_itemFakeStatStore[lowGUID].stat_value;
+ decreased = true;
+ }
+ }
}

if (val == 0)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e5e55b8..57336aa 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -1295,6 +1295,8 @@ class ObjectMgr

bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId); }

+ ItemFakeStatContainer _itemFakeStatStore; // custom
+
private:
// first free id for selected id type
uint32 _auctionId;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index f1359b7..b57f51d 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -1441,6 +1441,7 @@ void AddBattlegroundScripts()
#ifdef SCRIPTS
/* This is where custom scripts' loading functions should be declared. */

+void AddSC_REFORGER_NPC();
#endif

void AddCustomScripts()
@@ -1448,5 +1449,6 @@ void AddCustomScripts()
#ifdef SCRIPTS
/* This is where custom scripts should be added. */

+ AddSC_REFORGER_NPC();
#endif
}
diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt
index 80ebe36..20c2bc9 100644
--- a/src/server/scripts/Custom/CMakeLists.txt
+++ b/src/server/scripts/Custom/CMakeLists.txt
@@ -8,11 +8,11 @@
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

-# file(GLOB_RECURSE sources_Custom Custom/*.cpp Custom/*.h)
+file(GLOB_RECURSE sources_Custom Custom/*.cpp Custom/*.h)

set(scripts_STAT_SRCS
${scripts_STAT_SRCS}
-# ${sources_Custom}
+ ${sources_Custom}
)

message(" -> Prepared: Custom")
diff --git a/src/server/scripts/Custom/Reforging.cpp b/src/server/scripts/Custom/Reforging.cpp
new file mode 100644
index 0000000..fcd2bbd
--- /dev/null
+++ b/src/server/scripts/Custom/Reforging.cpp
@@ -0,0 +1,548 @@
+#include "ScriptPCH.h"
+
+static const bool send_cache_packets = true; // change player cache?
+
+// Remember to add to GetStatName too
+static const uint32 statTypes[] = { ITEM_MOD_SPIRIT, ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_HIT_RATING, ITEM_MOD_CRIT_RATING, ITEM_MOD_HASTE_RATING, ITEM_MOD_EXPERTISE_RATING };
+static const uint32 stat_type_max = sizeof(statTypes) / sizeof(*statTypes);
+
+typedef std::map<uint32, uint32> itemGuidMap;
+typedef std::unordered_map<uint32, itemGuidMap> playerItemMap;
+static playerItemMap playerItems; // playerItems[plrguid][itemguid] = entry;
+
+namespace
+{
+ static const char* GetStatName(uint32 ItemStatType)
+ {
+ switch(ItemStatType)
+ {
+ case ITEM_MOD_SPIRIT : return "Spirit"; break;
+ case ITEM_MOD_DODGE_RATING : return "Dodge rating"; break;
+ case ITEM_MOD_PARRY_RATING : return "Parry rating"; break;
+ case ITEM_MOD_HIT_RATING : return "Hit rating"; break;
+ case ITEM_MOD_CRIT_RATING : return "Crit rating"; break;
+ case ITEM_MOD_HASTE_RATING : return "Haste rating"; break;
+ case ITEM_MOD_EXPERTISE_RATING : return "Expertise rating"; break;
+ default: return NULL;
+ }
+ }
+
+ static const char* GetSlotName(uint8 slot, WorldSession* session)
+ {
+ switch (slot)
+ {
+ case EQUIPMENT_SLOT_HEAD : return "Head";
+ case EQUIPMENT_SLOT_SHOULDERS : return "Shoulders";
+ 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_BACK : return "Back";
+ case EQUIPMENT_SLOT_MAINHAND : return "Main hand";
+ case EQUIPMENT_SLOT_OFFHAND : return "Off hand";
+ case EQUIPMENT_SLOT_RANGED : return "Ranged";
+ default: return NULL;
+ }
+ }
+
+ static Item* GetEquippedItem(Player* player, uint32 guidlow)
+ {
+ for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
+ if (Item* pItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ if (pItem->GetGUIDLow() == guidlow)
+ return pItem;
+ return NULL;
+ }
+
+ static void RemoveReforgeSave(Player* player, uint32 itemguid, bool update, bool database);
+ static void SendReforgePacket(Player* player, uint32 entry, uint32 lowguid = 0)
+ {
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(entry);
+ FakeStatStruct* reforge = NULL;
+ if (lowguid)
+ {
+ if (sObjectMgr->_itemFakeStatStore.find(lowguid) != sObjectMgr->_itemFakeStatStore.end())
+ reforge = &sObjectMgr->_itemFakeStatStore[lowguid];
+ else
+ RemoveReforgeSave(player, lowguid, false, true);
+ }
+
+ // Update player cache (self only) pure visual.
+ // HandleItemQuerySingleOpcode copy paste
+ std::string Name = pProto->Name1;
+ std::string Description = pProto->Description;
+ int loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
+ if (loc_idx >= 0)
+ {
+ if (ItemLocale const* il = sObjectMgr->GetItemLocale(pProto->ItemId))
+ {
+ ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
+ ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
+ }
+ }
+ WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
+ data << pProto->ItemId;
+ data << pProto->Class;
+ data << pProto->SubClass;
+ data << pProto->SoundOverrideSubclass;
+ data << Name;
+ data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
+ data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
+ data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
+ data << pProto->DisplayInfoID;
+ data << pProto->Quality;
+ data << pProto->Flags;
+ data << pProto->Flags2;
+ data << pProto->BuyPrice;
+ data << pProto->SellPrice;
+ data << pProto->InventoryType;
+ data << pProto->AllowableClass;
+ data << pProto->AllowableRace;
+ data << pProto->ItemLevel;
+ data << pProto->RequiredLevel;
+ data << pProto->RequiredSkill;
+ data << pProto->RequiredSkillRank;
+ data << pProto->RequiredSpell;
+ data << pProto->RequiredHonorRank;
+ data << pProto->RequiredCityRank;
+ data << pProto->RequiredReputationFaction;
+ data << pProto->RequiredReputationRank;
+ data << int32(pProto->MaxCount);
+ data << int32(pProto->Stackable);
+ data << pProto->ContainerSlots;
+ data << pProto->StatsCount + (reforge ? 1 : 0); // increase stat count by 1
+ bool decreased = false;
+ for (uint32 i = 0; i < pProto->StatsCount; ++i)
+ {
+ data << pProto->ItemStat[i].ItemStatType;
+ if (reforge && !decreased && pProto->ItemStat[i].ItemStatType == reforge->decrease)
+ {
+ data << pProto->ItemStat[i].ItemStatValue-reforge->stat_value;
+ decreased = true;
+ }
+ else
+ data << pProto->ItemStat[i].ItemStatValue;
+ }
+ if (reforge)
+ {
+ data << reforge->increase; // set new stat type
+ data << reforge->stat_value; // and value
+ }
+ data << pProto->ScalingStatDistribution; // scaling stats distribution
+ data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column
+ for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
+ {
+ data << pProto->Damage[i].DamageMin;
+ data << pProto->Damage[i].DamageMax;
+ data << pProto->Damage[i].DamageType;
+ }
+
+ // resistances (7)
+ data << pProto->Armor;
+ data << pProto->HolyRes;
+ data << pProto->FireRes;
+ data << pProto->NatureRes;
+ data << pProto->FrostRes;
+ data << pProto->ShadowRes;
+ data << pProto->ArcaneRes;
+
+ data << pProto->Delay;
+ data << pProto->AmmoType;
+ data << pProto->RangedModRange;
+
+ for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
+ {
+ // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
+ // use `item_template` or if not set then only use spell cooldowns
+ SpellInfo const* spell = sSpellMgr->GetSpellInfo(pProto->Spells[s].SpellId);
+ if (spell)
+ {
+ bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
+
+ data << pProto->Spells[s].SpellId;
+ data << pProto->Spells[s].SpellTrigger;
+ data << uint32(-abs(pProto->Spells[s].SpellCharges));
+
+ if (db_data)
+ {
+ data << uint32(pProto->Spells[s].SpellCooldown);
+ data << uint32(pProto->Spells[s].SpellCategory);
+ data << uint32(pProto->Spells[s].SpellCategoryCooldown);
+ }
+ else
+ {
+ data << uint32(spell->RecoveryTime);
+ data << uint32(spell->GetCategory());
+ data << uint32(spell->CategoryRecoveryTime);
+ }
+ }
+ else
+ {
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(0);
+ data << uint32(-1);
+ data << uint32(0);
+ data << uint32(-1);
+ }
+ }
+ data << pProto->Bonding;
+ data << Description;
+ data << pProto->PageText;
+ data << pProto->LanguageID;
+ data << pProto->PageMaterial;
+ data << pProto->StartQuest;
+ data << pProto->LockID;
+ data << int32(pProto->Material);
+ data << pProto->Sheath;
+ data << pProto->RandomProperty;
+ data << pProto->RandomSuffix;
+ data << pProto->Block;
+ data << pProto->ItemSet;
+ data << pProto->MaxDurability;
+ data << pProto->Area;
+ data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch
+ data << pProto->BagFamily;
+ data << pProto->TotemCategory;
+ for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
+ {
+ data << pProto->Socket[s].Color;
+ data << pProto->Socket[s].Content;
+ }
+ data << pProto->socketBonus;
+ data << pProto->GemProperties;
+ data << pProto->RequiredDisenchantSkill;
+ data << pProto->ArmorDamageModifier;
+ data << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
+ data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
+ data << pProto->HolidayId; // Holiday.dbc?
+ player->GetSession()->SendPacket(&data);
+ }
+
+ static void SendReforgePackets(Player* player)
+ {
+ if (!send_cache_packets)
+ return;
+ if (playerItems.find(player->GetGUIDLow()) == playerItems.end())
+ return;
+ for (itemGuidMap::const_iterator it = playerItems[player->GetGUIDLow()].begin(); it != playerItems[player->GetGUIDLow()].end();)
+ {
+ itemGuidMap::const_iterator old_it = it++;
+ SendReforgePacket(player, old_it->second, old_it->first);
+ }
+ }
+
+ static void RemoveReforgeSave(Player* player, uint32 itemguid, bool update, bool database)
+ {
+ uint32 lowguid = player->GetGUIDLow();
+ Item* invItem = update ? player->GetItemByGuid(MAKE_NEW_GUID(itemguid, 0, HIGHGUID_ITEM)) : NULL;
+ if (invItem)
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), false);
+ if (playerItems.find(lowguid) != playerItems.end())
+ playerItems[lowguid].erase(itemguid);
+ sObjectMgr->_itemFakeStatStore.erase(itemguid);
+ if (invItem)
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), true);
+
+ if (!database)
+ return;
+ CharacterDatabase.PExecute("DELETE FROM `custom_reforges` WHERE `GUID` = %u", itemguid);
+ if (invItem)
+ SendReforgePacket(player, invItem->GetEntry());
+ player->SaveToDB();
+ }
+
+ static bool IsReforgable(Item* invItem, Player* player)
+ {
+ /*if (!invItem->IsEquipped())
+ return false;*/
+ if (invItem->GetOwnerGUID() != player->GetGUID())
+ return false;
+ const ItemTemplate* pProto = invItem->GetTemplate();
+ //if (pProto->ItemLevel < 200) // WOTLK items have less itemlevel than CATA
+ // return false;
+ if (pProto->Quality == ITEM_QUALITY_HEIRLOOM) // block heirlooms necessary? probably.
+ return false;
+ if (!pProto->StatsCount || pProto->StatsCount >= MAX_ITEM_PROTO_STATS)
+ return false;
+ if (sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
+ return false;
+ for (uint32 i = 0; i < pProto->StatsCount; ++i)
+ {
+ if (!GetStatName(pProto->ItemStat[i].ItemStatType))
+ continue;
+ if (((int32)floorf((float)pProto->ItemStat[i].ItemStatValue * 0.4f)) > 1)
+ return true;
+ }
+ return false;
+ }
+
+ static void UpdatePlayerReforgeStats(Item* invItem, Player* player, uint32 decrease, uint32 increase) // stat types
+ {
+ const ItemTemplate* pProto = invItem->GetTemplate();
+
+ int32 stat_diff = 0;
+ for (uint32 i = 0; i < pProto->StatsCount; i++)
+ {
+ if (pProto->ItemStat[i].ItemStatType == increase)
+ return; // Should not have the increased stat already
+ if (pProto->ItemStat[i].ItemStatType == decrease)
+ stat_diff = (int32)floorf((float)pProto->ItemStat[i].ItemStatValue * 0.4f);
+ }
+ if (stat_diff <= 0)
+ return; // Should have some kind of diff
+
+ // Update player stats
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), false);
+ uint32 guidlow = invItem->GetGUIDLow();
+ sObjectMgr->_itemFakeStatStore[guidlow].increase = increase;
+ sObjectMgr->_itemFakeStatStore[guidlow].decrease = decrease;
+ sObjectMgr->_itemFakeStatStore[guidlow].stat_value = stat_diff;
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), true);
+ CharacterDatabase.PExecute("REPLACE INTO `custom_reforges` (`GUID`, `increase`, `decrease`, `stat_value`) VALUES (%u, %u, %u, %i)", guidlow, increase, decrease, stat_diff);
+ player->ModifyMoney(pProto->SellPrice < (10*GOLD) ? (-10*GOLD) : -(int32)pProto->SellPrice);
+ SendReforgePacket(player, invItem->GetEntry(), guidlow);
+ player->SaveToDB();
+ }
+}
+
+class REFORGE_PLAYER : public PlayerScript
+{
+public:
+ REFORGE_PLAYER() : PlayerScript("REFORGE_PLAYER")
+ {
+ CharacterDatabase.Execute("DELETE FROM `custom_reforges` WHERE NOT EXISTS (SELECT 1 FROM `item_instance` WHERE `item_instance`.`guid` = `custom_reforges`.`GUID`)");
+ }
+
+ class SendRefPackLogin : public BasicEvent
+ {
+ public:
+ SendRefPackLogin(Player* _player) : player(_player)
+ {
+ _player->m_Events.AddEvent(this, _player->m_Events.CalculateTime(1000));
+ }
+
+ bool Execute(uint64, uint32)
+ {
+ SendReforgePackets(player);
+ return true;
+ }
+ Player* player;
+ };
+
+ void OnLogin(Player* player)
+ {
+ uint32 playerGUID = player->GetGUIDLow();
+ QueryResult result = CharacterDatabase.PQuery("SELECT custom_reforges.`GUID`, `increase`, `decrease`, `stat_value`, item_instance.itementry FROM `custom_reforges`, item_instance WHERE item_instance.`owner_guid` = %u and item_instance.`guid` = custom_reforges.GUID", playerGUID);
+ if (result)
+ {
+ do
+ {
+ uint32 lowGUID = (*result)[0].GetUInt32();
+ uint32 entry = (*result)[4].GetUInt32();
+ Item* invItem = player->GetItemByGuid(MAKE_NEW_GUID(lowGUID, 0, HIGHGUID_ITEM));
+ if (invItem)
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), false);
+ sObjectMgr->_itemFakeStatStore[lowGUID].increase = (*result)[1].GetUInt32();
+ sObjectMgr->_itemFakeStatStore[lowGUID].decrease = (*result)[2].GetUInt32();
+ sObjectMgr->_itemFakeStatStore[lowGUID].stat_value = (*result)[3].GetInt32();
+ playerItems[playerGUID][lowGUID] = entry;
+ if (invItem)
+ player->_ApplyItemMods(invItem, invItem->GetSlot(), true);
+ // SendReforgePacket(player, entry, lowGUID);
+ } while (result->NextRow());
+
+ // SendReforgePackets(player);
+ new SendRefPackLogin(player);
+ }
+ }
+
+ void OnLogout(Player* player)
+ {
+ if (playerItems.find(player->GetGUIDLow()) == playerItems.end())
+ return;
+ for (itemGuidMap::const_iterator it = playerItems[player->GetGUIDLow()].begin(); it != playerItems[player->GetGUIDLow()].end();)
+ {
+ itemGuidMap::const_iterator old_it = it++;
+ RemoveReforgeSave(player, old_it->first, false, false);
+ }
+ }
+};
+
+class REFORGER_NPC : public CreatureScript
+{
+public:
+ REFORGER_NPC() : CreatureScript("REFORGER_NPC") { }
+
+ bool OnGossipHello(Player* player, Creature* creature)
+ {
+ selectedItem.erase(player->GetGUIDLow());
+
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select slot of the item to reforge:", 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 (const char* slotname = GetSlotName(slot, player->GetSession()))
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, slotname, SELECT_STAT_REDUCE, slot);
+ }
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Remove reforges", SELECT_RESTORE, 0);
+ 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 MAIN_MENU: OnGossipHello(player, creature); break;
+ case SELECT_STAT_REDUCE:
+ // action = slot
+ if (Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action))
+ {
+ if (IsReforgable(invItem, player))
+ {
+ selectedItem[player->GetGUIDLow()] = invItem->GetGUIDLow();
+ const ItemTemplate* pProto = invItem->GetTemplate();
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Stat to decrease:", sender, action);
+ for (uint32 i = 0; i < pProto->StatsCount; ++i)
+ {
+ int32 stat_diff = ((int32)floorf((float)pProto->ItemStat[i].ItemStatValue * 0.4f));
+ if (stat_diff > 1)
+ if (const char* stat_name = GetStatName(pProto->ItemStat[i].ItemStatType))
+ {
+ std::ostringstream oss;
+ oss << stat_name << " (" << pProto->ItemStat[i].ItemStatValue << " |cFFDB2222-" << stat_diff << "|r)";
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, oss.str(), SELECT_STAT_INCREASE, 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("Invalid item selected");
+ OnGossipHello(player, creature);
+ }
+ }
+ else
+ {
+ player->GetSession()->SendNotification("Invalid item selected");
+ OnGossipHello(player, creature);
+ }
+ break;
+ case SELECT_STAT_INCREASE:
+ // action = StatsCount id
+ {
+ Item* invItem = GetEquippedItem(player, selectedItem[player->GetGUIDLow()]);
+ if (invItem)
+ {
+ const ItemTemplate* pProto = invItem->GetTemplate();
+ int32 stat_diff = ((int32)floorf((float)pProto->ItemStat[action].ItemStatValue * 0.4f));
+
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Stat to increase:", sender, action);
+ for (uint32 i = 0; i < stat_type_max; ++i)
+ {
+ bool cont = false;
+ for (uint32 j = 0; j < pProto->StatsCount; ++j)
+ {
+ if (statTypes[i] == pProto->ItemStat[j].ItemStatType) // skip existing stats on item
+ {
+ cont = true;
+ break;
+ }
+ }
+ if (cont)
+ continue;
+ if (const char* stat_name = GetStatName(statTypes[i]))
+ {
+ std::ostringstream oss;
+ oss << stat_name << " |cFF3ECB3C+" << stat_diff << "|r";
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, oss.str(), pProto->ItemStat[action].ItemStatType, statTypes[i], "Are you sure you want to reforge\n\n"+pProto->Name1, (pProto->SellPrice < (10*GOLD) ? (10*GOLD) : pProto->SellPrice), false);
+ }
+ }
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", SELECT_STAT_REDUCE, invItem->GetSlot());
+ player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
+ }
+ else
+ {
+ player->GetSession()->SendNotification("Invalid item selected");
+ OnGossipHello(player, creature);
+ }
+ }
+ break;
+ case SELECT_RESTORE:
+ {
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Select slot to remove reforge from:", sender, action);
+ for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; slot++)
+ {
+ if (Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
+ if (sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
+ if (const char* slotname = GetSlotName(slot, player->GetSession()))
+ player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, slotname, RESTORE, slot, "Really remove reforge from\n\n"+std::string(slotname), 0, false);
+ }
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Update menu", sender, action);
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, "Back..", MAIN_MENU, 0);
+ player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
+ }
+ break;
+ case RESTORE:
+ // action = slot
+ {
+ if (Item* invItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, action))
+ {
+ if (sObjectMgr->_itemFakeStatStore.find(invItem->GetGUIDLow()) != sObjectMgr->_itemFakeStatStore.end())
+ RemoveReforgeSave(player, invItem->GetGUIDLow(), true, true);
+ }
+ OnGossipHello(player, creature);
+ }
+ break;
+ default: // Reforge
+ // sender = stat type to decrease, action = stat type to increase
+ {
+ Item* invItem = GetEquippedItem(player, selectedItem[player->GetGUIDLow()]);
+ if (invItem && IsReforgable(invItem, player))
+ {
+ if (player->HasEnoughMoney(invItem->GetTemplate()->SellPrice < (10*GOLD) ? (10*GOLD) : invItem->GetTemplate()->SellPrice))
+ {
+ // int32 stat_diff = ((int32)floorf((float)invItem->GetTemplate()->ItemStat[action].ItemStatValue * 0.4f));
+ UpdatePlayerReforgeStats(invItem, player, sender, action); // rewrite this function
+ }
+ else
+ player->GetSession()->SendNotification("Not enough money");
+ }
+ else
+ player->GetSession()->SendNotification("Invalid item selected");
+ OnGossipHello(player, creature);
+ }
+ }
+ return true;
+ }
+
+ enum Senders
+ {
+ MAIN_MENU = 100,
+ SELECT_ITEM,
+ SELECT_STAT_REDUCE,
+ SELECT_STAT_INCREASE,
+ SELECT_RESTORE,
+ RESTORE,
+ REFORGE,
+ };
+
+private:
+
+ std::unordered_map<uint32, uint32> selectedItem;
+};
+
+void AddSC_REFORGER_NPC()
+{
+ new REFORGER_NPC;
+ new REFORGE_PLAYER;
+}
+
+#undef FOR_REFORGE_ITEMS
--
1.7.10.4


Skype - infernos-5

Сообщение отредактировал Infе[R]noS - Вторник, 15.07.2014, 14:39
 
Форум » TrinityCore » Патчи в ядро Trinity » Reforging
Страница 1 из 11
Поиск:

Новые сообщения в темах
Вопрос · (Wow Shop)
Автор: INFЕRNO
Последнее сообщение в 06:19
[FAQ]вопрос ответ · ([TrinityCore] Help)
Автор: MaeStroVIP
Последнее сообщение в 18:22
CCReport · (Проверенные аддоны для WoW)
Автор: Darkensand
Последнее сообщение в 20:21
Cорок неизвестных фактов из ис... · (Истории WoW)
Автор: R_a_Z_o_R
Последнее сообщение в 13:03
баг с голдом · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 13:48
Фарм СА(силы артефакта) и леге... · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 13:00
Новейший баг на дамаг ханта · (Баги WoW)
Автор: Act1mel
Последнее сообщение в 15:57
Циркуль магазин в ЛК опять отл... · (Баги WoW)
Автор: ADRE[N]ALINE
Последнее сообщение в 15:57
Баг на хонор(РАБОЧИЙ) · (Баги WoW)
Автор: Poltorushka
Последнее сообщение в 15:56
Положить сервер за пару минут · (Баги WoW)
Автор: CoBa
Последнее сообщение в 15:56
Баг на фарм очков доблести / 4... · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 15:56
Фарм голдов (3.3.5а) · (Баги WoW)
Автор: imfamous
Последнее сообщение в 15:56
Баг на бесплатную смену имени ... · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 15:45
:: Фармим хонор :: (почти любо... · (Баги WoW)
Автор: ADRE[N]ALINE
Последнее сообщение в 15:24
Баг на Дк WowCircl 4.0.6 · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 15:24
Баг на ледянные баджи на uwow · (Баги WoW)
Автор: Darkensand
Последнее сообщение в 15:24

Контакты Контакты Copyright WoW-Info — World of Warcraft портал © 2017 | Условия и правила использования ресурса | Реклама / Услуги
WoW-Info портал.World of Warcraft портал — готовые сервера, сайты, картинки, аддоны, патчи, читы, баги, mangos, ArcEmu, TrinityCore, Warcraft 3, новости, Cataclysm...
Яндекс.Метрика Создать бесплатный сайт с uCoz