Added PVP based logic

This commit is contained in:
xackery
2021-01-14 10:09:47 -08:00
parent 0f5a7e1317
commit 64b64222d1
7 changed files with 149 additions and 44 deletions
+2 -28
View File
@@ -527,22 +527,7 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
c1 = mob1->CastToClient();
c2 = mob2->CastToClient();
if // if both are pvp they can fight
(
c1->GetPVP() &&
c2->GetPVP()
)
return true;
else if // if they're dueling they can go at it
(
c1->IsDueling() &&
c2->IsDueling() &&
c1->GetDuelTarget() == c2->GetID() &&
c2->GetDuelTarget() == c1->GetID()
)
return true;
else
return false;
return c1->CanPvP(c2);
}
else if(_NPC(mob2)) // client vs npc
{
@@ -698,18 +683,7 @@ bool Mob::IsBeneficialAllowed(Mob *target)
c1 = mob1->CastToClient();
c2 = mob2->CastToClient();
if(c1->GetPVP() == c2->GetPVP())
return true;
else if // if they're dueling they can heal each other too
(
c1->IsDueling() &&
c2->IsDueling() &&
c1->GetDuelTarget() == c2->GetID() &&
c2->GetDuelTarget() == c1->GetID()
)
return true;
else
return false;
return c1->CanPvP(c2);
}
else if(_NPC(mob2)) // client to npc
{
+39 -12
View File
@@ -1574,11 +1574,15 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, EQ::skills::Skill
//should this be applied to all damage? comments sound like some is for spell DMG
//patch notes on PVP reductions only mention archery/throwing ... not normal dmg
if (other && other->IsClient() && (other != this) && damage > 0) {
int PvPMitigation = 100;
if (attack_skill == EQ::skills::SkillArchery || attack_skill == EQ::skills::SkillThrowing)
PvPMitigation = 80;
else
PvPMitigation = 67;
int PvPMitigation = RuleI(World, PVPMeleeMitigation);
if (attack_skill == EQ::skills::SkillAbjuration || //spells
attack_skill == EQ::skills::SkillAlteration ||
attack_skill == EQ::skills::SkillConjuration ||
attack_skill == EQ::skills::SkillDivination ||
attack_skill == EQ::skills::SkillEvocation) PvPMitigation = RuleI(World, PVPSpellMitigation);
if (attack_skill == EQ::skills::SkillArchery || //ranged
attack_skill == EQ::skills::SkillThrowing) PvPMitigation = RuleI(World, PVPRangedMitigation);
damage = std::max((damage * PvPMitigation) / 100, 1);
}
@@ -1754,7 +1758,27 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill
{
if (killerMob->IsClient())
{
exploss = 0;
int pvpleveldifference = 0;
if (RuleI(World, PVPSettings) == 4)
pvpleveldifference = 5; //Sullon Zek
if (RuleI(World, PVPLoseExperienceLevelDifference) > 0)
pvpleveldifference = RuleI(World, PVPLoseExperienceLevelDifference);
if (pvpleveldifference > 0) {
int level_difference = 0;
if (GetLevel() > killerMob->GetLevel())
level_difference = GetLevel() - killerMob->GetLevel();
else
level_difference = killerMob->GetLevel() - GetLevel();
if (level_difference > pvpleveldifference)
exploss = 0;
}
else
{
exploss = 0;
}
}
else if (killerMob->GetOwner() && killerMob->GetOwner()->IsClient())
{
@@ -2068,14 +2092,11 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
other->AddToHateList(this, hate);
LogCombat("Final damage against [{}]: [{}]", other->GetName(), my_hit.damage_done);
if (other->IsClient() && IsPet() && GetOwner()->IsClient()) {
//pets do half damage to clients in pvp
my_hit.damage_done /= 2;
if (my_hit.damage_done < 1)
my_hit.damage_done = 1;
my_hit.damage_done = std::max(my_hit.damage_done * RuleI(World, PVPPetDamageMitigation) / 100, 1);
}
LogCombat("Final damage against [{}]: [{}]", other->GetName(), my_hit.damage_done);
}
else {
my_hit.damage_done = DMG_INVULNERABLE;
@@ -4976,6 +4997,12 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot) {
int BreakChance = RuleI(Spells, RootBreakFromSpells);
if (attacker && attacker->IsClient() && IsClient()) {
if (RuleI(World, PVPSettings) > 0) BreakChance = 75; //All PVP servers is default 75% chance for root to break
if (RuleI(Spells, PVPRootBreakFromSpells) > 0) BreakChance = RuleI(Spells, PVPRootBreakFromSpells);
}
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance / 100;
int level_diff = attacker->GetLevel() - GetLevel();
+79
View File
@@ -10009,4 +10009,83 @@ void Client::Fling(float value, float target_x, float target_y, float target_z,
outapp_fling->priority = 6;
FastQueuePacket(&outapp_fling);
}
}
//CanPvP returns true if provided player can attack this player
bool Client::CanPvP(Client *c) {
if (c == nullptr)
return false;
//Dueling overrides normal PvP logic
if (IsDueling() && c->IsDueling() && GetDuelTarget() == c->GetID() && c->GetDuelTarget() == GetID())
return true;
//If PVPLevelDifference is enabled, only allow PVP if players are of proper range
int rule_level_diff = 0;
if (RuleI(World, PVPSettings) == 4)
rule_level_diff = 100; //Sullon Zek rules can attack anyone of opposing deity.
if (RuleI(World, PVPLevelDifference) > 0)
rule_level_diff = RuleI(World, PVPLevelDifference);
if (rule_level_diff > 0) {
int level_diff = 0;
if (c->GetLevel() > GetLevel())
level_diff = c->GetLevel() - GetLevel();
else
level_diff = GetLevel() - c->GetLevel();
if (level_diff > rule_level_diff)
return false;
}
//players need to be proper level for pvp
int rule_min_level = 0;
if (RuleI(World, PVPSettings) == 4)
rule_min_level = 6;
if (RuleI(World, PVPMinLevel) > 0)
rule_min_level = RuleI(World, PVPMinLevel);
if (rule_min_level > 0 && (GetLevel() < rule_min_level || c->GetLevel() < rule_min_level))
return false;
//is deity pvp rule enabled? If so, if we're same alignment, don't allow pvp
if ((RuleI(World, PVPSettings) == 4 || RuleB(World, PVPUseDeityBasedPVP)) && GetAlignment() == c->GetAlignment())
return false;
//VZTZ Zek PVP Setting
if ((RuleI(World, PVPSettings) == 2 || RuleB(World, PVPUseTeamsBySizeBasedPVP)) && GetPVPRaceTeamBySize() == c->GetPVPRaceTeamBySize())
return false;
//Check if players are flagged pvp. This may need to be removed later
if (!GetPVP() || !c->GetPVP()) return false;
return true;
}
//GetAlignment returns 0 = neutral, 1 = good, 2 = evil, used for pvp sullon zek rules
int Client::GetAlignment() {
if (GetDeity() == EQ::deity::DeityErollisiMarr ||
GetDeity() == EQ::deity::DeityMithanielMarr ||
GetDeity() == EQ::deity::DeityRodcetNife ||
GetDeity() == EQ::deity::DeityQuellious ||
GetDeity() == EQ::deity::DeityTunare) return 1; //good
if (GetDeity() == EQ::deity::DeityBertoxxulous ||
GetDeity() == EQ::deity::DeityCazicThule ||
GetDeity() == EQ::deity::DeityInnoruuk ||
GetDeity() == EQ::deity::DeityRallosZek) return 2; //evil
return 0; //neutral
}
//GetPVPRaceSize returns based on racial divisions
int Client::GetPVPRaceTeamBySize() {
if (GetRace() == HUMAN || GetRace() == BARBARIAN || GetRace() == ERUDITE || GetRace() == DRAKKIN)
return 1;
if (GetRace() == GNOME || GetRace() == HALFLING || GetRace() == DWARF || GetRace() == FROGLOK)
return 2;
if (GetRace() == HIGH_ELF || GetRace() == WOOD_ELF || GetRace() == HALF_ELF || GetRace() == VAHSHIR)
return 3;
if (GetRace() == DARK_ELF || GetRace() == OGRE || GetRace() == TROLL || GetRace() == IKSAR)
return 4;
return 1;
}
+4 -1
View File
@@ -770,6 +770,9 @@ public:
bool TradeskillExecute(DBTradeskillRecipe_Struct *spec);
void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQ::skills::SkillType tradeskill);
void InitInnates();
bool CanPvP(Client * c);
int GetAlignment();
int GetPVPRaceTeamBySize();
void GMKill();
inline bool IsMedding() const {return medding;}
@@ -903,7 +906,7 @@ public:
void IncStats(uint8 type,int16 increase_val);
void DropItem(int16 slot_id, bool recurse = true);
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field
void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false);
+10 -1
View File
@@ -2077,7 +2077,16 @@ void Client::HandleRespawnFromHover(uint32 Option)
CalcBonuses();
SetHP(GetMaxHP());
SetMana(GetMaxMana());
if (GetPVP()) {
int mana_pct = 100;
if (RuleI(World, PVPSettings) > 0)
mana_pct = 0; //All PVP servers spawn you with zero mana
if (RuleI(Character, PVPRespawnManaPercent) != 100) //override mana if it's not 100%
mana_pct = RuleI(Character, PVPRespawnManaPercent);
SetMana(std::max(GetMaxMana() * mana_pct / 100, 0));
} else {
SetMana(GetMaxMana());
}
SetEndurance(GetMaxEndurance());
m_Position.x = chosen->x;