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

View File

@ -4,10 +4,13 @@
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/mysql"
"/usr/include/mysql",
"/usr/local/include",
"/usr/include",
"/usr/include/lua5.1"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"compilerPath": "/usr/bin/c++",
"cStandard": "c11",
"cppStandard": "c++17"
}

View File

@ -163,6 +163,7 @@ RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishin
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
RULE_INT(Character, PVPRespawnManaPercent, 100, "How much mana to respawn with")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@ -239,6 +240,14 @@ RULE_INT(World, ExpansionSettings, 16383, "Sets the expansion settings for the s
RULE_BOOL(World, UseClientBasedExpansionSettings, true, "If true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using")
RULE_INT(World, PVPSettings, 0, "Sets the PVP settings for the server. 1=Rallos Zek RuleSet, 2=Tallon/Vallon Zek Ruleset, 4=Sullon Zek Ruleset, 6=Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. NOTE: edit IsAttackAllowed in Zone-table to accomodate for these rules")
RULE_INT(World, PVPMinLevel, 0, "Minimum level to pvp")
RULE_BOOL(World, PVPUseDeityBasedPVP, false, "In PvP, deity is used to determine if a player can attack another.")
RULE_BOOL(World, PVPUseTeamsBySizeBasedPVP, false, "In PVP, size of a race is used to determine if a player can attack another.")
RULE_INT(World, PVPLevelDifference, 0, "In PvP, if value is greater than 0, players with a difference greater than value will not be attackable")
RULE_INT(World, PVPLoseExperienceLevelDifference, 0, "In PvP, if value is greater than 0, players lose experience if killed by a player within level difference")
RULE_INT(World, PVPPetDamageMitigation, 100, "In PvP, pet damage is mitigated by this amount")
RULE_INT(World, PVPMeleeMitigation, 67, "In PvP, melee is mitigated by this amount")
RULE_INT(World, PVPSpellMitigation, 67, "In PvP, spells are mitigated by this amount")
RULE_INT(World, PVPRangedMitigation, 80, "In PvP, ranged attacks (archery/throwing) is mitigated by this amount")
RULE_BOOL (World, IsGMPetitionWindowEnabled, false, "Setting whether the GM petition window is available")
RULE_INT (World, FVNoDropFlag, 0, "Sets the Firiona Vie settings on the client, allowing trading of no-drop items. 1=for all players, 2=for GM only")
RULE_BOOL (World, IPLimitDisconnectAll, false, "Disconnect all current clients by IP if they go over the IP limit. This should allow people to quickly reconnect in the case of dead sessions waiting to timeout")
@ -390,6 +399,7 @@ RULE_BOOL(Spells, AllowItemTGB, false, "Target group buff (/tgb) doesn't work wi
RULE_BOOL(Spells, NPCInnateProcOverride, true, "NPC innate procs override the target type to single target")
RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximum targets for rains")
RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs")
RULE_INT(Spells, PVPRootBreakFromSpells, 75, "Chance for root to break when cast on by a client")
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)

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
{

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();

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;
}

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

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;