[Quest API] Add Archetype Methods to Perl/Lua (#4181)

* [Quest API] Add Archetype Methods to Perl/Lua

- Add `$mob->GetArchetypeName()`.
- Add `$mob->IsIntelligenceCasterClass()`.
- Add `$mob->IsPureMeleeClass()`.
- Add `$mob->IsWisdomCasterClass()`.

- Add `mob:GetArchetypeName()`.
- Add `mob:IsIntelligenceCasterClass()`.
- Add `mob:IsPureMeleeClass()`.
- Add `mob:IsWisdomCasterClass()`.

- Allows operators to use mob archetypes to perform different operations.
- Add a namespace for archetypes instead of constants.
- Utilize `IsIntelligenceCasterClass()`, `IsPureMeleeClass()`, and `IsWisdomCasterClass()` where necessary.
-

* Update mob.cpp
This commit is contained in:
Alex King 2024-03-23 15:37:35 -04:00 committed by GitHub
parent d2372de982
commit abdec39cdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 465 additions and 384 deletions

View File

@ -2287,7 +2287,7 @@ bool Bot::TryMeditate() {
if (!IsMoving() && !spellend_timer.Enabled()) {
if (GetTarget() && AI_EngagedCastCheck()) {
BotMeditate(false);
} else if (GetArchetype() == ARCHETYPE_CASTER) {
} else if (GetArchetype() == Archetype::Caster) {
BotMeditate(true);
}
@ -2755,7 +2755,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
}
}
if (GetArchetype() == ARCHETYPE_CASTER) {
if (GetArchetype() == Archetype::Caster) {
BotMeditate(true);
}
}
@ -5189,31 +5189,26 @@ void Bot::ProcessBotOwnerRefDelete(Mob* botOwner) {
}
}
int64 Bot::CalcMaxMana() {
switch(GetCasterClass()) {
case 'I':
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
max_mana += itembonuses.heroic_max_mana;
case 'W': {
max_mana = (GenerateBaseManaPoints() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
max_mana += itembonuses.heroic_max_mana;
break;
}
case 'N': {
max_mana = 0;
break;
}
default: {
LogDebug("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
max_mana = 0;
break;
}
int64 Bot::CalcMaxMana()
{
if (IsIntelligenceCasterClass() || IsWisdomCasterClass()) {
max_mana = (
GenerateBaseManaPoints() +
itembonuses.Mana +
spellbonuses.Mana +
aabonuses.Mana +
GroupLeadershipAAManaEnhancement()
);
max_mana += itembonuses.heroic_max_mana;
} else {
max_mana = 0;
}
if (current_mana > max_mana)
if (current_mana > max_mana) {
current_mana = max_mana;
else if (max_mana < 0)
} else if (max_mana < 0) {
max_mana = 0;
}
return max_mana;
}
@ -5528,87 +5523,107 @@ bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot
return Result;
}
int32 Bot::GenerateBaseManaPoints() {
int32 bot_mana = 0;
int32 WisInt = 0;
int32 Bot::GenerateBaseManaPoints()
{
int32 bot_mana = 0;
int32 WisInt = 0;
int32 MindLesserFactor, MindFactor;
int wisint_mana = 0;
int base_mana = 0;
int ConvertedWisInt = 0;
switch(GetCasterClass()) {
case 'I':
WisInt = INT;
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201)
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
}
else
ConvertedWisInt = WisInt;
int wisint_mana = 0;
int base_mana = 0;
int ConvertedWisInt = 0;
if (GetLevel() < 41) {
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
base_mana = (GetLevel() * 15);
} else if (GetLevel() < 81) {
wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100));
base_mana = (600 + ((GetLevel() - 40) * 30));
} else {
wisint_mana = (9 * ConvertedWisInt);
base_mana = (1800 + ((GetLevel() - 80) * 18));
if (IsIntelligenceCasterClass()) {
WisInt = INT;
if (
GetOwner() &&
GetOwner()->CastToClient() &&
GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD &&
RuleB(Character, SoDClientUseSoDHPManaEnd)
) {
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201) {
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
}
bot_mana = (base_mana + wisint_mana);
} else {
if (((WisInt - 199) / 2) > 0)
MindLesserFactor = ((WisInt - 199) / 2);
else
MindLesserFactor = 0;
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100)
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
else
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
ConvertedWisInt = WisInt;
}
break;
case 'W':
WisInt = WIS;
if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201)
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
} else
ConvertedWisInt = WisInt;
if (GetLevel() < 41) {
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
base_mana = (GetLevel() * 15);
} else if (GetLevel() < 81) {
wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100));
base_mana = (600 + ((GetLevel() - 40) * 30));
} else {
wisint_mana = (9 * ConvertedWisInt);
base_mana = (1800 + ((GetLevel() - 80) * 18));
}
bot_mana = (base_mana + wisint_mana);
if (GetLevel() < 41) {
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
base_mana = (GetLevel() * 15);
} else if (GetLevel() < 81) {
wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100));
base_mana = (600 + ((GetLevel() - 40) * 30));
} else {
if (((WisInt - 199) / 2) > 0)
MindLesserFactor = ((WisInt - 199) / 2);
else
MindLesserFactor = 0;
MindFactor = (WisInt - MindLesserFactor);
if (WisInt > 100)
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
else
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
wisint_mana = (9 * ConvertedWisInt);
base_mana = (1800 + ((GetLevel() - 80) * 18));
}
break;
default:
bot_mana = 0;
break;
bot_mana = (base_mana + wisint_mana);
} else {
if (((WisInt - 199) / 2) > 0) {
MindLesserFactor = ((WisInt - 199) / 2);
} else {
MindLesserFactor = 0;
}
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100) {
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
} else {
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
}
} else if (IsWisdomCasterClass()) {
WisInt = WIS;
if (
GetOwner() &&
GetOwner()->CastToClient() &&
GetOwner()->CastToClient()->ClientVersion() >= EQ::versions::ClientVersion::SoD &&
RuleB(Character, SoDClientUseSoDHPManaEnd)
) {
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201) {
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
}
} else {
ConvertedWisInt = WisInt;
}
if (GetLevel() < 41) {
wisint_mana = (GetLevel() * 75 * ConvertedWisInt / 1000);
base_mana = (GetLevel() * 15);
} else if (GetLevel() < 81) {
wisint_mana = ((3 * ConvertedWisInt) + ((GetLevel() - 40) * 15 * ConvertedWisInt / 100));
base_mana = (600 + ((GetLevel() - 40) * 30));
} else {
wisint_mana = (9 * ConvertedWisInt);
base_mana = (1800 + ((GetLevel() - 80) * 18));
}
bot_mana = (base_mana + wisint_mana);
} else {
if (((WisInt - 199) / 2) > 0) {
MindLesserFactor = ((WisInt - 199) / 2);
} else {
MindLesserFactor = 0;
}
MindFactor = (WisInt - MindLesserFactor);
if (WisInt > 100) {
bot_mana = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
} else {
bot_mana = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
}
} else {
bot_mana = 0;
}
max_mana = bot_mana;
return bot_mana;
}

View File

@ -591,7 +591,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
//Only check archetype if spell is not a group spell
//Hybrids get all buffs
switch (tar->GetArchetype()) {
case ARCHETYPE_CASTER:
case Archetype::Caster:
//TODO: probably more caster specific spell effects in here
if (
(
@ -606,7 +606,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
continue;
}
break;
case ARCHETYPE_MELEE:
case Archetype::Melee:
if (
(
IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) ||
@ -899,7 +899,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
switch (tar->GetArchetype())
{
case ARCHETYPE_CASTER:
case Archetype::Caster:
//TODO: probably more caster specific spell effects in here
if (IsEffectInSpell(s.SpellId, SE_AttackSpeed) || IsEffectInSpell(s.SpellId, SE_ATK) ||
IsEffectInSpell(s.SpellId, SE_STR) || IsEffectInSpell(s.SpellId, SE_ReverseDS))
@ -907,7 +907,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
continue;
}
break;
case ARCHETYPE_MELEE:
case Archetype::Melee:
if (IsEffectInSpell(s.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(s.SpellId, SE_ManaPool) ||
IsEffectInSpell(s.SpellId, SE_CastingLevel) || IsEffectInSpell(s.SpellId, SE_ManaRegen_v2) ||
IsEffectInSpell(s.SpellId, SE_CurrentMana))

View File

@ -523,28 +523,26 @@ int32 Client::GetRawItemAC()
int64 Client::CalcMaxMana()
{
switch (GetCasterClass()) {
case 'I':
case 'W': {
max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
break;
}
case 'N': {
max_mana = 0;
break;
}
default: {
LogSpells("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
max_mana = 0;
break;
}
if (IsIntelligenceCasterClass() || IsWisdomCasterClass()) {
max_mana = (
CalcBaseMana() +
itembonuses.Mana +
spellbonuses.Mana +
aabonuses.Mana +
GroupLeadershipAAManaEnhancement()
);
} else {
max_mana = 0;
}
if (max_mana < 0) {
max_mana = 0;
}
if (current_mana > max_mana) {
current_mana = max_mana;
}
int mana_perc_cap = spellbonuses.ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (mana_perc_cap) {
int curMana_cap = (max_mana * mana_perc_cap) / 100;
@ -552,96 +550,90 @@ int64 Client::CalcMaxMana()
current_mana = curMana_cap;
}
}
LogSpells("for [{}] returning [{}]", GetName(), max_mana);
return max_mana;
}
int64 Client::CalcBaseMana()
{
int ConvertedWisInt = 0;
int MindLesserFactor, MindFactor;
int WisInt = 0;
int64 base_mana = 0;
int wisint_mana = 0;
int64 max_m = 0;
switch (GetCasterClass()) {
case 'I':
WisInt = GetINT();
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
int ConvertedWisInt = 0;
int MindLesserFactor, MindFactor;
int WisInt = 0;
int64 base_mana = 0;
int wisint_mana = 0;
int64 max_m = 0;
if (IsIntelligenceCasterClass()) {
WisInt = GetINT();
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
else {
if ((( WisInt - 199 ) / 2) > 0) {
MindLesserFactor = ( WisInt - 199 ) / 2;
}
else {
MindLesserFactor = 0;
}
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100) {
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
}
else {
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
}
break;
case 'W':
WisInt = GetWIS();
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
}
} else {
if (((WisInt - 199) / 2) > 0) {
MindLesserFactor = (WisInt - 199) / 2;
} else {
MindLesserFactor = 0;
}
else {
if ((( WisInt - 199 ) / 2) > 0) {
MindLesserFactor = ( WisInt - 199 ) / 2;
}
else {
MindLesserFactor = 0;
}
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100) {
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
}
else {
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100) {
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
} else {
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
break;
case 'N': {
max_m = 0;
break;
}
} else if (IsWisdomCasterClass()) {
WisInt = GetWIS();
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
default: {
LogDebug("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
max_m = 0;
break;
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
}
} else {
if (((WisInt - 199) / 2) > 0) {
MindLesserFactor = (WisInt - 199) / 2;
} else {
MindLesserFactor = 0;
}
MindFactor = WisInt - MindLesserFactor;
if (WisInt > 100) {
max_m = (((5 * (MindFactor + 20)) / 2) * 3 * GetLevel() / 40);
} else {
max_m = (((5 * (MindFactor + 200)) / 2) * 3 * GetLevel() / 100);
}
}
} else {
max_m = 0;
}
#if EQDEBUG >= 11
LogDebug("Client::CalcBaseMana() called for [{}] - returning [{}]", GetName(), max_m);
#endif
return max_m;
}

View File

@ -19,9 +19,11 @@
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
#define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS
#define ARCHETYPE_HYBRID 1
#define ARCHETYPE_CASTER 2
#define ARCHETYPE_MELEE 3
namespace Archetype {
constexpr uint8 Hybrid = 1;
constexpr uint8 Caster = 2;
constexpr uint8 Melee = 3;
};
#define CON_GREEN 2
#define CON_LIGHTBLUE 18

View File

@ -3333,6 +3333,30 @@ void Lua_Mob::RestoreMana()
self->RestoreMana();
}
std::string Lua_Mob::GetArchetypeName()
{
Lua_Safe_Call_String();
return self->GetArchetypeName();
}
bool Lua_Mob::IsIntelligenceCasterClass()
{
Lua_Safe_Call_Bool();
return self->IsIntelligenceCasterClass();
}
bool Lua_Mob::IsPureMeleeClass()
{
Lua_Safe_Call_Bool();
return self->IsPureMeleeClass();
}
bool Lua_Mob::IsWisdomCasterClass()
{
Lua_Safe_Call_Bool();
return self->IsWisdomCasterClass();
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@ -3524,6 +3548,7 @@ luabind::scope lua_register_mob() {
.def("GetAggroRange", (float(Lua_Mob::*)(void))&Lua_Mob::GetAggroRange)
.def("GetAllowBeneficial", (bool(Lua_Mob::*)(void))&Lua_Mob::GetAllowBeneficial)
.def("GetAppearance", (uint32(Lua_Mob::*)(void))&Lua_Mob::GetAppearance)
.def("GetArchetypeName", &Lua_Mob::GetArchetypeName)
.def("GetAssistRange", (float(Lua_Mob::*)(void))&Lua_Mob::GetAssistRange)
.def("GetBaseGender", &Lua_Mob::GetBaseGender)
.def("GetBaseRace", &Lua_Mob::GetBaseRace)
@ -3732,6 +3757,7 @@ luabind::scope lua_register_mob() {
.def("IsFindable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFindable)
.def("IsHorse", &Lua_Mob::IsHorse)
.def("IsImmuneToSpell", (bool(Lua_Mob::*)(int,Lua_Mob))&Lua_Mob::IsImmuneToSpell)
.def("IsIntelligenceCasterClass", &Lua_Mob::IsIntelligenceCasterClass)
.def("IsInvisible", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsInvisible)
.def("IsInvisible", (bool(Lua_Mob::*)(void))&Lua_Mob::IsInvisible)
.def("IsMeleeDisabled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsMeleeDisabled)
@ -3742,6 +3768,7 @@ luabind::scope lua_register_mob() {
.def("IsPetOwnerBot", &Lua_Mob::IsPetOwnerBot)
.def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient)
.def("IsPetOwnerNPC", &Lua_Mob::IsPetOwnerNPC)
.def("IsPureMeleeClass", &Lua_Mob::IsPureMeleeClass)
.def("IsRoamer", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRoamer)
.def("IsRooted", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRooted)
.def("IsRunning", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRunning)
@ -3753,6 +3780,7 @@ luabind::scope lua_register_mob() {
.def("IsTemporaryPet", &Lua_Mob::IsTemporaryPet)
.def("IsTrackable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTrackable)
.def("IsWarriorClass", &Lua_Mob::IsWarriorClass)
.def("IsWisdomCasterClass", &Lua_Mob::IsWisdomCasterClass)
.def("Kill", (void(Lua_Mob::*)(void))&Lua_Mob::Kill)
.def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize)
.def("Message", &Lua_Mob::Message)

View File

@ -586,6 +586,10 @@ public:
void RestoreEndurance();
void RestoreHealth();
void RestoreMana();
std::string GetArchetypeName();
bool IsIntelligenceCasterClass();
bool IsPureMeleeClass();
bool IsWisdomCasterClass();
};
#endif

View File

@ -489,23 +489,12 @@ int64 Merc::CalcBaseHP()
int64 Merc::CalcMaxMana()
{
switch(GetCasterClass())
{
case 'I':
case 'W': {
if (IsIntelligenceCasterClass() || IsWisdomCasterClass()) {
max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
break;
}
case 'N': {
} else {
max_mana = 0;
break;
}
default: {
LogDebug("Invalid Class [{}] in CalcMaxMana", GetCasterClass());
max_mana = 0;
break;
}
}
if (max_mana < 0) {
max_mana = 0;
}
@ -565,12 +554,13 @@ int64 Merc::CalcManaRegen()
regen = mana_regen + spellbonuses.ManaRegen + itembonuses.ManaRegen;
}
if(GetCasterClass() == 'I')
if (IsIntelligenceCasterClass()) {
regen += (itembonuses.HeroicINT / 25);
else if(GetCasterClass() == 'W')
} else if (IsWisdomCasterClass()) {
regen += (itembonuses.HeroicWIS / 25);
else
} else {
regen = 0;
}
//AAs
regen += aabonuses.ManaRegen;
@ -581,14 +571,11 @@ int64 Merc::CalcManaRegen()
int64 Merc::CalcManaRegenCap()
{
int64 cap = RuleI(Character, ItemManaRegenCap) + aabonuses.ItemManaRegenCap;
switch(GetCasterClass())
{
case 'I':
if (IsIntelligenceCasterClass()) {
cap += (itembonuses.HeroicINT / 25);
break;
case 'W':
} else if (IsWisdomCasterClass()) {
cap += (itembonuses.HeroicWIS / 25);
break;
}
return (cap * RuleI(Character, ManaRegenMultiplier) / 100);
@ -1166,7 +1153,7 @@ void Merc::AI_Process() {
float newX = 0;
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != Archetype::Caster) {
RunTo(newX, newY, newZ);
return;
}
@ -1314,7 +1301,7 @@ void Merc::AI_Process() {
if(AI_EngagedCastCheck()) {
MercMeditate(false);
}
else if(GetArchetype() == ARCHETYPE_CASTER)
else if(GetArchetype() == Archetype::Caster)
MercMeditate(true);
}
}
@ -1337,7 +1324,7 @@ void Merc::AI_Process() {
//TODO: Implement passive stances.
//if(GetStance() != MercStancePassive) {
if(!AI_IdleCastCheck() && !IsCasting()) {
if(GetArchetype() == ARCHETYPE_CASTER) {
if(GetArchetype() == Archetype::Caster) {
MercMeditate(true);
}
}
@ -1792,7 +1779,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) {
if( !IsImmuneToSpell(selectedMercSpell.spellid, this)
&& (CanBuffStack(selectedMercSpell.spellid, mercLevel, true) >= 0)) {
if( GetArchetype() == ARCHETYPE_MELEE && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) {
if( GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) {
continue;
}
@ -1819,7 +1806,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) {
if( !tar->IsImmuneToSpell(selectedMercSpell.spellid, this)
&& (tar->CanBuffStack(selectedMercSpell.spellid, mercLevel, true) >= 0)) {
if( tar->GetArchetype() == ARCHETYPE_MELEE && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) {
if( tar->GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) {
continue;
}

View File

@ -940,19 +940,16 @@ int Mob::_GetFearSpeed() const {
return speed_mod;
}
int64 Mob::CalcMaxMana() {
switch (GetCasterClass()) {
case 'I':
max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
break;
case 'W':
max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
break;
case 'N':
default:
max_mana = 0;
break;
int64 Mob::CalcMaxMana()
{
if (IsIntelligenceCasterClass()) {
max_mana = (((GetINT() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
} else if (IsWisdomCasterClass()) {
max_mana = (((GetWIS() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
} else {
max_mana = 0;
}
if (max_mana < 0) {
max_mana = 0;
}
@ -981,90 +978,155 @@ int64 Mob::GetSpellHPBonuses() {
return spell_hp;
}
char Mob::GetCasterClass() const {
switch(class_)
{
case Class::Cleric:
case Class::Paladin:
case Class::Ranger:
case Class::Druid:
case Class::Shaman:
case Class::Beastlord:
case Class::ClericGM:
case Class::PaladinGM:
case Class::RangerGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::BeastlordGM:
return 'W';
break;
case Class::ShadowKnight:
case Class::Bard:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return 'I';
break;
default:
return 'N';
break;
bool Mob::IsIntelligenceCasterClass() const
{
switch (GetClass()) {
case Class::ShadowKnight:
case Class::Bard:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return true;
}
return false;
}
uint8 Mob::GetArchetype() const {
switch(class_)
{
case Class::Paladin:
case Class::Ranger:
case Class::ShadowKnight:
case Class::Bard:
case Class::Beastlord:
case Class::PaladinGM:
case Class::RangerGM:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::BeastlordGM:
return ARCHETYPE_HYBRID;
break;
case Class::Cleric:
case Class::Druid:
case Class::Shaman:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ClericGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return ARCHETYPE_CASTER;
break;
case Class::Warrior:
case Class::Monk:
case Class::Rogue:
case Class::Berserker:
case Class::WarriorGM:
case Class::MonkGM:
case Class::RogueGM:
case Class::BerserkerGM:
return ARCHETYPE_MELEE;
break;
default:
return ARCHETYPE_HYBRID;
break;
bool Mob::IsPureMeleeClass() const
{
switch (GetClass()) {
case Class::Warrior:
case Class::Monk:
case Class::Rogue:
case Class::Berserker:
case Class::WarriorGM:
case Class::MonkGM:
case Class::RogueGM:
case Class::BerserkerGM:
return true;
default:
break;
}
return false;
}
bool Mob::IsWarriorClass() const
{
switch (GetClass()) {
case Class::Warrior:
case Class::Paladin:
case Class::Ranger:
case Class::ShadowKnight:
case Class::Monk:
case Class::Bard:
case Class::Rogue:
case Class::Beastlord:
case Class::Berserker:
case Class::WarriorGM:
case Class::PaladinGM:
case Class::RangerGM:
case Class::ShadowKnightGM:
case Class::MonkGM:
case Class::BardGM:
case Class::RogueGM:
case Class::BeastlordGM:
case Class::BerserkerGM:
return true;
default:
break;
}
return false;
}
bool Mob::IsWisdomCasterClass() const
{
switch (GetClass()) {
case Class::Cleric:
case Class::Paladin:
case Class::Ranger:
case Class::Druid:
case Class::Shaman:
case Class::Beastlord:
case Class::ClericGM:
case Class::PaladinGM:
case Class::RangerGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::BeastlordGM:
return true;
}
return false;
}
uint8 Mob::GetArchetype() const
{
switch (GetClass()) {
case Class::Paladin:
case Class::Ranger:
case Class::ShadowKnight:
case Class::Bard:
case Class::Beastlord:
case Class::PaladinGM:
case Class::RangerGM:
case Class::ShadowKnightGM:
case Class::BardGM:
case Class::BeastlordGM:
return Archetype::Hybrid;
case Class::Cleric:
case Class::Druid:
case Class::Shaman:
case Class::Necromancer:
case Class::Wizard:
case Class::Magician:
case Class::Enchanter:
case Class::ClericGM:
case Class::DruidGM:
case Class::ShamanGM:
case Class::NecromancerGM:
case Class::WizardGM:
case Class::MagicianGM:
case Class::EnchanterGM:
return Archetype::Caster;
case Class::Warrior:
case Class::Monk:
case Class::Rogue:
case Class::Berserker:
case Class::WarriorGM:
case Class::MonkGM:
case Class::RogueGM:
case Class::BerserkerGM:
return Archetype::Melee;
default:
break;
}
return Archetype::Hybrid;
}
const std::string& Mob::GetArchetypeName()
{
switch (GetArchetype()) {
case Archetype::Hybrid:
return "Hybrid";
case Archetype::Caster:
return "Caster";
case Archetype::Melee:
return "Melee";
default:
break;
}
return "Hybrid";
}
void Mob::SetSpawnLastNameByClass(NewSpawn_Struct* ns)
@ -4586,39 +4648,6 @@ bool Mob::CanThisClassTripleAttack() const
}
}
bool Mob::IsWarriorClass(void) const
{
switch(GetClass())
{
case Class::Warrior:
case Class::WarriorGM:
case Class::Rogue:
case Class::RogueGM:
case Class::Monk:
case Class::MonkGM:
case Class::Paladin:
case Class::PaladinGM:
case Class::ShadowKnight:
case Class::ShadowKnightGM:
case Class::Ranger:
case Class::RangerGM:
case Class::Beastlord:
case Class::BeastlordGM:
case Class::Berserker:
case Class::BerserkerGM:
case Class::Bard:
case Class::BardGM:
{
return true;
}
default:
{
return false;
}
}
}
bool Mob::CanThisClassParry(void) const
{
if(!IsClient()) {

View File

@ -838,8 +838,11 @@ public:
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f);
bool IsWarriorClass() const;
char GetCasterClass() const;
bool IsIntelligenceCasterClass() const;
bool IsPureMeleeClass() const;
bool IsWisdomCasterClass() const;
uint8 GetArchetype() const;
const std::string& GetArchetypeName();
void SetZone(uint32 zone_id, uint32 instance_id);
void SendStatsWindow(Client* c, bool use_window);
void ShowStats(Client* client);

View File

@ -2756,35 +2756,28 @@ void NPC::SetSwarmTarget(int target_id)
int64 NPC::CalcMaxMana()
{
if (npc_mana == 0) {
switch (GetCasterClass()) {
case 'I':
max_mana = (((GetINT() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
break;
case 'W':
max_mana = (((GetWIS() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
break;
default:
max_mana = 0;
break;
if (IsIntelligenceCasterClass()) {
max_mana = (((GetINT() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
} else if (IsWisdomCasterClass()) {
max_mana = (((GetWIS() / 2) + 1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana;
} else {
max_mana = 0;
}
if (max_mana < 0) {
max_mana = 0;
}
return max_mana;
}
else {
switch (GetCasterClass()) {
case 'I':
max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana;
break;
case 'W':
max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana;
break;
default:
max_mana = 0;
break;
} else {
if (IsIntelligenceCasterClass()) {
max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana;
} else if (IsWisdomCasterClass()) {
max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana;
} else {
max_mana = 0;
}
if (max_mana < 0) {
max_mana = 0;
}

View File

@ -3448,6 +3448,26 @@ void Perl_Mob_RestoreMana(Mob* self)
self->RestoreMana();
}
std::string Perl_Mob_GetArchetypeName(Mob* self)
{
return self->GetArchetypeName();
}
bool Perl_Mob_IsIntelligenceCasterClass(Mob* self)
{
return self->IsIntelligenceCasterClass();
}
bool Perl_Mob_IsPureMeleeClass(Mob* self)
{
return self->IsPureMeleeClass();
}
bool Perl_Mob_IsWisdomCasterClass(Mob* self)
{
return self->IsWisdomCasterClass();
}
void perl_register_mob()
{
perl::interpreter perl(PERL_GET_THX);
@ -3620,6 +3640,7 @@ void perl_register_mob()
package.add("GetAggroRange", &Perl_Mob_GetAggroRange);
package.add("GetAllowBeneficial", &Perl_Mob_GetAllowBeneficial);
package.add("GetAppearance", &Perl_Mob_GetAppearance);
package.add("GetArchetypeName", &Perl_Mob_GetArchetypeName);
package.add("GetArmorTint", &Perl_Mob_GetArmorTint);
package.add("GetAssistRange", &Perl_Mob_GetAssistRange);
package.add("GetBaseGender", &Perl_Mob_GetBaseGender);
@ -3843,6 +3864,7 @@ void perl_register_mob()
package.add("IsFindable", &Perl_Mob_IsFindable);
package.add("IsHorse", &Perl_Mob_IsHorse);
package.add("IsImmuneToSpell", &Perl_Mob_IsImmuneToSpell);
package.add("IsIntelligenceCasterClass", &Perl_Mob_IsIntelligenceCasterClass);
package.add("IsInvisible", (bool(*)(Mob*))&Perl_Mob_IsInvisible);
package.add("IsInvisible", (bool(*)(Mob*, Mob*))&Perl_Mob_IsInvisible);
package.add("IsMeleeDisabled", &Perl_Mob_IsMeleeDisabled);
@ -3861,6 +3883,7 @@ void perl_register_mob()
package.add("IsPetOwnerClient", &Perl_Mob_IsPetOwnerClient);
package.add("IsPetOwnerNPC", &Perl_Mob_IsPetOwnerNPC);
package.add("IsPlayerCorpse", &Perl_Mob_IsPlayerCorpse);
package.add("IsPureMeleeClass", &Perl_Mob_IsPureMeleeClass);
package.add("IsRoamer", &Perl_Mob_IsRoamer);
package.add("IsRooted", &Perl_Mob_IsRooted);
package.add("IsRunning", &Perl_Mob_IsRunning);
@ -3873,6 +3896,7 @@ void perl_register_mob()
package.add("IsTrackable", &Perl_Mob_IsTrackable);
package.add("IsTrap", &Perl_Mob_IsTrap);
package.add("IsWarriorClass", &Perl_Mob_IsWarriorClass);
package.add("IsWisdomCasterClass", &Perl_Mob_IsWisdomCasterClass);
package.add("Kill", &Perl_Mob_Kill);
package.add("MakePet", (void(*)(Mob*, uint16, const char*))&Perl_Mob_MakePet);
package.add("MakePet", (void(*)(Mob*, uint16, const char*, const char*))&Perl_Mob_MakePet);

View File

@ -456,7 +456,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if(GetClass() == Class::Bard)
break;
if(IsManaTapSpell(spell_id)) {
if(GetCasterClass() != 'N') {
if (!IsPureMeleeClass()) {
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Current Mana: %+i", effect_value);
#endif
@ -578,12 +578,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
GetPet()->BuffFadeByEffect(SE_Charm);
}
}
CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), x, y, z, heading, 0, EvacToSafeCoords);
} else {
GMMove(x, y, z, heading);
}
if (RuleB(Spells, EvacClearAggroInSameZone)) {
entity_list.ClearAggro(this);
}
@ -1058,7 +1058,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
cd->hit_heading = action->hit_heading;
CastToClient()->QueuePacket(action_packet);
if (caster->IsClient() && caster != this) {
caster->CastToClient()->QueuePacket(action_packet);
}
@ -1068,7 +1068,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if (caster->IsClient() && caster != this) {
caster->CastToClient()->QueuePacket(message_packet);
}
CastToClient()->SetBindPoint(spells[spell_id].base_value[i] - 1);
Save();
safe_delete(action_packet);
@ -1105,7 +1105,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
}
break;
}
DispelMagic(caster, spell_id, effect_value);
break;
}
@ -7369,7 +7369,7 @@ bool Mob::PassLimitClass(uint32 Classes_, uint16 Class_)
return false;
}
void Mob::DispelMagic(Mob* caster, uint16 spell_id, int effect_value)
void Mob::DispelMagic(Mob* caster, uint16 spell_id, int effect_value)
{
for (int slot = 0; slot < GetMaxTotalSlots(); slot++) {
if (

View File

@ -224,8 +224,12 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
if(GetTarget() && IsManaTapSpell(spell_id)) {
// If melee, block if ManaTapsOnAnyClass rule is false
// if caster, block if ManaTapsRequireNPCMana and no mana
bool melee_block = !RuleB(Spells, ManaTapsOnAnyClass);
bool caster_block = (GetTarget()->GetCasterClass() != 'N' && RuleB(Spells, ManaTapsRequireNPCMana) && GetTarget()->GetMana() == 0);
bool melee_block = !RuleB(Spells, ManaTapsOnAnyClass);
bool caster_block = (
!GetTarget()->IsPureMeleeClass() &&
RuleB(Spells, ManaTapsRequireNPCMana) &&
GetTarget()->GetMana() == 0
);
if (melee_block || caster_block) {
InterruptSpell(TARGET_NO_MANA, 0x121, spell_id);
return false;
@ -1105,10 +1109,10 @@ bool Client::CheckFizzle(uint16 spell_id)
// CALCULATE EFFECTIVE CASTING STAT VALUE
float prime_stat_reduction = 0.0f;
if (GetCasterClass() == 'W') {
prime_stat_reduction = (GetWIS() - 75) / 10.0;
} else if (GetCasterClass() == 'I') {
if (IsIntelligenceCasterClass()) {
prime_stat_reduction = (GetINT() - 75) / 10.0;
} else if (IsWisdomCasterClass()) {
prime_stat_reduction = (GetWIS() - 75) / 10.0;
}
// BARDS ARE SPECIAL - they add both CHA and DEX mods to get casting rates similar to full casters without spec skill
@ -1183,10 +1187,10 @@ bool Client::CheckFizzle(uint16 spell_id)
// if you have high int/wis you fizzle less, you fizzle more if you are stupid
if (GetClass() == Class::Bard) {
diff -= (GetCHA() - 110) / 20.0;
} else if (GetCasterClass() == 'W') {
diff -= (GetWIS() - 125) / 20.0;
} else if (GetCasterClass() == 'I') {
} else if (IsIntelligenceCasterClass()) {
diff -= (GetINT() - 125) / 20.0;
} else if (IsWisdomCasterClass()) {
diff -= (GetWIS() - 125) / 20.0;
}
// base fizzlechance is lets say 5%, we can make it lower for AA skills or whatever