Skip to content

Commit e27f28a

Browse files
Merge AzerothCore 3.3.5 to ElunaAzerothcore [skip ci]
2 parents c49559c + f32f6d4 commit e27f28a

7 files changed

Lines changed: 268 additions & 155 deletions

File tree

src/common/Utilities/TypeList.h

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12+
* more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along
15+
* with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef TypeList_h__
19+
#define TypeList_h__
20+
21+
#include <cstddef>
22+
#include <utility>
23+
24+
namespace Acore
25+
{
26+
/**
27+
* @brief Provide an empty tag type containing the specified @p Ts.
28+
*
29+
* @tparam Ts The types in this list.
30+
*/
31+
template <typename... Ts>
32+
struct type_list { };
33+
34+
namespace Impl
35+
{
36+
template <typename T>
37+
inline constexpr bool is_type_list = false;
38+
39+
template <typename... Ts>
40+
inline constexpr bool is_type_list<type_list<Ts...>> = true;
41+
42+
template <typename List>
43+
struct list_size;
44+
45+
template <typename... Ts>
46+
struct list_size<type_list<Ts...>>
47+
{
48+
static constexpr std::size_t value = sizeof...(Ts);
49+
};
50+
51+
template <typename... Ts, typename Func>
52+
constexpr void for_each(type_list<Ts...>, Func&& f)
53+
{
54+
(f.template operator()<Ts>(), ...);
55+
}
56+
57+
template <typename... Ts, typename Pred>
58+
constexpr std::size_t count_if(type_list<Ts...>, Pred pred)
59+
{
60+
return ((pred.template operator()<Ts>() ? std::size_t{1} : std::size_t{0}) + ... + std::size_t{0});
61+
}
62+
63+
template <typename... Ts, typename Pred>
64+
constexpr bool any_of(type_list<Ts...>, Pred pred)
65+
{
66+
return (false || ... || pred.template operator()<Ts>());
67+
}
68+
}
69+
70+
/**
71+
* @brief Satisfied only by Acore::type_list specializations.
72+
*
73+
* Constrains the public list operations so they are viable only for an
74+
* actual type_list.
75+
*/
76+
template <typename T>
77+
concept AnyTypeList = Impl::is_type_list<T>;
78+
79+
/**
80+
* @brief The number of types in the specified @p List.
81+
*
82+
* @tparam List A type_list specialization.
83+
*/
84+
template <AnyTypeList List>
85+
inline constexpr std::size_t size_v = Impl::list_size<List>::value;
86+
87+
/**
88+
* @brief Invoke the specified @p f once for each type in the specified
89+
* @p List, in declaration order.
90+
*
91+
* @tparam List A type_list specialization.
92+
* @tparam Func The type of the callable.
93+
* @param f The callable to invoke.
94+
*/
95+
template <AnyTypeList List, typename Func>
96+
constexpr void for_each(Func&& f)
97+
{
98+
Impl::for_each(List{}, std::forward<Func>(f));
99+
}
100+
101+
/**
102+
* @brief Return the number of types in the specified @p List for which the
103+
* specified @p pred returns true.
104+
*
105+
* @tparam List A type_list specialization.
106+
* @tparam Pred The type of the predicate.
107+
* @param pred The predicate to evaluate.
108+
* @return The number of matching types.
109+
*/
110+
template <AnyTypeList List, typename Pred>
111+
constexpr std::size_t count_if(Pred pred)
112+
{
113+
return Impl::count_if(List{}, pred);
114+
}
115+
116+
/**
117+
* @brief Return true if the specified @p pred returns true for any type in
118+
* the specified @p List, and false otherwise.
119+
*
120+
* @tparam List A type_list specialization.
121+
* @tparam Pred The type of the predicate.
122+
* @param pred The predicate to evaluate.
123+
* @return True if any type matches, and false otherwise.
124+
*/
125+
template <AnyTypeList List, typename Pred>
126+
constexpr bool any_of(Pred pred)
127+
{
128+
return Impl::any_of(List{}, pred);
129+
}
130+
}
131+
132+
#endif // TypeList_h__

src/server/apps/worldserver/worldserver.conf.dist

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,15 @@ SpellQueue.Window = 400
22622262

22632263
Achievement.RealmFirstKillWindow = 60
22642264

2265+
#
2266+
# Achievement.RealmFirstRaceLimitOnePerCharacter
2267+
# Description: Limit 'Realm First!' race achievements to one per character. Prevents abuse
2268+
# of the race/faction change service to obtain multiple achievements.
2269+
# Default: 1 - (Enabled)
2270+
# 0 - (Disabled)
2271+
2272+
Achievement.RealmFirstRaceLimitOnePerCharacter = 1
2273+
22652274
#
22662275
###################################################################################################
22672276

src/server/game/Achievements/AchievementMgr.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,14 +1837,17 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
18371837
if (sAchievementMgr->IsRealmCompleted(achievement))
18381838
return false;
18391839

1840-
// A character may only have 1 race-specific 'Realm First!' achievement
1841-
// prevent clever use of the race/faction change service to obtain multiple 'Realm First!' achievements
1842-
constexpr std::array<uint32, 9> raceSpecificRealmFirstAchievements { 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413 };
1843-
bool isRaceSpecific = std::ranges::find(raceSpecificRealmFirstAchievements, achievement->ID) != std::ranges::end(raceSpecificRealmFirstAchievements);
1844-
if (isRaceSpecific)
1845-
for (uint32 raceAchievementId : raceSpecificRealmFirstAchievements)
1846-
if (raceAchievementId != achievement->ID && HasAchieved(raceAchievementId))
1847-
return false;
1840+
if (sWorld->getBoolConfig(CONFIG_ACHIEVEMENT_REALM_FIRST_RACE_LIMIT_ONE_PER_CHARACTER))
1841+
{
1842+
// A character may only have 1 race-specific 'Realm First!' achievement
1843+
// prevent clever use of the race/faction change service to obtain multiple 'Realm First!' achievements
1844+
constexpr std::array<uint32, 9> raceSpecificRealmFirstAchievements { 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413 };
1845+
bool isRaceSpecific = std::ranges::find(raceSpecificRealmFirstAchievements, achievement->ID) != std::ranges::end(raceSpecificRealmFirstAchievements);
1846+
if (isRaceSpecific)
1847+
for (uint32 raceAchievementId : raceSpecificRealmFirstAchievements)
1848+
if (raceAchievementId != achievement->ID && HasAchieved(raceAchievementId))
1849+
return false;
1850+
}
18481851
}
18491852

18501853
// pussywizard: progress will be deleted after getting the achievement (optimization)

src/server/game/Entities/Player/Player.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13954,45 +13954,45 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
1395413954
return EQUIP_ERR_OK;
1395513955
}
1395613956

13957+
static constexpr float FALL_DMG_EQU_SLOPE = 0.018f;
13958+
static constexpr float FALL_DMG_EQU_INTERCEPT = -0.2426f;
13959+
static constexpr float MIN_FALL_DMG_DIST = 13.48f; // Minimum fall distance that deals damage
13960+
// 13.48 can be calculated by resolving damageperc to 0 in the fall damage equation below, and assuming safe_fall reduction = 0
13961+
13962+
static constexpr uint32 SPELL_GUST_OF_WIND = 43621;
13963+
static constexpr uint32 SPELL_DIVINE_PROTECTION = 498;
13964+
1395713965
void Player::HandleFall(MovementInfo const& movementInfo)
1395813966
{
1395913967
// calculate total z distance of the fall
1396013968
float z_diff = m_lastFallZ - movementInfo.pos.GetPositionZ();
1396113969

1396213970
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
13963-
// 14.57 can be calculated by resolving damageperc formula below to 0
13964-
if (z_diff >= 14.57f && !isDead() && !IsGameMaster() && !GetCommandStatus(CHEAT_GOD) &&
13971+
if (z_diff >= MIN_FALL_DMG_DIST && !isDead() && !IsGameMaster() && !GetCommandStatus(CHEAT_GOD) &&
1396513972
!HasHoverAura() && !HasFeatherFallAura() &&
1396613973
!HasFlyAura())
1396713974
{
1396813975
//Safe fall, fall height reduction
1396913976
int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
1397013977

13971-
float damageperc = 0.018f * (z_diff - safe_fall) - 0.2426f;
13978+
float damageperc = FALL_DMG_EQU_SLOPE * (z_diff - safe_fall) + FALL_DMG_EQU_INTERCEPT;
1397213979
uint32 original_health = GetHealth(), final_damage = 0;
1397313980

1397413981
if (damageperc > 0 && !IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_NORMAL))
1397513982
{
1397613983
uint32 damage = (uint32)(damageperc * GetMaxHealth() * sWorld->getRate(RATE_DAMAGE_FALL));
1397713984

13978-
//float height = movementInfo.pos.m_positionZ;
13979-
//UpdateGroundPositionZ(movementInfo.pos.m_positionX, movementInfo.pos.m_positionY, height);
13980-
1398113985
if (damage > 0)
1398213986
{
1398313987
//Prevent fall damage from being more than the player maximum health
1398413988
if (damage > GetMaxHealth())
1398513989
damage = GetMaxHealth();
1398613990

13987-
// Gust of Wind
13988-
if (HasAura(43621))
13991+
if (HasAura(SPELL_GUST_OF_WIND))
1398913992
damage = GetMaxHealth() / 2;
1399013993

13991-
// Divine Protection
13992-
if (HasAura(498))
13993-
{
13994+
if (HasAura(SPELL_DIVINE_PROTECTION))
1399413995
damage /= 2;
13995-
}
1399613996

1399713997
final_damage = EnvironmentalDamage(DAMAGE_FALL, damage);
1399813998
}

0 commit comments

Comments
 (0)