关灯
开启左侧

古老的修改阵营,种族,外貌的M端代码

  [复制链接]
admin实名认证 发表于 2016-4-18 22:30:36 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 
diff --git a/src/game/Chat.cpp b/src/game/Chat.cppindex 449267f..b8ebd3b 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -505,6 +505,8 @@ ChatCommand * ChatHandler::getCommandTable()

         { "aura",           SEC_ADMINISTRATOR,  false, &ChatHandler::HandleAuraCommand,                "", NULL },
         { "unaura",         SEC_ADMINISTRATOR,  false, &ChatHandler::HandleUnAuraCommand,              "", NULL },
+        { "changerace",     SEC_ADMINISTRATOR,  false  &ChatHandler::HandleChangeRaceCommand,          "", NULL },
+        { "changeclass",    SEC_ADMINISTRATOR,  false  &ChatHandler::HandleChangeClassCommand,         "", NULL },
         { "announce",       SEC_MODERATOR,      true,  &ChatHandler::HandleAnnounceCommand,            "", NULL },
         { "notify",         SEC_MODERATOR,      true,  &ChatHandler::HandleNotifyCommand,              "", NULL },
         { "goname",         SEC_MODERATOR,      false, &ChatHandler::HandleGonameCommand,              "", NULL },
diff --git a/src/game/Chat.h b/src/game/Chat.h
index 12352f8..40c3ff4 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -413,6 +413,8 @@ class ChatHandler
         bool HandleWritePDumpCommand(const char *args);
         bool HandleCastCommand(const char *args);
         bool HandleCastBackCommand(const char *args);
+        bool HandleChangeRaceCommand(const char* args);
+        bool HandleChangeClassCommand(const char* args);
         bool HandleCastDistCommand(const char *args);
         bool HandleCastSelfCommand(const char *args);
         bool HandleCastTargetCommand(const char *args);
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 44f6262..9b1b365 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -6548,3 +6548,329 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)

     return true;
}
+
+void LoadTaxiMask(const char* data, TaxiMask& m_taximask)
+{
+    Tokens tokens = StrSplit(data, " ");
+
+    int index;
+    Tokens::iterator iter;
+    for (iter = tokens.begin(), index = 0;
+        (index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index)
+    {
+        // load and set bits only for existed taxi nodes
+        m_taximask[index] = sTaxiNodesMask[index] & uint32(atol((*iter).c_str()));
+    }
+}
+
+struct SkillLearnInfo {
+    SkillLearnInfo(uint16 skillId_, uint16 curValue_, uint16 maxValue_)
+        :skillId(skillId_), curValue(curValue_), maxValue(maxValue_){}
+    uint16 skillId;
+    uint16 curValue;
+    uint16 maxValue;
+};
+
+bool ChatHandler::HandleChangeRaceCommand(const char* args)
+{
+    // check parameters
+    if(!args)
+        return false;
+
+    // get char names
+    std::string nameFrom = strtok((char*)args, " ");
+    normalizePlayerName(nameFrom);
+
+    if(nameFrom.empty())
+        return false;
+    std::string nameTo = strtok(NULL, " ");
+    normalizePlayerName(nameTo);
+    if(nameTo.empty())
+        return false;
+
+    // check chars status
+    Player *chrFrom = objmgr.GetPlayer(nameFrom.data());
+    Player *chrTo = objmgr.GetPlayer(nameTo.data());
+    if (chrFrom || chrTo)
+    {
+        PSendSysMessage("Character's should be offline");
+        return true;
+    }
+
+    // get char guids by name
+    uint64 pfrom = objmgr.GetPlayerGUIDByName(nameFrom);
+    uint64 pto = objmgr.GetPlayerGUIDByName(nameTo);
+    if (!pfrom || !pto)
+    {
+        PSendSysMessage("Characters not found. Check names.");
+        return true;
+    }
+
+    // get class/race
+    QueryResult* result = sDatabase.PQuery("SELECT `race`, `class` FROM `character` WHERE `guid`=%u;", pfrom);
+    if(!result)
+    {
+        PSendSysMessage("Couldn't get race for first character");
+        return true;
+    }
+    Field* fields = result->Fetch();
+    uint32 raceFrom = fields[0].GetUInt32();
+    uint32 classFrom = fields[1].GetUInt32();
+    delete result;
+    result = sDatabase.PQuery("SELECT `race`, `class`, `taximask` FROM `character` WHERE `guid`=%u;", pto);
+    if(!result)
+    {
+        PSendSysMessage("Couldn't get race for second character");
+        return true;
+    }
+    fields = result->Fetch();
+    uint32 raceTo = fields[0].GetUInt32();
+    uint32 classTo = fields[1].GetUInt32();
+    TaxiMask taximask;
+    LoadTaxiMask(fields[2].GetString(), taximask);
+    delete result;
+
+    // check class
+    if (classFrom != classTo)
+    {
+        PSendSysMessage("Characters should be the same classes");
+        return true;
+    }
+
+    // change data fields
+    uint16 flags[] = { PLAYER_BYTES,
+        PLAYER_BYTES_3,
+        UNIT_FIELD_DISPLAYID,
+        UNIT_FIELD_NATIVEDISPLAYID,
+        UNIT_FIELD_FACTIONTEMPLATE,
+        UNIT_FIELD_BYTES_0,
+        0
+        };
+    Tokens tokens;
+    if(!Player::LoadValuesArrayFromDB(tokens, pto))
+        return false;
+    for (int i = 0; flags[i] != 0; i++) {
+        uint16 index = flags[i];
+        if(index >= tokens.size())
+            return false;
+        uint32 value = Player::GetUInt32ValueFromDB(index, pfrom);
+        char buf[11];
+        snprintf(buf,11, "%u", value);
+        tokens[index] = buf;
+    }
+    // save data about opened bank slot
+    uint32 value = Player::GetUInt32ValueFromDB(PLAYER_BYTES_2, pfrom);
+    uint32 bank = (uint32) atoi(tokens[PLAYER_BYTES_2].c_str());
+    Player::SetUInt32ValueInArray(tokens, PLAYER_BYTES_2, (value & ~0x70000) | (bank & 0x70000));
+   
+    // get class/race info
+    PlayerInfo const* infoFrom = objmgr.GetPlayerInfo(raceFrom, classFrom);
+    PlayerInfo const* infoTo = objmgr.GetPlayerInfo(raceTo, classFrom);
+    std::list<SkillLearnInfo> exclusiveFrom;
+    std::list<uint16> exclusiveTo;
+
+    // change spells
+    if (raceTo != raceFrom) {
+        // delete last race spells
+        std::ostringstream sssp;
+        sssp << "DELETE FROM `character_spell` WHERE `guid`=" << pto << " AND `spell` IN (";
+        for (std::list<CreateSpellPair>::const_iterator spell_itr = infoTo->spell.begin();
+            spell_itr != infoTo->spell.end(); ++spell_itr) {
+            uint16 spell_id = spell_itr->first;
+            sssp << spell_id << ", ";
+            ObjectMgr::SpellLearnSkillNode const* spellLearnSkill = objmgr.GetSpellLearnSkill(spell_id);
+            if (spellLearnSkill)exclusiveTo.push_back(spellLearnSkill->skill);
+        }
+        sssp << "0)";
+        sDatabase.PExecute(sssp.str().c_str());
+        // shift if need slot number
+        result = sDatabase.PQuery("SELECT MIN(`slot`) FROM `character_spell` WHERE `guid`=%u;", pto);
+        if(!result)
+        {
+            PSendSysMessage("Couldn't get min slot from character_spell");
+            return true;
+        }
+        fields = result->Fetch();
+        uint32 minSlotNumber = fields[0].GetUInt32();
+        if (infoFrom->spell.size() >= minSlotNumber)
+        { // shift slot number
+            uint32 count = infoFrom->spell.size() + 1 - fields[0].GetUInt32();
+            sDatabase.PExecute("UPDATE `character_spell` SET `slot`=`slot`+%u WHERE `guid`=%u", count, pto);
+        }
+        delete result;
+        // insert new spells
+        std::ostringstream ssspi;
+        ssspi << "INSERT INTO `character_spell` (`guid`, `spell`, `slot`, `active`) VALUES ";
+        std::list<CreateSpellPair>::const_iterator spell_itr = infoFrom->spell.begin();
+        int index = 1;
+        for (; index < infoFrom->spell.size(); ++spell_itr,  index++) {
+            uint16 spell_id = spell_itr->first;
+            ssspi << "(" << pto << ", " << spell_id << ", " << index << ", " << spell_itr->second << "),";
+            ObjectMgr::SpellLearnSkillNode const* spellLearnSkill = objmgr.GetSpellLearnSkill(spell_id);
+            if (spellLearnSkill)
+            {
+                uint32 skill_value = spellLearnSkill->value;
+                std::list<uint16>::iterator itr = find(exclusiveTo.begin(), exclusiveTo.end(), skill_value);
+                if (itr != exclusiveTo.end())
+                    exclusiveTo.erase(itr);
+                else {
+                    uint16 maxskill = 5 * Player::GetUInt32ValueFromArray(tokens, UNIT_FIELD_LEVEL);
+                    uint32 skill_max_value = spellLearnSkill->maxvalue == 0 ? maxskill : spellLearnSkill->maxvalue;
+                    exclusiveFrom.push_back(SkillLearnInfo(spellLearnSkill->skill, skill_value, skill_max_value));
+                }
+            }
+        }
+        ssspi << "(" << pto << ", " << spell_itr->first << ", " << index << ", " << spell_itr->second << ")";
+        sDatabase.PExecute(ssspi.str().c_str());
+
+        // change skills
+        const std::list<uint16>* skillsFrom = &(infoFrom->skill);
+        const std::list<uint16>* skillsTo = &(infoTo->skill);
+        for (std::list<uint16>::const_iterator itr = skillsFrom->begin(); itr != skillsFrom->end(); ++itr) {
+            uint16 value = (*itr);
+            if (std::find(skillsTo->begin(), skillsTo->end(), value) == skillsTo->end())
+                exclusiveFrom.push_back(SkillLearnInfo(value, 5, 5));
+        }
+        for (std::list<uint16>::const_iterator itr = skillsTo->begin(); itr != skillsTo->end(); ++itr) {
+            uint16 value = (*itr);
+            if (std::find(skillsFrom->begin(), skillsFrom->end(), value) == skillsFrom->end())
+                exclusiveTo.push_back(value);
+        }
+        for (int i = 0; i < PLAYER_MAX_SKILLS; i++) {
+            uint16 index = PLAYER_SKILL(i);
+            uint16 skillId = 0x0000FFFF & (uint32)atoi(tokens[index].c_str());
+            if (!skillId)
+            {
+                if (!exclusiveFrom.empty())
+                {
+                    std::list<SkillLearnInfo>::iterator itr = exclusiveFrom.begin();
+                    Player::SetUInt32ValueInArray(tokens, index, itr->skillId);
+                    Player::SetUInt32ValueInArray(tokens, index + 1, itr->maxValue*0x10000 + itr->curValue);
+                    tokens[index + 2] = "0";
+                    exclusiveFrom.erase(itr);
+                }
+                continue;
+            }
+            if (find(exclusiveTo.begin(), exclusiveTo.end(), skillId) != exclusiveTo.end())
+            { // change skill
+                if (exclusiveFrom.empty()) { // remove
+                    tokens[index] = "0";
+                    tokens[index + 1] = "0";
+                    tokens[index + 2] = "0";
+                } else { // replace
+                    std::list<SkillLearnInfo>::iterator itr = exclusiveFrom.begin();
+                    Player::SetUInt32ValueInArray(tokens, index, itr->skillId);
+                    Player::SetUInt32ValueInArray(tokens, index + 1, itr->maxValue*0x10000 + itr->curValue);
+                    tokens[index + 2] = "0";
+                    exclusiveFrom.erase(itr);
+                }
+            }
+        }
+    }
+    Player::SaveValuesArrayInDB(tokens, pto);
+    if (Player::TeamForRace(raceFrom) != Player::TeamForRace(raceTo))
+    {
+        // Taxi nodes setup
+        memset(taximask, 0, sizeof(taximask));
+        // capital and taxi hub masks
+        switch(raceFrom)
+        {
+            case 1:  taximask[0]= 1 << ( 2-1); break;         // Human
+            case 2:  taximask[0]= 1 << (23-1); break;         // Orc
+            case 3:  taximask[0]= 1 << ( 6-1); break;         // Dwarf
+                                                                // Night Elf
+            case 4:  taximask[0]= (1 << (26-1)) | (1 << (27-1)); break;
+            case 5:  taximask[0]= 1 << (11-1); break;         // Undead
+            case 6:  taximask[0]= 1 << (22-1); break;         // Tauren
+            case 7:  taximask[0]= 1 << ( 6-1); break;         // Gnome
+            case 8:  taximask[0]= 1 << (23-1); break;         // Troll
+            //case 10: m_taximask[0]= 1 << (1-1); break;        // Blood Elf
+            case 11: taximask[0+94/32]= 1 << (94%32-1); break;// Draenei
+        }
+        // new continent starting masks (It will be accessible only at new map
+        switch(Player::TeamForRace(raceFrom))
+        {
+            case ALLIANCE: taximask[3]= 1 << (4-1); break;
+            case HORDE:    taximask[3]= 1 << (3-1); break;
+        }
+    }
+    // save taximask
+    std::ostringstream sst;
+    sst << "UPDATE `character` SET `taximask`='";
+    for (int i = 0; i < 8; i++)
+        sst << taximask[i] << " ";
+    sst << "' WHERE `guid`=";
+    sst << pto;
+    sDatabase.Execute(sst.str().c_str());
+
+    if (raceFrom != raceTo)
+        sDatabase.PExecute("UPDATE `character` SET `race`=%u WHERE `guid`=%u", raceFrom, pto);
+    return true;
+}
+
+bool ChatHandler::HandleChangeClassCommand(const char* args)
+{
+    // check parameters
+    if(!args)
+        return false;
+
+    // get char names
+    std::string name = strtok((char*)args, " ");
+    normalizePlayerName(name);
+    if(name.empty())
+        return false;
+    // get class
+    std::string classNumStr = strtok(NULL, " ");
+    uint32 classDst = atoi(classNumStr.c_str());
+    if(classDst > 9 && classDst != 11)
+        return false;
+
+    // check chars status
+    Player *chr = objmgr.GetPlayer(name.data());
+    if (chr) {
+        PSendSysMessage("Character should be offline");
+        return true;
+    }
+
+    // get char guids by name
+    uint64 pguid = objmgr.GetPlayerGUIDByName(name);
+    if (!pguid) {
+        PSendSysMessage("Characters not found. Check names.");
+        return true;
+    }
+
+    // get class/race
+    QueryResult* result = sDatabase.PQuery("SELECT `race`, `class` FROM `character` WHERE `guid`=%u;", pguid);
+    if(!result) {
+        PSendSysMessage("Couldn't get race for character");
+        return true;
+    }
+    Field* fields = result->Fetch();
+    uint32 race = fields[0].GetUInt32();
+    uint32 classSrc = fields[1].GetUInt32();
+    delete result;
+
+    // check class
+    if (classSrc == classDst) {
+        PSendSysMessage("Nothing to change");
+        return true;
+    }
+
+    // change data fields
+    Tokens tokens;
+    if(!Player::LoadValuesArrayFromDB(tokens, pguid))
+    {
+        PSendSysMessage("Couldn't load data of character");
+        return true;
+    }
+    ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(classDst);
+    uint32 value = (uint32) atoi(tokens[UNIT_FIELD_BYTES_0].c_str());
+    value = (value & ~0xFF00FF00) | ((classDst << 8) & 0x0000FF00) | ((cEntry->powerType << 24) & 0xFF000000);
+    Player::SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, value);
+    Player::SaveValuesArrayInDB(tokens, pguid);
+    sDatabase.PExecute("UPDATE `character` SET `class`=%u, `at_login` = `at_login` | '%u' WHERE `guid`=%u",
+        classDst, uint32(AT_LOGIN_RESET_SPELLS | AT_LOGIN_RESET_TALENTS), pguid);
+
+    PSendSysMessage("Success");
+    return true;
+}
\ No newline at end of file

 
VIP介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 最佳新人

    注册账号后积极发帖的会员
  • 活跃会员

    经常参与各类话题的讨论,发帖内容较有主见
  • 热心会员

    经常帮助其他会员答疑
  • 推广达人

    积极宣传本站,为本站带来更多注册会员
  • 宣传达人

    积极宣传本站,为本站带来更多的用户访问量
  • 灌水之王

    经常在论坛发帖,且发帖量较大
  • 突出贡献

    长期对论坛的繁荣而不断努力,或多次提出建设性意见
  • 优秀版主

    活跃且尽责职守的版主
  • 荣誉管理

    曾经为论坛做出突出贡献目前已离职的版主
  • 论坛元老

    为论坛做出突出贡献的会员

0关注

5粉丝

3421帖子

排行榜
作者专栏

QQ交流群&&微信订阅号

QQ交流群

微信订阅号

吾爱尚玩资源基地永久域名:

Www.523Play.Com

在线管理员QQ:1589479632

邮箱:Email@523play.com

QQ交流群:558936238

Copyright   ©2015-2116  吾爱尚玩资源基地|523play.comPowered by©523Pplay.Com技术支持:吾爱尚玩资源基地