Core/Player: Initial War Mode support

Port From (https://github.com/TrinityCore/TrinityCore/commit/b821a729733db0d3742b4aefe05e5a8305724f66)
This commit is contained in:
hondacrx
2022-01-07 21:49:50 -05:00
parent 73b456b5a0
commit 4c922933de
10 changed files with 304 additions and 26 deletions
+6 -4
View File
@@ -192,6 +192,8 @@ namespace Game.Entities
GetMap().SendZoneDynamicInfo(newZone, this);
UpdateWarModeAuras();
UpdateHostileAreaState(zone);
if (zone.HasFlag(AreaFlags.Capital)) // Is in a capital city
@@ -247,15 +249,15 @@ namespace Game.Entities
{
if (InBattleground() || area.HasFlag(AreaFlags.Combat) || (area.PvpCombatWorldStateID != -1 && Global.WorldMgr.GetWorldState((WorldStates)area.PvpCombatWorldStateID) != 0))
pvpInfo.IsInHostileArea = true;
else if (Global.WorldMgr.IsPvPRealm() || area.HasFlag(AreaFlags.Unk3))
else if (IsWarModeLocalActive() || area.HasFlag(AreaFlags.Unk3))
{
if (area.HasFlag(AreaFlags.ContestedArea))
pvpInfo.IsInHostileArea = Global.WorldMgr.IsPvPRealm();
pvpInfo.IsInHostileArea = IsWarModeLocalActive();
else
{
FactionTemplateRecord factionTemplate = GetFactionTemplateEntry();
if (factionTemplate == null || factionTemplate.FriendGroup.HasAnyFlag(area.FactionGroupMask))
pvpInfo.IsInHostileArea = false;
pvpInfo.IsInHostileArea = false; // friend area are considered hostile if war mode is active
else if (factionTemplate.EnemyGroup.HasAnyFlag(area.FactionGroupMask))
pvpInfo.IsInHostileArea = true;
else
@@ -282,7 +284,7 @@ namespace Game.Entities
}
// Treat players having a quest flagging for PvP as always in hostile area
pvpInfo.IsHostile = pvpInfo.IsInHostileArea || HasPvPForcingQuest();
pvpInfo.IsHostile = pvpInfo.IsInHostileArea || HasPvPForcingQuest() || IsWarModeLocalActive();
}
public ZonePVPTypeOverride GetOverrideZonePVPType() { return (ZonePVPTypeOverride)(uint)m_activePlayerData.OverrideZonePVPType; }
+104 -6
View File
@@ -2887,6 +2887,12 @@ namespace Game.Entities
packet.AddState(2491, 0xF); // 9
}
// Horde War Mode bonus
packet.AddState(17042, 10 + (Global.WorldMgr.GetWarModeDominantFaction() == TeamId.Alliance ? Global.WorldMgr.GetWarModeOutnumberedFactionReward() : 0));
// Alliance War Mode bonus
packet.AddState(17043, 10 + (Global.WorldMgr.GetWarModeDominantFaction() == TeamId.Horde ? Global.WorldMgr.GetWarModeOutnumberedFactionReward() : 0));
// insert <field> <value>
switch (zoneid)
{
@@ -5068,15 +5074,101 @@ namespace Game.Entities
return true;
}
public void SetWarModeDesired(bool enabled)
{
// Only allow to toggle on when in stormwind/orgrimmar, and to toggle off in any rested place.
// Also disallow when in combat
if ((enabled == IsWarModeDesired()) || IsInCombat() || !HasPlayerFlag(PlayerFlags.Resting))
return;
if (enabled && !CanEnableWarModeInArea())
return;
// Don't allow to chang when aura SPELL_PVP_RULES_ENABLED is on
if (HasAura(PlayerConst.SpellPvpRulesEnabled))
return;
if (enabled)
{
AddPlayerFlag(PlayerFlags.WarModeDesired);
TogglePvpTalents(true);
SetPvP(true);
}
else
{
RemovePlayerFlag(PlayerFlags.WarModeDesired);
TogglePvpTalents(false);
SetPvP(false);
}
UpdateWarModeAuras();
}
void SetWarModeLocal(bool enabled)
{
if (enabled)
AddPlayerLocalFlag(PlayerLocalFlags.WarMode);
else
RemovePlayerLocalFlag(PlayerLocalFlags.WarMode);
}
public bool CanEnableWarModeInArea()
{
var area = CliDB.AreaTableStorage.LookupByKey(GetAreaId());
if (area == null || !IsFriendlyArea(area))
var zone = CliDB.AreaTableStorage.LookupByKey(GetZoneId());
if (zone == null || !IsFriendlyArea(zone))
return false;
return area.HasFlag2(AreaFlags2.CanEnableWarMode);
var area = CliDB.AreaTableStorage.LookupByKey(GetAreaId());
if (area == null)
area = zone;
do
{
if ((area.Flags[1] & (uint)AreaFlags2.CanEnableWarMode) != 0)
return true;
area = CliDB.AreaTableStorage.LookupByKey(area.ParentAreaID);
} while (area != null);
return false;
}
void UpdateWarModeAuras()
{
uint auraInside = 282559;
uint auraOutside = PlayerConst.WarmodeEnlistedSpellOutside;
if (IsWarModeDesired())
{
if (CanEnableWarModeInArea())
{
RemovePlayerFlag(PlayerFlags.WarModeActive);
RemoveAurasDueToSpell(auraOutside);
CastSpell(this, auraInside, true);
}
else
{
AddPlayerFlag(PlayerFlags.WarModeActive);
RemoveAurasDueToSpell(auraInside);
CastSpell(this, auraOutside, true);
}
SetWarModeLocal(true);
AddPvpFlag(UnitPVPStateFlags.PvP);
}
else
{
SetWarModeLocal(false);
RemoveAurasDueToSpell(auraOutside);
RemoveAurasDueToSpell(auraInside);
RemovePlayerFlag(PlayerFlags.WarModeActive);
RemovePvpFlag(UnitPVPStateFlags.PvP);
}
}
bool IsWarModeDesired() { return HasPlayerFlag(PlayerFlags.WarModeDesired); }
bool IsWarModeActive() { return HasPlayerFlag(PlayerFlags.WarModeActive); }
public bool IsWarModeLocalActive() { return HasPlayerLocalFlag(PlayerLocalFlags.WarMode); }
// Used in triggers for check "Only to targets that grant experience or honor" req
public bool IsHonorOrXPTarget(Unit victim)
{
@@ -5350,6 +5442,12 @@ namespace Game.Entities
}
public bool IsAFK() { return HasPlayerFlag(PlayerFlags.AFK); }
public bool IsDND() { return HasPlayerFlag(PlayerFlags.DND); }
public bool IsMaxLevel()
{
return GetLevel() >= m_activePlayerData.MaxLevel;
}
public ChatFlags GetChatFlags()
{
ChatFlags tag = ChatFlags.None;
@@ -7504,11 +7602,11 @@ namespace Game.Entities
public bool CanTameExoticPets() { return IsGameMaster() || HasAuraType(AuraType.AllowTamePetType); }
void SendAttackSwingDeadTarget() { SendPacket(new AttackSwingError(AttackSwingErr.DeadTarget)); }
void SendAttackSwingCantAttack() { SendPacket(new AttackSwingError(AttackSwingErr.CantAttack)); }
public void SendAttackSwingCancelAttack() { SendPacket(new CancelCombat()); }
void SendAttackSwingDeadTarget() { SendPacket(new AttackSwingError(AttackSwingErr.DeadTarget)); }
public void SendAttackSwingNotInRange() { SendPacket(new AttackSwingError(AttackSwingErr.NotInRange)); }
void SendAttackSwingBadFacingAttack() { SendPacket(new AttackSwingError(AttackSwingErr.BadFacing)); }
public void SendAttackSwingCancelAttack() { SendPacket(new CancelCombat()); }
public void SendAutoRepeatCancel(Unit target)
{
CancelAutoRepeat cancelAutoRepeat = new();
+22 -16
View File
@@ -506,39 +506,45 @@ namespace Game
[WorldPacketHandler(ClientOpcodes.TogglePvp)]
void HandleTogglePvP(TogglePvP packet)
{
if (GetPlayer().HasPlayerFlag(PlayerFlags.InPVP))
{
GetPlayer().RemovePlayerFlag(PlayerFlags.InPVP);
GetPlayer().AddPlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().pvpInfo.IsHostile && GetPlayer().IsPvP())
GetPlayer().pvpInfo.EndTimer = GameTime.GetGameTime() + 300; // start toggle-off
}
else
if (!GetPlayer().HasPlayerFlag(PlayerFlags.InPVP))
{
GetPlayer().AddPlayerFlag(PlayerFlags.InPVP);
GetPlayer().RemovePlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().IsPvP() || GetPlayer().pvpInfo.EndTimer != 0)
GetPlayer().UpdatePvP(true, true);
}
else if (!GetPlayer().IsWarModeLocalActive())
{
GetPlayer().RemovePlayerFlag(PlayerFlags.InPVP);
GetPlayer().AddPlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().pvpInfo.IsHostile && GetPlayer().IsPvP())
GetPlayer().pvpInfo.EndTimer = GameTime.GetGameTime() + 300; // start toggle-off
}
}
[WorldPacketHandler(ClientOpcodes.SetPvp)]
void HandleSetPvP(SetPvP packet)
{
if (!packet.EnablePVP)
{
GetPlayer().RemovePlayerFlag(PlayerFlags.InPVP);
GetPlayer().AddPlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().pvpInfo.IsHostile && GetPlayer().IsPvP())
GetPlayer().pvpInfo.EndTimer = GameTime.GetGameTime() + 300; // start toggle-off
}
else
if (packet.EnablePVP)
{
GetPlayer().AddPlayerFlag(PlayerFlags.InPVP);
GetPlayer().RemovePlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().IsPvP() || GetPlayer().pvpInfo.EndTimer != 0)
GetPlayer().UpdatePvP(true, true);
}
else if (!GetPlayer().IsWarModeLocalActive())
{
GetPlayer().RemovePlayerFlag(PlayerFlags.InPVP);
GetPlayer().AddPlayerFlag(PlayerFlags.PVPTimer);
if (!GetPlayer().pvpInfo.IsHostile && GetPlayer().IsPvP())
GetPlayer().pvpInfo.EndTimer = GameTime.GetGameTime() + 300; // start toggle-off
}
}
[WorldPacketHandler(ClientOpcodes.SetWarMode)]
void HandleSetWarMode(SetWarMode packet)
{
_player.SetWarModeDesired(packet.Enable);
}
[WorldPacketHandler(ClientOpcodes.FarSight)]
@@ -1135,6 +1135,18 @@ namespace Game.Networking.Packets
public bool EnablePVP;
}
class SetWarMode : ClientPacket
{
public SetWarMode(WorldPacket packet) : base(packet) { }
public override void Read()
{
Enable = _worldPacket.HasBit();
}
public bool Enable;
}
class AccountHeirloomUpdate : ServerPacket
{
public AccountHeirloomUpdate() : base(ServerOpcodes.AccountHeirloomUpdate, ConnectionType.Instance) { }
+84
View File
@@ -1243,6 +1243,18 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, @"VMap data directory is: {0}\vmaps", GetDataPath());
}
void SetForcedWarModeFactionBalanceState(int team, int reward)
{
_warModeDominantFaction = team;
_warModeOutnumberedFactionReward = reward;
}
void DisableForcedWarModeFactionBalanceState()
{
UpdateWarModeRewardValues();
}
public void LoadAutobroadcasts()
{
uint oldMSTime = Time.GetMSTime();
@@ -2001,6 +2013,9 @@ namespace Game
// reselect pools
Global.QuestPoolMgr.ChangeDailyQuests();
// Update faction balance
UpdateWarModeRewardValues();
// store next reset time
long now = GameTime.GetGameTime();
long next = GetNextDailyResetTime(now);
@@ -2450,6 +2465,67 @@ namespace Game
m_timers[WorldTimers.Corpses].SetCurrent(m_timers[WorldTimers.Corpses].GetInterval());
}
void UpdateWarModeRewardValues()
{
long[] warModeEnabledFaction = new long[2];
// Search for characters that have war mode enabled and played during the last week
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_WAR_MODE_TUNING);
stmt.AddValue(0, (uint)PlayerFlags.WarModeDesired);
stmt.AddValue(1, (uint)PlayerFlags.WarModeDesired);
SQLResult result = DB.Characters.Query(stmt);
if (!result.IsEmpty())
{
do
{
byte race = result.Read<byte>(0);
var raceEntry = CliDB.ChrRacesStorage.LookupByKey(race);
if (raceEntry != null)
{
var raceFaction = CliDB.FactionTemplateStorage.LookupByKey(raceEntry.FactionID);
if (raceFaction != null)
{
if ((raceFaction.FactionGroup & (byte)FactionMasks.Alliance) != 0)
warModeEnabledFaction[TeamId.Alliance] += result.Read<long>(1);
else if ((raceFaction.FactionGroup & (byte)FactionMasks.Horde) != 0)
warModeEnabledFaction[TeamId.Horde] += result.Read<long>(1);
}
}
} while (result.NextRow());
}
_warModeDominantFaction = TeamId.Neutral;
_warModeOutnumberedFactionReward = 0;
if (warModeEnabledFaction.All(val => val == 0))
return;
long dominantFactionCount = warModeEnabledFaction[TeamId.Alliance];
int dominantFaction = TeamId.Alliance;
if (warModeEnabledFaction[TeamId.Alliance] < warModeEnabledFaction[TeamId.Horde])
{
dominantFactionCount = warModeEnabledFaction[TeamId.Horde];
dominantFaction = TeamId.Horde;
}
double total = warModeEnabledFaction[TeamId.Alliance] + warModeEnabledFaction[TeamId.Horde];
double pct = dominantFactionCount / total;
if (pct >= WorldConfig.GetFloatValue(WorldCfg.CallToArms20Pct))
_warModeOutnumberedFactionReward = 20;
else if (pct >= WorldConfig.GetFloatValue(WorldCfg.CallToArms10Pct))
_warModeOutnumberedFactionReward = 10;
else if (pct >= WorldConfig.GetFloatValue(WorldCfg.CallToArms5Pct))
_warModeOutnumberedFactionReward = 5;
else
return;
_warModeDominantFaction = dominantFaction;
}
public uint GetVirtualRealmAddress()
{
return _realm.Id.GetAddress();
@@ -2477,6 +2553,10 @@ namespace Game
public bool IsGuidWarning() { return _guidWarn; }
public bool IsGuidAlert() { return _guidAlert; }
// War mode balancing
public int GetWarModeDominantFaction() { return _warModeDominantFaction; }
public int GetWarModeOutnumberedFactionReward() { return _warModeOutnumberedFactionReward; }
public WorldUpdateTime GetWorldUpdateTime() { return _worldUpdateTime; }
#region Fields
@@ -2550,6 +2630,10 @@ namespace Game
bool _guidAlert;
uint _warnDiff;
long _warnShutdownTime;
// War mode balancing
int _warModeDominantFaction; // the team that has higher percentage
int _warModeOutnumberedFactionReward;
#endregion
}