diff options
author | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-07-05 14:28:58 +0200 |
---|---|---|
committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-07-05 14:28:58 +0200 |
commit | a508ce1976caaf8ede6afcea7e8a857399f548ef (patch) | |
tree | a74648a065e92da70251066a99ecda387a9fe1a2 /src | |
parent | 6d93a0a810c9d092797a5016738576d03005d1b7 (diff) | |
parent | d28b66bca88de621fd00495e4edc7e4d9d01e7eb (diff) |
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts:
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Globals/ObjectMgr.cpp
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 6 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 244 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 15 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 127 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_learn.cpp | 3 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/model.cpp | 21 |
14 files changed, 271 insertions, 195 deletions
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index e9cc810e11a..2ba5a236f95 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -393,8 +393,8 @@ enum MapFlags enum AbilytyLearnType { - ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, - ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 + SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE = 1, // Spell state will update depending on skill value + SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN = 2 // Spell will be learned/removed together with entire skill }; enum ItemEnchantmentType @@ -439,7 +439,7 @@ enum SkillRaceClassInfoFlags SKILL_FLAG_UNLEARNABLE = 0x20, // Skill can be unlearned SKILL_FLAG_INCLUDE_IN_SORT = 0x80, // Spells belonging to a skill with this flag will additionally compare skill ids when sorting spellbook in client SKILL_FLAG_NOT_TRAINABLE = 0x100, - SKILL_FLAG_MONO_VALUE = 0x400 // Skill always has value 1 + SKILL_FLAG_MONO_VALUE = 0x400 // Skill always has value 1 - clientside display flag, real value can be different }; enum SpellCategoryFlags diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index a16577cdf0e..09efd81a51b 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -601,7 +601,7 @@ void LoadDBCStores(const std::string& dataPath) if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; - if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) + if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; sPetFamilySpellsStore[i].insert(spellInfo->Id); diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index c4c078718f1..26a35457bc3 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1704,7 +1704,7 @@ struct SkillLineAbilityEntry //uint32 classmaskNot; // 6 m_excludeClass uint32 req_skill_value; // 7 m_minSkillLineRank uint32 forward_spellid; // 8 m_supercededBySpell - uint32 learnOnGetSkill; // 9 m_acquireMethod + uint32 AutolearnType; // 9 m_acquireMethod uint32 max_value; // 10 m_trivialSkillLineRankHigh uint32 min_value; // 11 m_trivialSkillLineRankLow uint32 character_points[2]; // 12-13 m_characterPoints diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index cb0b6dee782..ab9d7c40f7d 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1146,7 +1146,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) } // original spells - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); // original action bar for (PlayerCreateInfoActions::const_iterator action_itr = info->action.begin(); action_itr != info->action.end(); ++action_itr) @@ -3889,39 +3890,6 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value); } - else - { - // not ranked skills - for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx) - { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); - if (!pSkill) - continue; - - if (HasSkill(pSkill->id)) - continue; - - if (_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0)) - { - switch (GetSkillRangeType(pSkill, _spell_idx->second->racemask != 0)) - { - case SKILL_RANGE_LANGUAGE: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 300, 300); - break; - case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, GetMaxSkillValueForLevel()); - break; - case SKILL_RANGE_MONO: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, 1); - break; - default: - break; - } - } - } - } // learn dependent spells SpellLearnSpellMapBounds spell_bounds = sSpellMgr->GetSpellLearnSpellMapBounds(spellId); @@ -4150,31 +4118,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) } } } - else - { - // not ranked skills - SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spell_id); - - for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) - { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); - if (!pSkill) - continue; - - if ((_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL && - pSkill->categoryId != SKILL_CATEGORY_CLASS) ||// not unlearn class skills (spellbook/talent pages) - // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0)) - { - // not reset skills for professions and racial abilities - if ((pSkill->categoryId == SKILL_CATEGORY_SECONDARY || pSkill->categoryId == SKILL_CATEGORY_PROFESSION) && - (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0)) - continue; - - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0); - } - } - } // remove dependent spells SpellLearnSpellMapBounds spell_bounds = sSpellMgr->GetSpellLearnSpellMapBounds(spell_id); @@ -6058,9 +6001,6 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (!skill_id) return false; - if (skill_id == SKILL_FIST_WEAPONS) - skill_id = SKILL_UNARMED; - SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; @@ -6076,7 +6016,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (value < max) { - uint16 new_value = value + step; + uint32 new_value = value + step; if (new_value > max) new_value = max; @@ -6261,14 +6201,14 @@ void Player::UpdateSkillsForLevel() continue; uint32 pskill = itr->first; - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(pskill); - if (!pSkill) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass()); + if (!rcEntry) continue; - if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) + if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL) continue; - if (IsWeaponSkill(pSkill->id)) + if (IsWeaponSkill(rcEntry->SkillId)) continue; uint16 field = itr->second.pos / 2; @@ -6296,10 +6236,14 @@ void Player::UpdateSkillsToMaxSkillsForLevel() continue; uint32 pskill = itr->first; - if (IsProfessionOrRidingSkill(pskill)) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass()); + if (!rcEntry) + continue; + + if (IsProfessionOrRidingSkill(rcEntry->SkillId)) continue; - if (IsWeaponSkill(pskill)) + if (IsWeaponSkill(rcEntry->SkillId)) continue; uint16 field = itr->second.pos / 2; @@ -17784,7 +17728,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // after spell and quest load InitTalentForLevel(); - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); // must be before inventory (some items required reputation check) m_reputationMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_REPUTATION)); @@ -23648,15 +23593,19 @@ void Player::resetSpells(bool myClassOnly) for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) removeSpell(iter->first, false, false); // only iter->first can be accessed, object by iter->second can be deleted already - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); learnQuestRewardedSpells(); } -void Player::learnDefaultSpells() +void Player::LearnCustomSpells() { + if (!sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS)) + return; + // learn default race/class spells PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); - for (PlayerCreateInfoSpells::const_iterator itr = info->spell.begin(); itr != info->spell.end(); ++itr) + for (PlayerCreateInfoSpells::const_iterator itr = info->customSpells.begin(); itr != info->customSpells.end(); ++itr) { uint32 tspell = *itr; TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial spell, id = %u", uint32(getClass()), uint32(getRace()), tspell); @@ -23667,6 +23616,68 @@ void Player::learnDefaultSpells() } } +void Player::LearnDefaultSkills() +{ + // learn default race/class skills + PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); + for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr) + { + uint32 skillId = itr->SkillId; + if (HasSkill(skillId)) + continue; + + LearnDefaultSkill(skillId, itr->Rank); + } +} + +void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) +{ + SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(skillId, getRace(), getClass()); + if (!rcInfo) + return; + + TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial skill, id = %u", uint32(getClass()), uint32(getRace()), skillId); + switch (GetSkillRangeType(rcInfo)) + { + case SKILL_RANGE_LANGUAGE: + SetSkill(skillId, 0, 300, 300); + break; + case SKILL_RANGE_LEVEL: + { + uint16 skillValue = 1; + uint16 maxValue = GetMaxSkillValueForLevel(); + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + skillValue = maxValue; + else if (getClass() == CLASS_DEATH_KNIGHT) + skillValue = std::min(std::max<uint16>({ 1, uint16((getLevel() - 1) * 5) }), maxValue); + + SetSkill(skillId, 0, skillValue, maxValue); + break; + } + case SKILL_RANGE_MONO: + SetSkill(skillId, 0, 1, 1); + break; + case SKILL_RANGE_RANK: + { + if (!rank) + break; + + SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcInfo->SkillTier); + uint16 maxValue = tier->MaxSkill[std::max<int32>(rank - 1, 0)]; + uint16 skillValue = 1; + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + skillValue = maxValue; + else if (getClass() == CLASS_DEATH_KNIGHT) + skillValue = std::min(std::max<uint16>({ uint16(1), uint16((getLevel() - 1) * 5) }), maxValue); + + SetSkill(skillId, rank, skillValue, maxValue); + break; + } + default: + break; + } +} + void Player::learnQuestRewardedSpells(Quest const* quest) { int32 spell_id = quest->GetRewSpellCast(); @@ -23764,29 +23775,35 @@ void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value) { uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); - for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j) + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j); - if (!pAbility || pAbility->skillId != skill_id || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + if (!pAbility || pAbility->skillId != skill_id) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pAbility->spellId); + if (!spellInfo) + continue; + + if (pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; + // Check race if set if (pAbility->racemask && !(pAbility->racemask & raceMask)) continue; + // Check class if set if (pAbility->classmask && !(pAbility->classmask & classMask)) continue; - if (sSpellMgr->GetSpellInfo(pAbility->spellId)) - { - // need unlearn spell - if (skill_value < pAbility->req_skill_value) - removeSpell(pAbility->spellId); - // need learn - else if (!IsInWorld()) - addSpell(pAbility->spellId, true, true, true, false); - else - learnSpell(pAbility->spellId, true); - } + // need unlearn spell + if (skill_value < pAbility->req_skill_value && pAbility->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) + removeSpell(pAbility->spellId); + // need learn + else if (!IsInWorld()) + addSpell(pAbility->spellId, true, true, true, false); + else + learnSpell(pAbility->spellId, true); } } @@ -25517,15 +25534,15 @@ void Player::_LoadSkills(PreparedQueryResult result) uint16 value = fields[1].GetUInt16(); uint16 max = fields[2].GetUInt16(); - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill); - if (!pSkill) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skill, getRace(), getClass()); + if (!rcEntry) { TC_LOG_ERROR("entities.player", "Character %u has skill %u that does not exist.", GetGUIDLow(), skill); continue; } // set fixed skill ranges - switch (GetSkillRangeType(pSkill, false)) + switch (GetSkillRangeType(rcEntry)) { case SKILL_RANGE_LANGUAGE: // 300..300 value = max = 300; @@ -25533,9 +25550,12 @@ void Player::_LoadSkills(PreparedQueryResult result) case SKILL_RANGE_MONO: // 1..1, grey monolite bar value = max = 1; break; + case SKILL_RANGE_LEVEL: + max = GetMaxSkillValueForLevel(); default: break; } + if (value == 0) { TC_LOG_ERROR("entities.player", "Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill); @@ -25556,15 +25576,19 @@ void Player::_LoadSkills(PreparedQueryResult result) SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill); uint16 step = 0; - if (pSkill->categoryId == SKILL_CATEGORY_SECONDARY) - step = max / 75; - - if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(rcEntry->SkillId); + if (skillLine) { - step = max / 75; + if (skillLine->categoryId == SKILL_CATEGORY_SECONDARY) + step = max / 75; + + if (skillLine->categoryId == SKILL_CATEGORY_PROFESSION) + { + step = max / 75; - if (professionCount < 2) - SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + if (professionCount < 2) + SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + } } SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); @@ -25600,34 +25624,6 @@ void Player::_LoadSkills(PreparedQueryResult result) SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); } - - // special settings - if (getClass() == CLASS_DEATH_KNIGHT) - { - uint8 base_level = std::min(getLevel(), uint8(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL))); - if (base_level < 1) - base_level = 1; - uint16 base_skill = (base_level-1)*5; // 270 at starting level 55 - if (base_skill < 1) - base_skill = 1; // skill mast be known and then > 0 in any case - - if (GetPureSkillValue(SKILL_FIRST_AID) < base_skill) - SetSkill(SKILL_FIRST_AID, 4 /*artisan*/, base_skill, 300); - if (GetPureSkillValue(SKILL_AXES) < base_skill) - SetSkill(SKILL_AXES, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_DEFENSE) < base_skill) - SetSkill(SKILL_DEFENSE, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_POLEARMS) < base_skill) - SetSkill(SKILL_POLEARMS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_SWORDS) < base_skill) - SetSkill(SKILL_SWORDS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_2H_AXES) < base_skill) - SetSkill(SKILL_2H_AXES, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_2H_SWORDS) < base_skill) - SetSkill(SKILL_2H_SWORDS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_UNARMED) < base_skill) - SetSkill(SKILL_UNARMED, 0, base_skill, base_skill); - } } InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index f60cf38cbc8..243ba8e725f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -384,6 +384,14 @@ struct PlayerCreateInfoAction typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions; +struct PlayerCreateInfoSkill +{ + uint16 SkillId; + uint16 Rank; +}; + +typedef std::list<PlayerCreateInfoSkill> PlayerCreateInfoSkills; + struct PlayerInfo { // existence checked by displayId != 0 @@ -398,8 +406,9 @@ struct PlayerInfo uint16 displayId_m; uint16 displayId_f; PlayerCreateInfoItems item; - PlayerCreateInfoSpells spell; + PlayerCreateInfoSpells customSpells; PlayerCreateInfoActions action; + PlayerCreateInfoSkills skills; PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 }; @@ -1761,7 +1770,9 @@ class Player : public Unit, public GridObject<Player> void learnSpell(uint32 spell_id, bool dependent); void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true); void resetSpells(bool myClassOnly = false); - void learnDefaultSpells(); + void LearnCustomSpells(); + void LearnDefaultSkills(); + void LearnDefaultSkill(uint32 skillId, uint16 rank); void learnQuestRewardedSpells(); void learnQuestRewardedSpells(Quest const* quest); void learnSpellHighRank(uint32 spellid); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 1d8e8122e30..e41243e5337 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6668,7 +6668,8 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; // Try handle unknown trigger spells - if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL) + // triggered spells exists only in serverside spell_dbc + /// @todo: reverify and move these spells to spellscripts { switch (auraSpellInfo->SpellFamilyName) { @@ -13686,7 +13687,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) group->SendLooter(creature, NULL); // Update round robin looter only if the creature had loot - if (!creature->loot.empty()) + if (!loot->empty()) group->UpdateLooterGuid(creature); } } @@ -13793,7 +13794,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) creature->DeleteThreatList(); // must be after setDeathState which resets dynamic flags - if (!creature->loot.empty()) + if (!creature->loot.isLooted()) creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); else creature->AllLootRemovedFromCorpse(); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 068f9513268..72621865465 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3250,17 +3250,91 @@ void ObjectMgr::LoadPlayerInfo() } } + + // Load playercreate skills + TC_LOG_INFO("server.loading", "Loading Player Create Skill Data..."); + { + uint32 oldMSTime = getMSTime(); + + QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, skill, rank FROM playercreateinfo_skills"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty."); + } + else + { + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + uint32 raceMask = fields[0].GetUInt32(); + uint32 classMask = fields[1].GetUInt32(); + PlayerCreateInfoSkill skill; + skill.SkillId = fields[2].GetUInt16(); + skill.Rank = fields[3].GetUInt16(); + + if (skill.Rank >= MAX_SKILL_STEP) + { + TC_LOG_ERROR("sql.sql", "Skill rank value %hu set for skill %hu raceMask %u classMask %u is too high, max allowed value is %d", skill.Rank, skill.SkillId, raceMask, classMask, MAX_SKILL_STEP); + continue; + } + + if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) + { + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_skills` table, ignoring.", raceMask); + continue; + } + + if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) + { + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_skills` table, ignoring.", classMask); + continue; + } + + if (!sSkillLineStore.LookupEntry(skill.SkillId)) + { + TC_LOG_ERROR("sql.sql", "Wrong skill id %u in `playercreateinfo_skills` table, ignoring.", skill.SkillId); + continue; + } + + for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex) + { + if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask)) + { + for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex) + { + if (classMask == 0 || ((1 << (classIndex - 1)) & classMask)) + { + if (!GetSkillRaceClassInfo(skill.SkillId, raceIndex, classIndex)) + continue; + + if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) + { + info->skills.push_back(skill); + ++count; + } + } + } + } + } + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u player create skills in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + } + } + // Load playercreate spells TC_LOG_INFO("server.loading", "Loading Player Create Spell Data..."); { uint32 oldMSTime = getMSTime(); - std::string tableName = sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell"; - QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM %s", tableName.c_str()); + QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM playercreateinfo_spell_custom"); if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", tableName.c_str()); + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty."); } else { @@ -3275,13 +3349,13 @@ void ObjectMgr::LoadPlayerInfo() if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `%s` table, ignoring.", raceMask, tableName.c_str()); + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell_custom` table, ignoring.", raceMask); continue; } if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `%s` table, ignoring.", classMask, tableName.c_str()); + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell_custom` table, ignoring.", classMask); continue; } @@ -3295,7 +3369,7 @@ void ObjectMgr::LoadPlayerInfo() { if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) { - info->spell.push_back(spellId); + info->customSpells.push_back(spellId); ++count; } // We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them. @@ -3309,7 +3383,7 @@ void ObjectMgr::LoadPlayerInfo() } while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u custom player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } @@ -7847,34 +7921,27 @@ int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 rac return 0; } -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial) +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry) { - switch (pSkill->categoryId) + SkillLineEntry const* skill = sSkillLineStore.LookupEntry(rcEntry->SkillId); + if (!skill) + return SKILL_RANGE_NONE; + + if (sSkillTiersStore.LookupEntry(rcEntry->SkillTier)) + return SKILL_RANGE_RANK; + + if (rcEntry->SkillId == SKILL_RUNEFORGING) + return SKILL_RANGE_MONO; + + switch (skill->categoryId) { + case SKILL_CATEGORY_ARMOR: + return SKILL_RANGE_MONO; case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; - case SKILL_CATEGORY_WEAPON: - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_ARMOR: - case SKILL_CATEGORY_CLASS: - if (pSkill->id != SKILL_LOCKPICKING) - return SKILL_RANGE_MONO; - else - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_SECONDARY: - case SKILL_CATEGORY_PROFESSION: - // not set skills for professions and racial abilities - if (IsProfessionSkill(pSkill->id)) - return SKILL_RANGE_RANK; - else if (racial) - return SKILL_RANGE_NONE; - else - return SKILL_RANGE_MONO; - default: - case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) - return SKILL_RANGE_NONE; } + + return SKILL_RANGE_LEVEL; } void ObjectMgr::LoadGameTele() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 006bdfeaebf..a6e2ce9b067 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -670,7 +670,7 @@ enum SkillRangeType SKILL_RANGE_NONE // 0..0 always }; -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial); +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry); #define MAX_PLAYER_NAME 12 // max allowed by client name length #define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 56ae9061033..7a4d4904cc1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2271,7 +2271,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied //Spells with this flag cannot trigger if effect is cast on self - bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && CanExecuteTriggersOnHit(mask); + bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2); Unit* spellHitTarget = NULL; if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target @@ -2317,15 +2317,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (m_damage > 0) positive = false; else if (!m_healing) - { - for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) - // If at least one effect negative spell is negative hit - if (mask & (1<<i) && !m_spellInfo->IsPositiveEffect(i)) - { - positive = false; - break; - } - } + positive = m_spellInfo->IsPositive(); + switch (m_spellInfo->DmgClass) { case SPELL_DAMAGE_CLASS_MAGIC: @@ -2527,9 +2520,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA } } + uint8 aura_effmask = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect()) + aura_effmask |= 1 << i; + // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo, m_triggeredByAuraSpell); - if (m_diminishGroup) + if (m_diminishGroup && aura_effmask) { m_diminishLevel = unit->GetDiminishing(m_diminishGroup); DiminishingReturnsType type = GetDiminishingReturnsGroupType(m_diminishGroup); @@ -2540,11 +2538,6 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA unit->IncrDiminishing(m_diminishGroup); } - uint8 aura_effmask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect()) - aura_effmask |= 1 << i; - if (aura_effmask) { // Select rank for aura with level requirements only in specific cases diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index ebd0a269223..98ee85dce84 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -531,14 +531,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) } break; } - case SPELLFAMILY_MAGE: - { - // Deep Freeze should deal damage to permanently stun-immune targets. - if (m_spellInfo->Id == 71757) - if (unitTarget->GetTypeId() != TYPEID_UNIT || !(unitTarget->IsImmunedToSpellEffect(sSpellMgr->GetSpellInfo(44572), 0))) - return; - break; - } } if (m_originalCaster && damage > 0 && apply_direct_bonus) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 040f1df3cf5..d19c79cef41 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1130,7 +1130,7 @@ bool SpellInfo::IsAbilityLearnedWithProfession() const for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) { SkillLineAbilityEntry const* pAbility = _spell_idx->second; - if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + if (!pAbility || pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) continue; if (pAbility->req_skill_value > 0) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 09bb154106b..fa43176fd0b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2437,7 +2437,7 @@ void SpellMgr::LoadPetLevelupSpellMap() if (skillLine->skillId != creatureFamily->skillLine[j]) continue; - if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) + if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; SpellInfo const* spell = GetSpellInfo(skillLine->spellId); diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 41d740de3c2..3cb0d4c7d3f 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -332,7 +332,8 @@ public: if (!handler->extractPlayerTarget((char*)args, &target)) return false; - target->learnDefaultSpells(); + target->LearnDefaultSkills(); + target->LearnCustomSpells(); target->learnQuestRewardedSpells(); handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target).c_str()); diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 0f1bde7712d..692939cf288 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -98,8 +98,19 @@ bool Model::ConvertToVMAPModel(const char * outfilename) wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes; fwrite(&wsize, sizeof(int), 1, output); fwrite(&nIndexes, sizeof(uint32), 1, output); - if (nIndexes >0) + if (nIndexes > 0) + { + for (uint32 i = 0; i < nIndexes; ++i) + { + if ((i % 3) - 1 == 0 && i + 1 < nIndexes) + { + uint16 tmp = indices[i]; + indices[i] = indices[i + 1]; + indices[i + 1] = tmp; + } + } fwrite(indices, sizeof(unsigned short), nIndexes, output); + } fwrite("VERT", 4, 1, output); wsize = sizeof(int) + sizeof(float) * 3 * nVertices; @@ -107,8 +118,12 @@ bool Model::ConvertToVMAPModel(const char * outfilename) fwrite(&nVertices, sizeof(int), 1, output); if (nVertices >0) { - for(uint32 vpos=0; vpos <nVertices; ++vpos) - std::swap(vertices[vpos].y, vertices[vpos].z); + for (uint32 vpos = 0; vpos < nVertices; ++vpos) + { + float tmp = vertices[vpos].y; + vertices[vpos].y = -vertices[vpos].z; + vertices[vpos].z = tmp; + } fwrite(vertices, sizeof(float)*3, nVertices, output); } |