Skip to content

Commit 4619c9e

Browse files
kewinrauschHelias
andauthored
Divide et impera (#190)
* 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]>
1 parent 5d2778e commit 4619c9e

32 files changed

+8079
-6676
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# ![logo](https://raw.githubusercontent.com/azerothcore/azerothcore.github.io/master/images/logo-github.png) AzerothCore
22

3+
## Beta testing warning
4+
5+
The current version of the master branch is currently in beta, under testing to ensure all the functionalities are working properly.
6+
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.
7+
38
## AutoBalance
49

510
- 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)

src/ABAllCreatureScript.cpp

Lines changed: 1637 additions & 0 deletions
Large diffs are not rendered by default.

src/ABAllCreatureScript.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
3+
*/
4+
5+
#ifndef __AB_ALL_CREATURE_SCRIPT_H
6+
#define __AB_ALL_CREATURE_SCRIPT_H
7+
8+
#include "ScriptMgr.h"
9+
10+
class AutoBalance_AllCreatureScript : public AllCreatureScript
11+
{
12+
public:
13+
AutoBalance_AllCreatureScript()
14+
: AllCreatureScript("AutoBalance_AllCreatureScript")
15+
{
16+
}
17+
18+
void OnBeforeCreatureSelectLevel(const CreatureTemplate* /*creatureTemplate*/, Creature* creature, uint8& level) override;
19+
void Creature_SelectLevel(const CreatureTemplate* /* cinfo */, Creature* creature) override;
20+
void OnCreatureAddWorld(Creature* creature) override;
21+
void OnCreatureRemoveWorld(Creature* creature) override;
22+
void OnAllCreatureUpdate(Creature* creature, uint32 /*diff*/) override;
23+
24+
// Reset the passed creature to stock if the config has changed
25+
bool ResetCreatureIfNeeded(Creature* creature);
26+
void ModifyCreatureAttributes(Creature* creature);
27+
28+
private:
29+
bool _isSummonCloneOfSummoner(Creature* summon);
30+
};
31+
32+
#endif /* __AB_ALL_CREATURE_SCRIPT_H */

src/ABAllMapScript.cpp

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
#include "Chat.h"
2+
3+
#include "ABAllMapScript.h"
4+
#include "ABConfig.h"
5+
#include "ABMapInfo.h"
6+
#include "ABUtils.h"
7+
#include "Message.h"
8+
9+
void AutoBalance_AllMapScript::OnCreateMap(Map* map)
10+
{
11+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{})",
12+
map->GetMapName(),
13+
map->GetId(),
14+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
15+
);
16+
17+
// clear out any previously-recorded data
18+
map->CustomData.Erase("AutoBalanceMapInfo");
19+
20+
AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");
21+
22+
if (map->IsDungeon())
23+
{
24+
// get the map's LFG stats even if not enabled
25+
LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty());
26+
if (dungeon) {
27+
mapABInfo->lfgMinLevel = dungeon->MinLevel;
28+
mapABInfo->lfgMaxLevel = dungeon->MaxLevel;
29+
mapABInfo->lfgTargetLevel = dungeon->TargetLevel;
30+
}
31+
// if this is a heroic dungeon that isn't in LFG, get the stats from the non-heroic version
32+
else if (map->IsHeroic())
33+
{
34+
LFGDungeonEntry const* nonHeroicDungeon = nullptr;
35+
if (map->GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC)
36+
{
37+
nonHeroicDungeon = GetLFGDungeon(map->GetId(), DUNGEON_DIFFICULTY_NORMAL);
38+
}
39+
else if (map->GetDifficulty() == RAID_DIFFICULTY_10MAN_HEROIC)
40+
{
41+
nonHeroicDungeon = GetLFGDungeon(map->GetId(), RAID_DIFFICULTY_10MAN_NORMAL);
42+
}
43+
else if (map->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC)
44+
{
45+
nonHeroicDungeon = GetLFGDungeon(map->GetId(), RAID_DIFFICULTY_25MAN_NORMAL);
46+
}
47+
48+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | is a Heroic dungeon that is not in LFG. Using non-heroic LFG levels.",
49+
map->GetMapName(),
50+
map->GetId(),
51+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
52+
);
53+
54+
if (nonHeroicDungeon)
55+
{
56+
mapABInfo->lfgMinLevel = nonHeroicDungeon->MinLevel;
57+
mapABInfo->lfgMaxLevel = nonHeroicDungeon->MaxLevel;
58+
mapABInfo->lfgTargetLevel = nonHeroicDungeon->TargetLevel;
59+
}
60+
else
61+
{
62+
LOG_ERROR("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | Could not determine LFG level ranges for this map. Level will bet set to 0.",
63+
map->GetMapName(),
64+
map->GetId(),
65+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
66+
);
67+
}
68+
}
69+
70+
if (map->GetInstanceId())
71+
{
72+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | is an instance of a map. Loading initial map data.",
73+
map->GetMapName(),
74+
map->GetId(),
75+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
76+
);
77+
UpdateMapDataIfNeeded(map);
78+
79+
// provide a concise summary of the map data we collected
80+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}{}) | LFG levels ({}-{}) (target {}). {} for AutoBalancing.",
81+
map->GetMapName(),
82+
map->GetId(),
83+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
84+
mapABInfo->lfgMinLevel ? std::to_string(mapABInfo->lfgMinLevel) : "?",
85+
mapABInfo->lfgMaxLevel ? std::to_string(mapABInfo->lfgMaxLevel) : "?",
86+
mapABInfo->lfgTargetLevel ? std::to_string(mapABInfo->lfgTargetLevel) : "?",
87+
mapABInfo->enabled ? "Enabled" : "Disabled"
88+
);
89+
}
90+
else
91+
{
92+
LOG_DEBUG(
93+
"module.AutoBalance", "AutoBalance_AllMapScript::OnCreateMap(): Map {} ({}) | is an instance base map.",
94+
map->GetMapName(),
95+
map->GetId()
96+
);
97+
}
98+
}
99+
}
100+
101+
void AutoBalance_AllMapScript::OnPlayerEnterAll(Map* map, Player* player)
102+
{
103+
if (!EnableGlobal)
104+
return;
105+
106+
if (!map->IsDungeon())
107+
return;
108+
109+
LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");
110+
111+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player {}{} | enters {} ({}{})",
112+
player->GetName(),
113+
player->IsGameMaster() ? " (GM)" : "",
114+
map->GetMapName(),
115+
map->GetId(),
116+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
117+
);
118+
119+
// get the map's info
120+
AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");
121+
122+
// store the previous difficulty for comparison later
123+
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;
124+
125+
// add player to this map's player list
126+
AddPlayerToMap(map, player);
127+
128+
// recalculate the zone's level stats
129+
mapABInfo->highestCreatureLevel = 0;
130+
mapABInfo->lowestCreatureLevel = 0;
131+
//mapABInfo->avgCreatureLevel = 0;
132+
mapABInfo->activeCreatureCount = 0;
133+
134+
WorldSession* session = player->GetSession();
135+
LocaleConstant locale = session->GetSessionDbLocaleIndex();
136+
137+
// if the previous player count is the same as the new player count, update without force
138+
if ((prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount) && (mapABInfo->adjustedPlayerCount != 1))
139+
{
140+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty unchanged at {}. Updating map data (no force).",
141+
mapABInfo->adjustedPlayerCount
142+
);
143+
144+
// Update the map's data
145+
UpdateMapDataIfNeeded(map, false);
146+
}
147+
else
148+
{
149+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty changed from ({})->({}). Updating map data (force).",
150+
prevAdjustedPlayerCount,
151+
mapABInfo->adjustedPlayerCount
152+
);
153+
154+
// Update the map's data, forced
155+
UpdateMapDataIfNeeded(map, true);
156+
}
157+
158+
// see which existing creatures are active
159+
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
160+
{
161+
AddCreatureToMapCreatureList(*creatureIterator, false, true);
162+
}
163+
164+
// Notify players of the change
165+
if (PlayerChangeNotify && mapABInfo->enabled)
166+
{
167+
if (map->GetEntry()->IsDungeon() && player)
168+
{
169+
if (mapABInfo->playerCount)
170+
{
171+
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
172+
{
173+
Player* thisPlayer = *playerIterator;
174+
if (thisPlayer)
175+
{
176+
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());
177+
InstanceMap* instanceMap = map->ToInstanceMap();
178+
179+
std::string instanceDifficulty; if (instanceMap->IsHeroic()) instanceDifficulty = "Heroic"; else instanceDifficulty = "Normal";
180+
181+
if (thisPlayer && thisPlayer == player) // This is the player that entered
182+
{
183+
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_player").c_str(),
184+
map->GetMapName(),
185+
instanceMap->GetMaxPlayers(),
186+
instanceDifficulty.c_str(),
187+
mapABInfo->playerCount,
188+
mapABInfo->adjustedPlayerCount);
189+
190+
// notify GMs that they won't be accounted for
191+
if (player->IsGameMaster())
192+
{
193+
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_gm").c_str());
194+
}
195+
}
196+
else
197+
{
198+
// announce non-GMs entering the instance only
199+
if (!player->IsGameMaster())
200+
{
201+
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "announce_non_gm_entering_instance").c_str(), player->GetName().c_str(), mapABInfo->playerCount, mapABInfo->adjustedPlayerCount);
202+
}
203+
}
204+
}
205+
}
206+
}
207+
}
208+
}
209+
}
210+
211+
void AutoBalance_AllMapScript::OnPlayerLeaveAll(Map* map, Player* player)
212+
{
213+
if (!EnableGlobal)
214+
return;
215+
216+
if (!map->IsDungeon())
217+
return;
218+
219+
LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");
220+
221+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {}{} | exits {} ({}{})",
222+
player->GetName(),
223+
player->IsGameMaster() ? " (GM)" : "",
224+
map->GetMapName(),
225+
map->GetId(),
226+
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
227+
);
228+
229+
// get the map's info
230+
AutoBalanceMapInfo* mapABInfo = map->CustomData.GetDefault<AutoBalanceMapInfo>("AutoBalanceMapInfo");
231+
232+
// store the previous difficulty for comparison later
233+
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;
234+
235+
// remove this player from this map's player list
236+
bool playerWasRemoved = RemovePlayerFromMap(map, player);
237+
238+
// report the number of players in the map
239+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: There are {} player(s) left in the map.", mapABInfo->allMapPlayers.size());
240+
241+
// if a player was NOT removed, return now - stats don't need to be updated
242+
if (!playerWasRemoved)
243+
{
244+
return;
245+
}
246+
247+
// recalculate the zone's level stats
248+
mapABInfo->highestCreatureLevel = 0;
249+
mapABInfo->lowestCreatureLevel = 0;
250+
//mapABInfo->avgCreatureLevel = 0;
251+
mapABInfo->activeCreatureCount = 0;
252+
253+
// see which existing creatures are active
254+
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
255+
{
256+
AddCreatureToMapCreatureList(*creatureIterator, false, true);
257+
}
258+
259+
// if the previous player count is the same as the new player count, update without force
260+
if (prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount)
261+
{
262+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty unchanged at {}. Updating map data (no force).",
263+
mapABInfo->adjustedPlayerCount
264+
);
265+
266+
// Update the map's data
267+
UpdateMapDataIfNeeded(map, false);
268+
}
269+
else
270+
{
271+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty changed from ({})->({}). Updating map data (force).",
272+
prevAdjustedPlayerCount,
273+
mapABInfo->adjustedPlayerCount
274+
);
275+
276+
// Update the map's data, forced
277+
UpdateMapDataIfNeeded(map, true);
278+
}
279+
280+
// updates the player count and levels for the map
281+
if (map->GetEntry() && map->GetEntry()->IsDungeon())
282+
{
283+
{
284+
mapABInfo->playerCount = mapABInfo->allMapPlayers.size();
285+
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {} left the instance.",
286+
player->GetName(),
287+
mapABInfo->playerCount,
288+
mapABInfo->adjustedPlayerCount
289+
);
290+
}
291+
}
292+
293+
// Notify remaining players in the instance that a player left
294+
if (PlayerChangeNotify && mapABInfo->enabled)
295+
{
296+
if (map->GetEntry()->IsDungeon() && player && !player->IsGameMaster())
297+
{
298+
if (mapABInfo->playerCount)
299+
{
300+
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
301+
{
302+
Player* thisPlayer = *playerIterator;
303+
if (thisPlayer && thisPlayer != player)
304+
{
305+
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());
306+
307+
if (mapABInfo->combatLocked)
308+
{
309+
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance_combat").c_str(),
310+
player->GetName().c_str(),
311+
mapABInfo->adjustedPlayerCount);
312+
}
313+
else
314+
{
315+
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance").c_str(),
316+
player->GetName().c_str(),
317+
mapABInfo->playerCount,
318+
mapABInfo->adjustedPlayerCount);
319+
}
320+
}
321+
}
322+
}
323+
}
324+
}
325+
}

src/ABAllMapScript.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
3+
*/
4+
5+
#ifndef __AB_ALL_MAP_SCRIPT_H
6+
#define __AB_ALL_MAP_SCRIPT_H
7+
8+
#include "ScriptMgr.h"
9+
10+
class AutoBalance_AllMapScript : public AllMapScript
11+
{
12+
public:
13+
AutoBalance_AllMapScript()
14+
: AllMapScript("AutoBalance_AllMapScript")
15+
{
16+
}
17+
18+
void OnCreateMap(Map* map);
19+
// hook triggers after the player has already entered the world
20+
void OnPlayerEnterAll(Map* map, Player* player);
21+
// hook triggers just before the player left the world
22+
void OnPlayerLeaveAll(Map* map, Player* player);
23+
};
24+
25+
#endif

0 commit comments

Comments
 (0)