Browse Source

PVP Basics

PVP Melee attack, spell attack is possible now.  Originally the PVPFlag did not function correctly.  Added a PVP Level Range rule.

Fixes #33
Image 4 years ago
parent
commit
7c960a9d74

+ 18 - 6
EQ2/source/WorldServer/Combat.cpp

@@ -105,9 +105,6 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) {
 			target = ((NPC*)target)->GetOwner();
 	}
 
-	bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool();
-	LogWrite(COMBAT__DEBUG, 3, "PVP", "PVP is: %s", pvp_allowed ? "ENABLED!" : "Disabled.");
-
 	if (attacker == target) {
 		LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: attacker tried to attack himself or his pet.");
 		return false;
@@ -123,9 +120,24 @@ bool Entity::AttackAllowed(Entity* target, float distance, bool range_attack) {
 		return false;
 	}
 
-	if (!pvp_allowed && (attacker->IsPlayer() && target->IsPlayer())) {
-		LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: pvp is not allowed");
-		return false;
+	if (attacker->IsPlayer() && target->IsPlayer())
+	{
+		bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool();
+		if (!pvp_allowed) {
+			LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: pvp is not allowed");
+			return false;
+		}
+		else
+		{
+			sint32 pvpLevelRange = rule_manager.GetGlobalRule(R_PVP, LevelRange)->GetSInt32();
+			int32 attackerLevel = attacker->GetLevel();
+			int32 defenderLevel = target->GetLevel();
+			if ((sint32)abs((sint32)attackerLevel - (sint32)defenderLevel) > pvpLevelRange)
+			{
+				LogWrite(COMBAT__DEBUG, 3, "AttackAllowed", "Failed to attack: pvp range of %i exceeded abs(%i-%i).", pvpLevelRange, attackerLevel, defenderLevel);
+				return false;
+			}
+		}
 	}
 
 	if (target->GetHP() <= 0) {

+ 1 - 0
EQ2/source/WorldServer/Rules/Rules.cpp

@@ -204,6 +204,7 @@ RuleManager::RuleManager() {
 
 	/* PVP */
 	RULE_INIT(R_PVP, AllowPVP, "0");
+	RULE_INIT(R_PVP, LevelRange, "4");
 
 	/* SPAWN */
 	RULE_INIT(R_Spawn, SpeedMultiplier, "300"); // note: this value was 1280 until 6/1/2009, then was 600 til Sep 2009, when it became 300...?

+ 1 - 0
EQ2/source/WorldServer/Rules/Rules.h

@@ -69,6 +69,7 @@ enum RuleType {
 
 	/* PVP */
 	AllowPVP,
+	LevelRange,
 
 	/* SPAWN */
 	SpeedMultiplier,

+ 10 - 4
EQ2/source/WorldServer/SpellProcess.cpp

@@ -21,6 +21,7 @@
 #include "../common/Log.h"
 #include "Tradeskills/Tradeskills.h"
 #include "ClientPacketFunctions.h"
+#include "Rules/Rules.h"
 
 extern MasterSpellList master_spell_list;
 extern MasterSkillList master_skill_list;
@@ -28,6 +29,7 @@ extern ConfigReader configReader;
 extern LuaInterface* lua_interface;
 extern Commands commands;
 extern World world;
+extern RuleManager rule_manager;
 
 SpellProcess::SpellProcess(){
 	last_checked_time = 0;
@@ -1052,10 +1054,14 @@ void SpellProcess::ProcessSpell(ZoneServer* zone, Spell* spell, Entity* caster,
 
 				if ((target->IsPlayer() || target->IsBot()) && (caster->IsPlayer() || caster->IsBot())) 
 				{
-					LogWrite(SPELL__DEBUG, 1, "Spell", "%s: Target (%s) is player and not attackable.", spell->GetName(), target->GetName());
-					zone->SendSpellFailedPacket(client, SPELL_ERROR_NOT_AN_ENEMY);
-					safe_delete(lua_spell);
-					return;
+					bool attackAllowed = (Entity*)caster->AttackAllowed((Entity*)target, 0);
+					if (!attackAllowed)
+					{
+						LogWrite(SPELL__DEBUG, 1, "Spell", "%s: Target (%s) is player and not attackable.", spell->GetName(), target->GetName());
+						zone->SendSpellFailedPacket(client, SPELL_ERROR_NOT_AN_ENEMY);
+						safe_delete(lua_spell);
+						return;
+					}
 				}
 
 				if (target->IsPet() && ((NPC*)target)->GetOwner() && ((NPC*)target)->GetOwner() == caster) {

+ 3 - 0
EQ2/source/WorldServer/client.cpp

@@ -896,6 +896,9 @@ bool Client::HandlePacket(EQApplicationPacket *app) {
 					firstlogin = zar->isFirstLogin ( );
 					LogWrite(ZONE__INFO, 0, "ZoneAuth", "Access Key: %u, Character Name: %s, Account ID: %u, Client Data Version: %u", zar->GetAccessKey(), zar->GetCharacterName(), zar->GetAccountID(), version);
 					if(database.loadCharacter(zar->GetCharacterName(), zar->GetAccountID(), this)){
+						bool pvp_allowed = rule_manager.GetGlobalRule(R_PVP, AllowPVP)->GetBool();
+						if (pvp_allowed)
+							this->GetPlayer()->SetAttackable(1);
 						version = request->getType_int16_ByName("version");
 						MDeletePlayer.writelock(__FUNCTION__, __LINE__);
 						Client* client = zone_list.GetClientByCharName(player->GetName());