diff options
author | Ovalord <1Don7H4v3@m41L.com> | 2016-07-23 18:39:56 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-07-23 18:39:56 +0200 |
commit | 79aafd5865f11b5ecdd2865829562b981652db75 (patch) | |
tree | 73b19b280e4b153e8ba10e4f459421d0cc9f6712 /src | |
parent | 3b8cdd434133939cec1c7aaceb24fb7dc98000f9 (diff) |
Core/Players: Initial work on demon hunters
* Added starting level and required level config options as well as rbac permission to ignore the requirements
* Updated max power values for both demon hunter specs
* Fixed a crash during DK and DH creation
* Added playercreateinfo data for demon hunters
Closes #17651
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Accounts/RBAC.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 78 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 27 | ||||
-rw-r--r-- | src/server/game/World/World.h | 3 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_dh.cpp | 26 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_script_loader.cpp | 2 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 31 |
9 files changed, 169 insertions, 14 deletions
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 2b85d922657..28c8fc11e27 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -61,7 +61,7 @@ enum RBACPermissions // 9 - reuse RBAC_PERM_USE_CHARACTER_TEMPLATES = 10, RBAC_PERM_LOG_GM_TRADE = 11, - // 12 - reuse + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEMON_HUNTER = 12, RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13, RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14, RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15, diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 9873f90edbb..2c238fe4e60 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -482,9 +482,11 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); // set starting level - uint32 start_level = getClass() != CLASS_DEATH_KNIGHT - ? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL) - : sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + uint32 start_level = sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL); + if (getClass() == CLASS_DEATH_KNIGHT) + start_level = sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + else if (getClass() == CLASS_DEMON_HUNTER) + start_level = sWorld->getIntConfig(CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL); if (m_session->HasPermission(rbac::RBAC_PERM_USE_START_GM_LEVEL)) { @@ -11933,7 +11935,8 @@ void Player::VisualizeItem(uint8 slot, Item* pItem) if (pItem->GetTemplate()->GetBonding() == BIND_WHEN_EQUIPED || pItem->GetTemplate()->GetBonding() == BIND_WHEN_PICKED_UP || pItem->GetTemplate()->GetBonding() == BIND_QUEST_ITEM) { pItem->SetBinding(true); - GetSession()->GetCollectionMgr()->AddItemAppearance(pItem); + if (IsInWorld()) + GetSession()->GetCollectionMgr()->AddItemAppearance(pItem); } TC_LOG_DEBUG("entities.player.items", "Player::SetVisibleItemSlot: Player '%s' (%s), Slot: %u, Item: %u", @@ -26710,6 +26713,7 @@ uint32 Player::CalculateTalentsTiers() const break; case CLASS_DEMON_HUNTER: rowLevels = DHTalentRowLevels; + break; default: rowLevels = DefaultTalentRowLevels; break; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ea36658b786..1b67b78a5f1 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11090,12 +11090,14 @@ int32 Unit::GetCreatePowers(Powers power) const case POWER_MANA: return GetCreateMana(); case POWER_RAGE: + case POWER_PAIN: return 1000; case POWER_FOCUS: if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_HUNTER) return 100; return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100); case POWER_ENERGY: + case POWER_FURY: return 100; case POWER_COMBO_POINTS: return 5; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index abac1b283fb..044eb15dab7 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -264,10 +264,11 @@ bool LoginQueryHolder::Initialize() void WorldSession::HandleCharEnum(PreparedQueryResult result) { + uint8 demonHunterCount = 0; // We use this counter to allow multiple demon hunter creations when allowed in config + bool canAlwaysCreateDemonHunter = HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEMON_HUNTER); WorldPackets::Character::EnumCharactersResult charEnum; charEnum.Success = true; charEnum.IsDeletedCharacters = false; - charEnum.IsDemonHunterCreationAllowed = true; charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); _legitCharacters.clear(); @@ -303,8 +304,14 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) sWorld->AddCharacterInfo(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.Sex, charInfo.Race, charInfo.Class, charInfo.Level, false); if (charInfo.Class == CLASS_DEMON_HUNTER) + demonHunterCount++; + + if (demonHunterCount >= sWorld->getIntConfig(CONFIG_DEMON_HUNTERS_PER_REALM) && !canAlwaysCreateDemonHunter) charEnum.HasDemonHunterOnRealm = true; - if (charInfo.Level >= 70) + else + charEnum.HasDemonHunterOnRealm = false; + + if (charInfo.Level >= sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER) || canAlwaysCreateDemonHunter) charEnum.HasLevel70OnRealm = true; charEnum.Characters.emplace_back(charInfo); @@ -312,6 +319,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) while (result->NextRow()); } + charEnum.IsDemonHunterCreationAllowed = (!charEnum.HasDemonHunterOnRealm && charEnum.HasLevel70OnRealm); + SendPacket(charEnum.Write()); } @@ -580,11 +589,11 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac _charCreateCallback.FreeResult(); - if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) + if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO); stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1); + stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER) ? 12 : 1); _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); _charCreateCallback.NextStage(); return; @@ -598,15 +607,19 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac { bool haveSameRace = false; uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER); + uint32 demonHunterReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER); bool hasHeroicReqLevel = (heroicReqLevel == 0); + bool hasDemonHunterReqLevel = (demonHunterReqLevel == 0); bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION); uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS); bool checkHeroicReqs = createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER); + bool checkDemonHunterReqs = createInfo->Class == CLASS_DEMON_HUNTER && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEMON_HUNTER); if (result) { uint32 team = Player::TeamForRace(createInfo->Race); uint32 freeHeroicSlots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); + uint32 freeDemonHunterSlots = sWorld->getIntConfig(CONFIG_DEMON_HUNTERS_PER_REALM); Field* field = result->Fetch(); uint8 accRace = field[1].GetUInt8(); @@ -635,6 +648,30 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac } } + if (checkDemonHunterReqs) + { + uint8 accClass = field[2].GetUInt8(); + if (accClass == CLASS_DEMON_HUNTER) + { + if (freeDemonHunterSlots > 0) + --freeDemonHunterSlots; + + if (freeDemonHunterSlots == 0) + { + SendCharCreate(CHAR_CREATE_FAILED); + _charCreateCallback.Reset(); + return; + } + } + + if (!hasDemonHunterReqLevel) + { + uint8 accLevel = field[0].GetUInt8(); + if (accLevel >= demonHunterReqLevel) + hasDemonHunterReqLevel = true; + } + } + // need to check team only for first character /// @todo what to if account already has characters of both races? if (!allowTwoSideAccounts) @@ -653,7 +690,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac // search same race for cinematic or same class if need /// @todo check if cinematic already shown? (already logged in?; cinematic field) - while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT) + while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT || createInfo->Class == CLASS_DEMON_HUNTER) { if (!result->NextRow()) break; @@ -687,6 +724,30 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac hasHeroicReqLevel = true; } } + + if (checkDemonHunterReqs) + { + uint8 accClass = field[2].GetUInt8(); + if (accClass == CLASS_DEMON_HUNTER) + { + if (freeDemonHunterSlots > 0) + --freeDemonHunterSlots; + + if (freeDemonHunterSlots == 0) + { + SendCharCreate(CHAR_CREATE_FAILED); + _charCreateCallback.Reset(); + return; + } + } + + if (!hasDemonHunterReqLevel) + { + uint8 accLevel = field[0].GetUInt8(); + if (accLevel >= demonHunterReqLevel) + hasDemonHunterReqLevel = true; + } + } } } @@ -697,6 +758,13 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac return; } + if (checkDemonHunterReqs && !hasDemonHunterReqLevel) + { + SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT); + _charCreateCallback.Reset(); + return; + } + Player newChar(this); newChar.GetMotionMaster()->Initialize(); if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo)) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index e2c80f16ca8..8d0030849c9 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -808,14 +808,23 @@ void World::LoadConfigSettings(bool reload) } m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("HeroicCharactersPerRealm", 1); - if (int32(m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10) + if (int32(m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 12) { - TC_LOG_ERROR("server.loading", "HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.", m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]); + TC_LOG_ERROR("server.loading", "HeroicCharactersPerRealm (%i) must be in range 0..12. Set to 1.", m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]); m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1; } m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER] = sConfigMgr->GetIntDefault("CharacterCreating.MinLevelForHeroicCharacter", 55); + m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] = sConfigMgr->GetIntDefault("DemonHuntersPerRealm", 1); + if (int32(m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] > 12) + { + TC_LOG_ERROR("server.loading", "DemonHuntersPerRealm (%i) must be in range 0..12. Set to 1.", m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM]); + m_int_configs[CONFIG_DEMON_HUNTERS_PER_REALM] = 1; + } + + m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER] = sConfigMgr->GetIntDefault("CharacterCreating.MinLevelForDemonHunter", 70); + m_int_configs[CONFIG_SKIP_CINEMATICS] = sConfigMgr->GetIntDefault("SkipCinematics", 0); if (int32(m_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_int_configs[CONFIG_SKIP_CINEMATICS] > 2) { @@ -866,6 +875,20 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL]; } + m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("StartDemonHunterPlayerLevel", 98); + if (m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL] < 98) + { + TC_LOG_ERROR("server.loading", "StartDemonHunterPlayerLevel (%i) must be in range 98..MaxPlayerLevel(%u). Set to 98.", + m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL] = 98; + } + else if (m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL]) + { + TC_LOG_ERROR("server.loading", "StartDemonHunterPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", + m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_int_configs[CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL]; + } + m_int_configs[CONFIG_START_PLAYER_MONEY] = sConfigMgr->GetIntDefault("StartPlayerMoney", 0); if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0) { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 1851ffa6079..9b1b2ade6cb 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -242,11 +242,14 @@ enum WorldIntConfigs CONFIG_CHARACTERS_PER_REALM, CONFIG_HEROIC_CHARACTERS_PER_REALM, CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER, + CONFIG_DEMON_HUNTERS_PER_REALM, + CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEMON_HUNTER, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_MIN_DUALSPEC_LEVEL, CONFIG_START_PLAYER_LEVEL, CONFIG_START_HEROIC_PLAYER_LEVEL, + CONFIG_START_DEMON_HUNTER_PLAYER_LEVEL, CONFIG_START_PLAYER_MONEY, CONFIG_CURRENCY_START_APEXIS_CRYSTALS, CONFIG_CURRENCY_MAX_APEXIS_CRYSTALS, diff --git a/src/server/scripts/Spells/spell_dh.cpp b/src/server/scripts/Spells/spell_dh.cpp new file mode 100644 index 00000000000..3d36c446fa7 --- /dev/null +++ b/src/server/scripts/Spells/spell_dh.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Scripts for spells with SPELLFAMILY_DEMONHUNTER and SPELLFAMILY_GENERIC spells used by deathknight players. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_dh_". + */ + +void AddSC_demon_hunter_spell_scripts() +{ +} diff --git a/src/server/scripts/Spells/spell_script_loader.cpp b/src/server/scripts/Spells/spell_script_loader.cpp index c841c3b4ef8..167eb2b1da6 100644 --- a/src/server/scripts/Spells/spell_script_loader.cpp +++ b/src/server/scripts/Spells/spell_script_loader.cpp @@ -17,6 +17,7 @@ // This is where scripts' loading functions should be declared: void AddSC_deathknight_spell_scripts(); +void AddSC_demon_hunter_spell_scripts(); void AddSC_druid_spell_scripts(); void AddSC_generic_spell_scripts(); void AddSC_hunter_spell_scripts(); @@ -37,6 +38,7 @@ void AddSC_holiday_spell_scripts(); void AddSpellsScripts() { AddSC_deathknight_spell_scripts(); + AddSC_demon_hunter_spell_scripts(); AddSC_druid_spell_scripts(); AddSC_generic_spell_scripts(); AddSC_hunter_spell_scripts(); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 49ddb92df24..af8aeae4c91 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -668,7 +668,8 @@ DeclinedNames = 0 # Expansion # Description: Allow server to use content from expansions. Checks for expansion-related # map files, client compatibility and class/race character creation. -# Default: 5 - (Expansion 5) +# Default: 6 - (Expansion 6) +# 5 - (Expansion 5) # 4 - (Expansion 4) # 3 - (Expansion 3) # 2 - (Expansion 2) @@ -796,7 +797,7 @@ CharactersPerRealm = 12 # # HeroicCharactersPerRealm # Description: Limit number of heroic class characters per account on this realm. -# Range: 1-10 +# Range: 1-12 # Default: 1 HeroicCharactersPerRealm = 1 @@ -812,6 +813,24 @@ HeroicCharactersPerRealm = 1 CharacterCreating.MinLevelForHeroicCharacter = 55 # +# DemonHuntersPerRealm +# Description: Limit number of demon hunter characters per account on this realm. +# Range: 1-12 +# Default: 1 + +DemonHuntersPerRealm = 1 + +# +# CharacterCreating.MinLevelForDemonHunter +# Description: Limit creating demon hunters only for account with another +# character of specific level. +# Default: 70 - (Enabled, Requires at least another level 70 character) +# 0 - (Disabled) +# 1 - (Enabled, Requires at least another level 1 character) + +CharacterCreating.MinLevelForDemonHunter = 70 + +# # SkipCinematics # Description: Disable cinematic intro at first login after character creation. # Prevents buggy intros in case of custom start location coordinates. @@ -854,6 +873,14 @@ StartPlayerLevel = 1 StartHeroicPlayerLevel = 55 # +# StartDemonHunterPlayerLevel +# Description: Staring level for demon hunters after creation. +# Range: 98-MaxPlayerLevel +# Default: 98 + +StartDemonHunterPlayerLevel = 98 + +# # StartPlayerMoney # Description: Amount of money (in Copper) that a character has after creation. # Default: 0 |