Skip to content

Commit

Permalink
Divide et impera (#190)
Browse files Browse the repository at this point in the history
* Split of the single file implementation into dedicated class files; no changes on the module internal mechanism, only code movement from a file to another

* Added a note about the current state of the repo and a link to last stable version

* Update README.md

---------

Co-authored-by: Stefano Borzì <[email protected]>
  • Loading branch information
kewinrausch and Helias authored Sep 26, 2024
1 parent 5d2778e commit 4619c9e
Show file tree
Hide file tree
Showing 32 changed files with 8,079 additions and 6,676 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# ![logo](https://raw.githubusercontent.com/azerothcore/azerothcore.github.io/master/images/logo-github.png) AzerothCore

## Beta testing warning

The current version of the master branch is currently in beta, under testing to ensure all the functionalities are working properly.
If you encur in problems please open an Issue and consider to use the last [stable version](https://github.com/azerothcore/mod-autobalance/releases/tag/stable) of this repository.

## AutoBalance

- Latest build status with azerothcore: [![Build Status](https://github.com/azerothcore/mod-autobalance/workflows/core-build/badge.svg?branch=master&event=push)](https://github.com/azerothcore/mod-autobalance)
Expand Down
1,637 changes: 1,637 additions & 0 deletions src/ABAllCreatureScript.cpp

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions src/ABAllCreatureScript.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/

#ifndef __AB_ALL_CREATURE_SCRIPT_H
#define __AB_ALL_CREATURE_SCRIPT_H

#include "ScriptMgr.h"

class AutoBalance_AllCreatureScript : public AllCreatureScript
{
public:
AutoBalance_AllCreatureScript()
: AllCreatureScript("AutoBalance_AllCreatureScript")
{
}

void OnBeforeCreatureSelectLevel(const CreatureTemplate* /*creatureTemplate*/, Creature* creature, uint8& level) override;
void Creature_SelectLevel(const CreatureTemplate* /* cinfo */, Creature* creature) override;
void OnCreatureAddWorld(Creature* creature) override;
void OnCreatureRemoveWorld(Creature* creature) override;
void OnAllCreatureUpdate(Creature* creature, uint32 /*diff*/) override;

// Reset the passed creature to stock if the config has changed
bool ResetCreatureIfNeeded(Creature* creature);
void ModifyCreatureAttributes(Creature* creature);

private:
bool _isSummonCloneOfSummoner(Creature* summon);
};

#endif /* __AB_ALL_CREATURE_SCRIPT_H */
325 changes: 325 additions & 0 deletions src/ABAllMapScript.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
#include "Chat.h"

#include "ABAllMapScript.h"
#include "ABConfig.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
#include "Message.h"

void AutoBalance_AllMapScript::OnCreateMap(Map* map)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{})",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);

// clear out any previously-recorded data
map->CustomData.Erase("AutoBalanceMapInfo");

AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");

if (map->IsDungeon())
{
// get the map's LFG stats even if not enabled
LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty());
if (dungeon) {
mapABInfo->lfgMinLevel = dungeon->MinLevel;
mapABInfo->lfgMaxLevel = dungeon->MaxLevel;
mapABInfo->lfgTargetLevel = dungeon->TargetLevel;
}
// if this is a heroic dungeon that isn't in LFG, get the stats from the non-heroic version
else if (map->IsHeroic())
{
LFGDungeonEntry const* nonHeroicDungeon = nullptr;
if (map->GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC)
{
nonHeroicDungeon = GetLFGDungeon(map->GetId(), DUNGEON_DIFFICULTY_NORMAL);
}
else if (map->GetDifficulty() == RAID_DIFFICULTY_10MAN_HEROIC)
{
nonHeroicDungeon = GetLFGDungeon(map->GetId(), RAID_DIFFICULTY_10MAN_NORMAL);
}
else if (map->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC)
{
nonHeroicDungeon = GetLFGDungeon(map->GetId(), RAID_DIFFICULTY_25MAN_NORMAL);
}

LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | is a Heroic dungeon that is not in LFG. Using non-heroic LFG levels.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);

if (nonHeroicDungeon)
{
mapABInfo->lfgMinLevel = nonHeroicDungeon->MinLevel;
mapABInfo->lfgMaxLevel = nonHeroicDungeon->MaxLevel;
mapABInfo->lfgTargetLevel = nonHeroicDungeon->TargetLevel;
}
else
{
LOG_ERROR("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | Could not determine LFG level ranges for this map. Level will bet set to 0.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);
}
}

if (map->GetInstanceId())
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | is an instance of a map. Loading initial map data.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);
UpdateMapDataIfNeeded(map);

// provide a concise summary of the map data we collected
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | LFG levels ({}-{}) (target {}). {} for AutoBalancing.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
mapABInfo->lfgMinLevel ? std::to_string(mapABInfo->lfgMinLevel) : "?",
mapABInfo->lfgMaxLevel ? std::to_string(mapABInfo->lfgMaxLevel) : "?",
mapABInfo->lfgTargetLevel ? std::to_string(mapABInfo->lfgTargetLevel) : "?",
mapABInfo->enabled ? "Enabled" : "Disabled"
);
}
else
{
LOG_DEBUG(
"module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}) | is an instance base map.",
map->GetMapName(),
map->GetId()
);
}
}
}

void AutoBalance_AllMapScript::OnPlayerEnterAll(Map* map, Player* player)
{
if (!EnableGlobal)
return;

if (!map->IsDungeon())
return;

LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");

LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player {}{} | enters {} ({}{})",
player->GetName(),
player->IsGameMaster() ? " (GM)" : "",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);

// get the map's info
AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");

// store the previous difficulty for comparison later
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;

// add player to this map's player list
AddPlayerToMap(map, player);

// recalculate the zone's level stats
mapABInfo->highestCreatureLevel = 0;
mapABInfo->lowestCreatureLevel = 0;
//mapABInfo->avgCreatureLevel = 0;
mapABInfo->activeCreatureCount = 0;

WorldSession* session = player->GetSession();
LocaleConstant locale = session->GetSessionDbLocaleIndex();

// if the previous player count is the same as the new player count, update without force
if ((prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount) && (mapABInfo->adjustedPlayerCount != 1))
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty unchanged at {}. Updating map data (no force).",
mapABInfo->adjustedPlayerCount
);

// Update the map's data
UpdateMapDataIfNeeded(map, false);
}
else
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty changed from ({})->({}). Updating map data (force).",
prevAdjustedPlayerCount,
mapABInfo->adjustedPlayerCount
);

// Update the map's data, forced
UpdateMapDataIfNeeded(map, true);
}

// see which existing creatures are active
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
{
AddCreatureToMapCreatureList(*creatureIterator, false, true);
}

// Notify players of the change
if (PlayerChangeNotify && mapABInfo->enabled)
{
if (map->GetEntry()->IsDungeon() && player)
{
if (mapABInfo->playerCount)
{
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
{
Player* thisPlayer = *playerIterator;
if (thisPlayer)
{
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());
InstanceMap* instanceMap = map->ToInstanceMap();

std::string instanceDifficulty; if (instanceMap->IsHeroic()) instanceDifficulty = "Heroic"; else instanceDifficulty = "Normal";

if (thisPlayer && thisPlayer == player) // This is the player that entered
{
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_player").c_str(),
map->GetMapName(),
instanceMap->GetMaxPlayers(),
instanceDifficulty.c_str(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount);

// notify GMs that they won't be accounted for
if (player->IsGameMaster())
{
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_gm").c_str());
}
}
else
{
// announce non-GMs entering the instance only
if (!player->IsGameMaster())
{
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "announce_non_gm_entering_instance").c_str(), player->GetName().c_str(), mapABInfo->playerCount, mapABInfo->adjustedPlayerCount);
}
}
}
}
}
}
}
}

void AutoBalance_AllMapScript::OnPlayerLeaveAll(Map* map, Player* player)
{
if (!EnableGlobal)
return;

if (!map->IsDungeon())
return;

LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");

LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {}{} | exits {} ({}{})",
player->GetName(),
player->IsGameMaster() ? " (GM)" : "",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);

// get the map's info
AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");

// store the previous difficulty for comparison later
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;

// remove this player from this map's player list
bool playerWasRemoved = RemovePlayerFromMap(map, player);

// report the number of players in the map
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: There are {} player(s) left in the map.", mapABInfo->allMapPlayers.size());

// if a player was NOT removed, return now - stats don't need to be updated
if (!playerWasRemoved)
{
return;
}

// recalculate the zone's level stats
mapABInfo->highestCreatureLevel = 0;
mapABInfo->lowestCreatureLevel = 0;
//mapABInfo->avgCreatureLevel = 0;
mapABInfo->activeCreatureCount = 0;

// see which existing creatures are active
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
{
AddCreatureToMapCreatureList(*creatureIterator, false, true);
}

// if the previous player count is the same as the new player count, update without force
if (prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty unchanged at {}. Updating map data (no force).",
mapABInfo->adjustedPlayerCount
);

// Update the map's data
UpdateMapDataIfNeeded(map, false);
}
else
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty changed from ({})->({}). Updating map data (force).",
prevAdjustedPlayerCount,
mapABInfo->adjustedPlayerCount
);

// Update the map's data, forced
UpdateMapDataIfNeeded(map, true);
}

// updates the player count and levels for the map
if (map->GetEntry() && map->GetEntry()->IsDungeon())
{
{
mapABInfo->playerCount = mapABInfo->allMapPlayers.size();
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {} left the instance.",
player->GetName(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount
);
}
}

// Notify remaining players in the instance that a player left
if (PlayerChangeNotify && mapABInfo->enabled)
{
if (map->GetEntry()->IsDungeon() && player && !player->IsGameMaster())
{
if (mapABInfo->playerCount)
{
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
{
Player* thisPlayer = *playerIterator;
if (thisPlayer && thisPlayer != player)
{
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());

if (mapABInfo->combatLocked)
{
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance_combat").c_str(),
player->GetName().c_str(),
mapABInfo->adjustedPlayerCount);
}
else
{
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance").c_str(),
player->GetName().c_str(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount);
}
}
}
}
}
}
}
25 changes: 25 additions & 0 deletions src/ABAllMapScript.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/

#ifndef __AB_ALL_MAP_SCRIPT_H
#define __AB_ALL_MAP_SCRIPT_H

#include "ScriptMgr.h"

class AutoBalance_AllMapScript : public AllMapScript
{
public:
AutoBalance_AllMapScript()
: AllMapScript("AutoBalance_AllMapScript")
{
}

void OnCreateMap(Map* map);
// hook triggers after the player has already entered the world
void OnPlayerEnterAll(Map* map, Player* player);
// hook triggers just before the player left the world
void OnPlayerLeaveAll(Map* map, Player* player);
};

#endif
Loading

0 comments on commit 4619c9e

Please sign in to comment.