diff --git a/modules/mod-Forge/sql/world/updates/20231106 starter talents.sql b/modules/mod-Forge/sql/world/updates/20231106 starter talents.sql
index a29440b63e7f42..68d04b904c93de 100644
--- a/modules/mod-Forge/sql/world/updates/20231106 starter talents.sql
+++ b/modules/mod-Forge/sql/world/updates/20231106 starter talents.sql
@@ -1,16 +1,8 @@
-drop table if exists `acore_world`.`forge_character_spec_strarter_talents`;
-CREATE TABLE `acore_world`.`forge_character_spec_strarter_talents` (
- `class` INT(10) UNSIGNED NOT NULL,
- `tab` INT(10) UNSIGNED NOT NULL,
- `spell` INT(10) UNSIGNED NOT NULL,
- PRIMARY KEY (`class`,`tab`,`spell`)
-) COLLATE='utf8_general_ci' ENGINE=InnoDB;
-
drop table if exists `acore_world`.`forge_character_spec_spells`;
CREATE TABLE `acore_world`.`forge_character_spec_spells` (
`class` INT(10) UNSIGNED NOT NULL,
- `tab` INT(10) UNSIGNED NOT NULL,
+ `race` INT(10) UNSIGNED NOT NULL,
`level` INT(10) UNSIGNED NOT NULL,
`spell` INT(10) UNSIGNED NOT NULL,
- PRIMARY KEY (`class`,`tab`,`spell`)
+ PRIMARY KEY (`class`, `race`,`spell`)
) COLLATE='utf8_general_ci' ENGINE=InnoDB;
\ No newline at end of file
diff --git a/modules/mod-Forge/src/ForgeCache.cpp b/modules/mod-Forge/src/ForgeCache.cpp
index e78a4dcb7156fb..771018ebd86407 100644
--- a/modules/mod-Forge/src/ForgeCache.cpp
+++ b/modules/mod-Forge/src/ForgeCache.cpp
@@ -891,8 +891,7 @@ class ForgeCache : public DatabaseScript
return 0;
}
- std::unordered_map>>> _levelClassSpellMap;
- std::unordered_map>> _specStarterTalents;
+ std::unordered_map>>> _levelClassSpellMap;
/* hater: cached tree meta data */
struct NodeMetaData {
@@ -938,14 +937,6 @@ class ForgeCache : public DatabaseScript
UpdateCharPoints(player, fcp);
}
- void InitSpecForTabId(Player* player, uint32 tabId) {
- ForgeCharacterSpec* spec;
- if (TryGetCharacterActiveSpec(player, spec)) {
- spec->Talents.clear();
- auto starters = GetStarterTalents(player->getClass(), tabId);
- }
- }
-
private:
std::unordered_map CharacterActiveSpecs;
std::unordered_map CONFIG;
@@ -1013,7 +1004,6 @@ class ForgeCache : public DatabaseScript
AddTalentTrees();
AddTalentsToTrees();
AddLevelClassSpellMap();
- AddSpecStarterTalents();
AddTalentPrereqs();
AddTalentChoiceNodes();
AddTalentRanks();
@@ -1728,7 +1718,7 @@ class ForgeCache : public DatabaseScript
{
_levelClassSpellMap.clear();
- QueryResult mapQuery = WorldDatabase.Query("select `level`,`class`, `tab`, `spell` from `acore_world`.`forge_character_spec_spells` order by `level` asc, `class` asc, `tab` asc, `spell` asc");
+ QueryResult mapQuery = WorldDatabase.Query("select * from `acore_world`.`forge_character_spec_spells` order by `class` asc, `race` asc, `level` asc, `spell` asc");
if (!mapQuery)
return;
@@ -1736,38 +1726,14 @@ class ForgeCache : public DatabaseScript
do
{
Field* mapFields = mapQuery->Fetch();
- uint32 level = mapFields[0].Get();
- uint32 classId = mapFields[1].Get();
- uint32 spec = mapFields[2].Get();
+ uint8 pClass = mapFields[0].Get();
+ uint32 race = mapFields[1].Get();
+ uint8 level = mapFields[2].Get();
uint32 spell = mapFields[3].Get();
- _levelClassSpellMap[level][classId][spec].push_back(spell);
+ _levelClassSpellMap[pClass][race][level].push_back(spell);
} while (mapQuery->NextRow());
}
-
- void AddSpecStarterTalents()
- {
- _specStarterTalents.clear();
-
- QueryResult mapQuery = WorldDatabase.Query("select `class`, `tab`, `spell` from `acore_world`.`forge_character_spec_strarter_talents`");
-
- if (!mapQuery)
- return;
-
- do
- {
- Field* mapFields = mapQuery->Fetch();
- uint32 classId = mapFields[0].Get();
- uint32 spec = mapFields[1].Get();
- uint32 spell = mapFields[2].Get();
-
- _specStarterTalents[classId][spec].push_back(spell);
- } while (mapQuery->NextRow());
- }
-
- std::vector GetStarterTalents(uint32 pClass, uint32 tabId) {
- return _specStarterTalents[pClass][tabId];
- }
};
#define sForgeCache ForgeCache::instance()
diff --git a/modules/mod-Forge/src/ForgePlayerMessageHandler.cpp b/modules/mod-Forge/src/ForgePlayerMessageHandler.cpp
index a7c35e8e09e82e..8b003c08f8e262 100644
--- a/modules/mod-Forge/src/ForgePlayerMessageHandler.cpp
+++ b/modules/mod-Forge/src/ForgePlayerMessageHandler.cpp
@@ -58,23 +58,7 @@ class ForgePlayerMessageHandler : public PlayerScript
if (!player)
return;
- uint32 count = 1;
-
- for (auto const& [accID, session] : sWorld->GetAllSessions())
- {
- Player* _player = session->GetPlayer();
- if (!_player || _player == player)
- {
- continue;
- }
-
- // If Remote Address matches, remove the player from the world
- //if (player->GetSession()->GetRemoteAddress() == _player->GetSession()->GetRemoteAddress() && ++count > 1)
- //{
- // player->GetSession()->KickPlayer();
- //}
- }
-
+ LearnSpellsForLevel(player);
fc->ApplyAccountBoundTalents(player);
}
@@ -102,85 +86,39 @@ class ForgePlayerMessageHandler : public PlayerScript
uint32 levelMod = fc->GetConfig("levelMod", 2);
uint8 levelDiff = currentLevel - oldlevel;
- if (currentLevel == fc->GetConfig("MaxLevel", 80))
- {
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::PRESTIGE_TREE, fc->GetConfig("PrestigePointsAtMaxLevel", 5));
- }
+ //if (currentLevel == fc->GetConfig("MaxLevel", 80))
+ //{
+ // fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::PRESTIGE_TREE, fc->GetConfig("PrestigePointsAtMaxLevel", 5));
+ //}
if (currentLevel >= 10)
{
uint8 amount = levelDiff;
if (oldlevel < 10 && levelDiff > 1)
- amount = levelDiff - (9 - oldlevel);
+ levelDiff -= (9 - oldlevel);
- if (levelDiff < levelMod && currentLevel % levelMod == 0)
- {
- uint32 scrapEarned = fc->GetConfig("scrapsPerLevelMod", 1);
- player->AddItem(FORGE_SCRAP, scrapEarned);
- }
- else if (levelDiff > 1 && levelDiff >= levelMod) // someone added levels, protect div by zero, dont allow 1 as its been evaluated. check if its enough levels
- {
- uint32 pointsMultiplier = levelDiff / levelMod;
- uint32 scrapEarned = fc->GetConfig("scrapsPerLevelMod", 1) * pointsMultiplier;
- player->AddItem(FORGE_SCRAP, scrapEarned);
- }
+ if (levelDiff > 1) {
+ int div = levelDiff / 2;
+ int rem = levelDiff % 2;
+ fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::TALENT_TREE, div);
+ if (rem)
+ div += 1;
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::TALENT_TREE, amount);
-
- ForgeCharacterPoint* pp = fc->GetCommonCharacterPoint(player, CharacterPointType::PRESTIGE_COUNT);
-
- if (oldlevel < 10 && pp->Sum == 0)
- {
- auto points = fc->GetConfig("fogepointsAt10", 30);
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::FORGE_SKILL_TREE, points);
+ fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::CLASS_TREE, div);
}
-
- if (pp->Sum == 0)
- {
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::FORGE_SKILL_TREE, amount * fc->GetConfig("InitialForgePointsPerLevel", 1));
-
- if (currentLevel >= 20 && oldlevel < 20)
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::RACIAL_TREE, fc->GetConfig("MilestonePoints", 4));
-
- if (currentLevel >= 40 && oldlevel < 40)
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::RACIAL_TREE, fc->GetConfig("MilestonePoints", 4));
-
- if (currentLevel >= 60 && oldlevel < 60)
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::RACIAL_TREE, fc->GetConfig("MilestonePoints", 4));
-
- if (currentLevel == 80)
- fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::RACIAL_TREE, fc->GetConfig("MilestonePoints", 4));
+ else {
+ if (currentLevel % 2)
+ fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::TALENT_TREE, amount);
+ else
+ fc->AddCharacterPointsToAllSpecs(player, CharacterPointType::CLASS_TREE, amount);
}
cm->SendActiveSpecInfo(player);
- cm->SendTalentTreeLayout(player);
- cm->SendTalents(player);
- }
-
- if (currentLevel == 80)
- {
- for (auto charTabType : fc->TALENT_POINT_TYPES)
- {
- if (ACCOUNT_WIDE_TYPE != charTabType)
- continue;
-
- std::list tabs;
- if (fc->TryGetForgeTalentTabs(player, charTabType, tabs))
- for (auto* tab : tabs)
- {
- auto talItt = spec->Talents.find(tab->Id);
-
- for (auto spell : tab->Talents)
- {
- for (auto rank : spell.second->Ranks)
- player->removeSpell(rank.second, SPEC_MASK_ALL, false);
- }
- }
- }
-
cm->SendTalents(player);
}
+ fc->UpdateCharacterSpec(player, spec);
+ LearnSpellsForLevel(player);
}
}
@@ -259,7 +197,29 @@ class ForgePlayerMessageHandler : public PlayerScript
TopicRouter* Router;
ForgeCache* fc;
ForgeCommonMessage* cm;
- uint32 FORGE_SCRAP = 90000;
+
+ void LearnSpellsForLevel(Player* player) {
+ if (player->HasUnitState(UNIT_STATE_DIED))
+ player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
+
+ auto pClass = fc->_levelClassSpellMap.find(player->getClass());
+ if (pClass != fc->_levelClassSpellMap.end()) {
+ for (auto race : pClass->second) {
+ if (player->getRaceMask() & race.first) {
+ for (auto level : race.second) {
+ if (level.first <= player->getLevel()) {
+ for (auto spell : level.second) {
+ if (player->HasSpell(spell))
+ continue;
+
+ player->learnSpell(spell);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
};
// Add all scripts in one
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 61804661fa43df..9bfc5d250efe40 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5032,16 +5032,7 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex)
bool knockbackImmune = false;
- Unit::AuraApplicationMap& auraMap = unitTarget->GetAppliedAuras();
- for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();)
- {
- AuraApplication* aurApp = iter->second;
- Aura* aura = aurApp->GetBase();
- if (aura->HasEffectType(SPELL_AURA_KNOCKBACK_IMMUNITY))
- knockbackImmune = true;
- }
-
- if (knockbackImmune)
+ if (unitTarget->HasAuraType(SPELL_AURA_KNOCKBACK_IMMUNITY))
return;
// Xinef: allow entry specific spells to skip those checks