Skip to content

Instantly share code, notes, and snippets.

@Natureknight
Created December 22, 2015 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Natureknight/41ef2cf5d83e2c55684f to your computer and use it in GitHub Desktop.
Save Natureknight/41ef2cf5d83e2c55684f to your computer and use it in GitHub Desktop.
From e91cb611a8da376ee380b2629a814b3bd49f45a0 Mon Sep 17 00:00:00 2001
From: Natureknight <vallez8244@gmail.com>
Date: Tue, 22 Dec 2015 13:13:22 +0200
Subject: [PATCH] Implementation of feature which allows players to simply copy
gear or talents (or both) from another player ingame
---
sql/updates/custom/world/22_12_2015.sql | 4 +
src/server/game/Scripting/ScriptLoader.cpp | 2 +
src/server/scripts/Custom/copyGearCommands.cpp | 485 +++++++++++++++++++++++++
3 files changed, 491 insertions(+)
create mode 100644 sql/updates/custom/world/22_12_2015.sql
create mode 100644 src/server/scripts/Custom/copyGearCommands.cpp
diff --git a/sql/updates/custom/world/22_12_2015.sql b/sql/updates/custom/world/22_12_2015.sql
new file mode 100644
index 0000000..dc0a282
--- /dev/null
+++ b/sql/updates/custom/world/22_12_2015.sql
@@ -0,0 +1,4 @@
+INSERT INTO `command` (`name`, `security`, `help`) VALUES ('copy', 0, 'Syntax: .copy Gives a list of available subcommands for copying another player\'s gear/talents');
+INSERT INTO `command` (`name`, `security`, `help`) VALUES ('copy gear', 0, 'Syntax: .copy gear - Copies the gear of your target completely, including gems and enchants');
+INSERT INTO `command` (`name`, `security`, `help`) VALUES ('copy talents', 0, 'Syntax: .copy talents - Copies the talents and glyphs of your target');
+INSERT INTO `command` (`name`, `security`, `help`) VALUES ('copy all', 0, 'Syntax: .copy all - Copies the whole gear, talents, enchants, gems, glyphs of your target');
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 45644d1..65060cd 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -1259,6 +1259,7 @@ void AddBattlegroundScripts()
void AddSC_Arena_AntiDraw();
void AddSC_transmog_multivendor();
void AddSC_mount_launcher();
+ void AddSC_CopyGearCommands();
#endif
void AddCustomScripts()
@@ -1298,5 +1299,6 @@ void AddCustomScripts()
AddSC_Arena_AntiDraw();
AddSC_transmog_multivendor();
AddSC_mount_launcher();
+ AddSC_CopyGearCommands();
#endif
}
diff --git a/src/server/scripts/Custom/copyGearCommands.cpp b/src/server/scripts/Custom/copyGearCommands.cpp
new file mode 100644
index 0000000..9a10475
--- /dev/null
+++ b/src/server/scripts/Custom/copyGearCommands.cpp
@@ -0,0 +1,485 @@
+/////////////////////////////////////////////////////////////////////////////
+// ____ __ __ __ ___ //
+// / __ )____ _/ /_/ /_/ /__ / | ________ ____ ____ ______ //
+// / __ / __ `/ __/ __/ / _ \/ /| | / ___/ _ \/ __ \/ __ `/ ___/ //
+// / /_/ / /_/ / /_/ /_/ / __/ ___ |/ / / __/ / / / /_/ (__ ) //
+// /_____/\__,_/\__/\__/_/\___/_/ |_/_/ \___/_/ /_/\__,_/____/ //
+// Developed by Natureknight for BattleArenas.no-ip.org //
+// Copyright (C) 2015 Natureknight/JessiqueBA //
+// battlearenas.no-ip.org //
+/////////////////////////////////////////////////////////////////////////////
+
+#include "ScriptPCH.h"
+
+enum ArmorSpells
+{
+ PLATE_MAIL = 750,
+ ARMOR_MAIL = 8737
+};
+
+enum WeaponProficiencies
+{
+ BLOCK = 107,
+ BOWS = 264,
+ CROSSBOWS = 5011,
+ DAGGERS = 1180,
+ FIST_WEAPONS = 15590,
+ GUNS = 266,
+ ONE_H_AXES = 196,
+ ONE_H_MACES = 198,
+ ONE_H_SWORDS = 201,
+ POLEARMS = 200,
+ SHOOT = 5019,
+ STAVES = 227,
+ TWO_H_AXES = 197,
+ TWO_H_MACES = 199,
+ TWO_H_SWORDS = 202,
+ WANDS = 5009,
+ THROW_WAR = 2567
+};
+
+class CopyGearCommands : public CommandScript
+{
+public:
+ CopyGearCommands() : CommandScript("CopyGearCommands") { }
+
+ ChatCommand* GetCommands() const
+ {
+ static ChatCommand HandleCopyGearCommandTable[] =
+ {
+ { "gear", SEC_PLAYER, false, &HandleCopyGearCommand, "", NULL },
+ { "talents", SEC_PLAYER, false, &HandleCopyTalentsCommand, "", NULL },
+ { "all", SEC_PLAYER, false, &HandleCopyGearAndTalentsCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+
+ static ChatCommand commandTable[] =
+ {
+ { "copy", SEC_PLAYER, true, NULL, "", HandleCopyGearCommandTable },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+ return commandTable;
+ }
+
+ static bool HandleCopyGearCommand(ChatHandler* handler, const char* args)
+ {
+ std::string name;
+ Player* player = handler->GetSession()->GetPlayer();
+ Player* target;
+ char* targetName = strtok((char*)args, " "); // Get entered name
+
+ if (targetName)
+ {
+ name = targetName;
+ normalizePlayerName(name);
+ target = sObjectAccessor->FindPlayerByName(name.c_str());
+ }
+ else // If no name was entered - use target
+ {
+ target = handler->getSelectedPlayer();
+ if (target)
+ name = target->GetName();
+ }
+
+ if (target)
+ {
+ if (target == player)
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can't copy your own gear.");
+ return false;
+ }
+
+ // Restrict copying from the opposite faction
+ if (player->GetTeam() != target->GetTeam())
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can only copy talents from players thats in opposite faction.");
+ return false;
+ }
+
+ CopyGear(player, target);
+ handler->GetSession()->SendAreaTriggerMessage("Successfuly copied gear of %s",
+ target->GetName());
+
+ LearnPlateMailSpells(player);
+ player->UpdateSkillsForLevel();
+ LearnWeaponSkills(player);
+ player->SaveToDB();
+ return true;
+ }
+ else
+ player->GetSession()->SendAreaTriggerMessage("You must have a target.");
+
+ return true;
+ }
+
+ static bool HandleCopyTalentsCommand(ChatHandler* handler, const char* args)
+ {
+ std::string name;
+ Player* player = handler->GetSession()->GetPlayer();
+ Player* target;
+ char* targetName = strtok((char*)args, " "); // Get entered name
+
+ if (targetName)
+ {
+ name = targetName;
+ normalizePlayerName(name);
+ target = sObjectAccessor->FindPlayerByName(name.c_str());
+ }
+ else // If no name was entered - use target
+ {
+ target = handler->getSelectedPlayer();
+ if (target && target != player)
+ name = target->GetName();
+ else
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can't copy your own gear/talents.");
+ return false;
+ }
+ }
+
+ if (target)
+ {
+ if (target == player)
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can't copy your own talents.");
+ return false;
+ }
+
+ CopyTalents(player, target);
+ handler->GetSession()->SendAreaTriggerMessage("Successfuly copied talents of %s",
+ target->GetName());
+
+ player->UpdateSkillsForLevel();
+ player->SaveToDB();
+ return true;
+ }
+ else
+ player->GetSession()->SendAreaTriggerMessage("You must have a target.");
+
+ return true;
+ }
+
+ static bool HandleCopyGearAndTalentsCommand(ChatHandler* handler, const char* args)
+ {
+ std::string name;
+ Player* player = handler->GetSession()->GetPlayer();
+ Player* target;
+ char* targetName = strtok((char*)args, " "); // Get entered name
+
+ if (targetName)
+ {
+ name = targetName;
+ normalizePlayerName(name);
+ target = sObjectAccessor->FindPlayerByName(name.c_str());
+ }
+ else // If no name was entered - use target
+ {
+ target = handler->getSelectedPlayer();
+ if (target && target != player)
+ name = target->GetName();
+ else
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can't copy your own gear/talents.");
+ return false;
+ }
+ }
+
+ if (target)
+ {
+ if (target == player)
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can't copy your own gear/talents.");
+ return false;
+ }
+
+ // Restrict copying from the opposite faction
+ if (player->GetTeam() != target->GetTeam())
+ {
+ handler->GetSession()->SendAreaTriggerMessage("You can only copy talents from players thats in opposite faction.");
+ return false;
+ }
+
+ CopyGear(player, target);
+ CopyTalents(player, target);
+ handler->GetSession()->SendAreaTriggerMessage("Successfuly copied gear and talents of %s",
+ target->GetName());
+
+ LearnPlateMailSpells(player);
+ LearnWeaponSkills(player);
+ player->UpdateSkillsForLevel();
+ player->SaveToDB();
+ return true;
+ }
+ else
+ player->GetSession()->SendAreaTriggerMessage("You must have a target.");
+
+ return true;
+ }
+
+private:
+ static void ApplyBonus(Player* player, Item* item, EnchantmentSlot slot, uint32 bonusEntry)
+ {
+ if (!item)
+ return;
+
+ if (!bonusEntry || bonusEntry == 0)
+ return;
+
+ player->ApplyEnchantment(item, slot, false);
+ item->SetEnchantment(slot, bonusEntry, 0, 0);
+ player->ApplyEnchantment(item, slot, true);
+ }
+
+ // Get the gear from the selected player
+ static void CopyGear(Player* player, Player* target)
+ {
+ for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
+ {
+ // Delete previous items if equipped
+ player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true);
+
+ if (Item* equippedItem = target->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ {
+ // TODO: Implement checks for items here
+
+ player->EquipNewItem(i, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEntry(), true);
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ PERM_ENCHANTMENT_SLOT, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ SOCK_ENCHANTMENT_SLOT, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT));
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ SOCK_ENCHANTMENT_SLOT_2, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2));
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ SOCK_ENCHANTMENT_SLOT_3, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3));
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ BONUS_ENCHANTMENT_SLOT, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT));
+ ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, i),
+ PRISMATIC_ENCHANTMENT_SLOT, target->GetItemByPos(INVENTORY_SLOT_BAG_0, i)->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
+ }
+ }
+ }
+
+ static void CopyTalents(Player* player, Player* target)
+ {
+ // Reset current talents first
+ if (player->GetFreeTalentPoints() < 71)
+ {
+ player->resetTalents(true);
+ player->SendTalentsInfoData(false);
+ }
+
+ target->SaveToDB();
+
+ QueryResult result = CharacterDatabase.PQuery("SELECT spell FROM character_talent WHERE guid = '%u' "
+ "AND spec = '%u';", target->GetGUID(), target->GetActiveSpec());
+
+ if (!result)
+ {
+ player->GetSession()->SendAreaTriggerMessage("%s doesn't have any talents yet.",
+ target->GetName());
+ return;
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 spell = fields[0].GetUInt32();
+
+ player->learnSpell(spell, false);
+ player->AddTalent(spell, player->GetActiveSpec(), true);
+
+ } while (result->NextRow());
+
+
+ CopyGlyphs(player, target);
+ player->SetFreeTalentPoints(0);
+ player->SendTalentsInfoData(false);
+ }
+
+ static void CopyGlyphs(Player* player, Player* target)
+ {
+ QueryResult result = CharacterDatabase.PQuery("SELECT glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 "
+ "FROM character_glyphs WHERE guid = '%u' AND spec = '%u';", target->GetGUID(), target->GetActiveSpec());
+
+ for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
+ {
+ if (!result)
+ continue;
+
+ Field* fields = result->Fetch();
+ uint32 glyph1 = fields[0].GetUInt32();
+ uint32 glyph2 = fields[1].GetUInt32();
+ uint32 glyph3 = fields[2].GetUInt32();
+ uint32 glyph4 = fields[3].GetUInt32();
+ uint32 glyph5 = fields[4].GetUInt32();
+ uint32 glyph6 = fields[5].GetUInt32();
+
+ uint32 tempGlyph; // Temp
+
+ switch (slot)
+ {
+ case 0: tempGlyph = glyph1; break;
+ case 1: tempGlyph = glyph2; break;
+ case 2: tempGlyph = glyph3; break;
+ case 3: tempGlyph = glyph4; break;
+ case 4: tempGlyph = glyph5; break;
+ case 5: tempGlyph = glyph6; break;
+ default:
+ break;
+ }
+
+ if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(tempGlyph))
+ {
+ if (uint32 oldGlyph = player->GetGlyph(slot))
+ {
+ player->RemoveAurasDueToSpell(sGlyphPropertiesStore.LookupEntry(oldGlyph)->SpellId);
+ player->SetGlyph(slot, 0);
+ }
+ player->CastSpell(player, gp->SpellId, true);
+ player->SetGlyph(slot, tempGlyph);
+ }
+ }
+ }
+
+ static void LearnWeaponSkills(Player* player)
+ {
+ WeaponProficiencies wepSkills[] = {
+ BLOCK, BOWS, CROSSBOWS, DAGGERS, FIST_WEAPONS, GUNS, ONE_H_AXES, ONE_H_MACES,
+ ONE_H_SWORDS, POLEARMS, SHOOT, STAVES, TWO_H_AXES, TWO_H_MACES, TWO_H_SWORDS, WANDS, THROW_WAR
+ };
+
+ uint32 size = 17;
+
+ for (uint32 i = 0; i < size; ++i)
+ if (player->HasSpell(wepSkills[i]))
+ continue;
+
+ switch (player->getClass())
+ {
+ case CLASS_WARRIOR:
+ player->learnSpell(THROW_WAR, false);
+ player->learnSpell(TWO_H_SWORDS, false);
+ player->learnSpell(TWO_H_MACES, false);
+ player->learnSpell(TWO_H_AXES, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(POLEARMS, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(ONE_H_AXES, false);
+ player->learnSpell(GUNS, false);
+ player->learnSpell(FIST_WEAPONS, false);
+ player->learnSpell(DAGGERS, false);
+ player->learnSpell(CROSSBOWS, false);
+ player->learnSpell(BOWS, false);
+ player->learnSpell(BLOCK, false);
+ break;
+ case CLASS_PRIEST:
+ player->learnSpell(WANDS, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(SHOOT, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(DAGGERS, false);
+ break;
+ case CLASS_PALADIN:
+ player->learnSpell(TWO_H_SWORDS, false);
+ player->learnSpell(TWO_H_MACES, false);
+ player->learnSpell(TWO_H_AXES, false);
+ player->learnSpell(POLEARMS, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(ONE_H_AXES, false);
+ player->learnSpell(BLOCK, false);
+ break;
+ case CLASS_ROGUE:
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(ONE_H_AXES, false);
+ player->learnSpell(GUNS, false);
+ player->learnSpell(FIST_WEAPONS, false);
+ player->learnSpell(DAGGERS, false);
+ player->learnSpell(CROSSBOWS, false);
+ player->learnSpell(BOWS, false);
+ break;
+ case CLASS_DEATH_KNIGHT:
+ player->learnSpell(TWO_H_SWORDS, false);
+ player->learnSpell(TWO_H_MACES, false);
+ player->learnSpell(TWO_H_AXES, false);
+ player->learnSpell(POLEARMS, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(ONE_H_AXES, false);
+ break;
+ case CLASS_MAGE:
+ player->learnSpell(WANDS, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(SHOOT, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(DAGGERS, false);
+ break;
+ case CLASS_SHAMAN:
+ player->learnSpell(TWO_H_MACES, false);
+ player->learnSpell(TWO_H_AXES, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(ONE_H_AXES, false);
+ player->learnSpell(FIST_WEAPONS, false);
+ player->learnSpell(DAGGERS, false);
+ player->learnSpell(BLOCK, false);
+ break;
+ case CLASS_HUNTER:
+ player->learnSpell(THROW_WAR, false);
+ player->learnSpell(TWO_H_SWORDS, false);
+ player->learnSpell(TWO_H_AXES, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(POLEARMS, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(ONE_H_AXES, false);
+ player->learnSpell(GUNS, false);
+ player->learnSpell(FIST_WEAPONS, false);
+ player->learnSpell(DAGGERS, false);
+ player->learnSpell(CROSSBOWS, false);
+ player->learnSpell(BOWS, false);
+ break;
+ case CLASS_DRUID:
+ player->learnSpell(TWO_H_MACES, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(POLEARMS, false);
+ player->learnSpell(ONE_H_MACES, false);
+ player->learnSpell(FIST_WEAPONS, false);
+ player->learnSpell(DAGGERS, false);
+ break;
+ case CLASS_WARLOCK:
+ player->learnSpell(WANDS, false);
+ player->learnSpell(STAVES, false);
+ player->learnSpell(SHOOT, false);
+ player->learnSpell(ONE_H_SWORDS, false);
+ player->learnSpell(DAGGERS, false);
+ break;
+ default:
+ break;
+ }
+ }
+
+ static void LearnPlateMailSpells(Player* player)
+ {
+ switch (player->getClass())
+ {
+ case CLASS_WARRIOR:
+ case CLASS_PALADIN:
+ case CLASS_DEATH_KNIGHT:
+ player->learnSpell(PLATE_MAIL, true);
+ break;
+ case CLASS_SHAMAN:
+ case CLASS_HUNTER:
+ player->learnSpell(ARMOR_MAIL, true);
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+void AddSC_CopyGearCommands()
+{
+ new CopyGearCommands();
+}
\ No newline at end of file
--
2.1.1.1.g1fb337f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment