Files
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

1158 lines
35 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Gumps;
using Server.Network;
using Server.Guilds;
using Server.Engines.Points;
using Server.Engines.CityLoyalty;
using Server.SkillHandlers;
using Server.Multis;
using Server.Regions;
using Server.Misc;
namespace Server.Engines.VvV
{
public enum UpdateType
{
Kill,
Assist,
Steal,
TurnInVice,
TurnInVirtue,
Disarm
}
[PropertyObject]
public class VvVBattle
{
public static readonly int Duration = 30;
public static readonly int Cooldown = 5;
public static readonly int Announcement = 2;
public static readonly int KillCooldownDuration = 5;
public static readonly int MaxTraps = 20;
public static readonly int MaxTurrets = 10;
//Battle Scoring
public static readonly double ScoreToWin = 10000;
public static readonly double OccupyPoints = 300;
public static readonly double AltarPoints = 1000;
public static readonly double KillPoints = 600;
public static readonly double TurnInPoints = 500;
public static readonly int AltarSilver = 100;
public static readonly int TurnInSilver = 100;
public static readonly int KillSilver = 50;
public static readonly int WinSilver = 100;
public static readonly int DisarmSilver = 50;
// silver penalty in the event the battle is uncontested
public static readonly double Penalty = 0.5;
[CommandProperty(AccessLevel.GameMaster)]
public double SilverPenalty
{
get
{
if (!ViceVsVirtueSystem.EnhancedRules)
return 1.0;
return UnContested ? Penalty : 1.0;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public ViceVsVirtueSystem System { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime StartTime { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime CooldownEnds { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime LastOccupationCheck { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextSigilSpawn { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextAnnouncement { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextAltarActivate { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextManaSpike { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime ManaSpikeEndEffects { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public VvVCity City { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public VvVSigil Sigil { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool OnGoing { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool UnContested { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Region Region
{
get
{
CityInfo info = CityInfo.Infos[City];
if (info != null)
{
return info.Region;
}
return null;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool ForceStart
{
get { return false; }
set
{
if (!OnGoing && value)
Begin();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool ForceEnd
{
get { return false; }
set
{
if (OnGoing && value)
EndBattle();
}
}
public List<BattleTeam> Teams { get; set; }
public Dictionary<Mobile, DateTime> KillCooldown { get; set; }
public Dictionary<Mobile, DateTime> BattleAggression { get; set; }
public List<string> Messages { get; set; }
public List<VvVAltar> Altars { get; set; }
public int AltarIndex { get; set; }
public List<VvVTrap> Traps { get; set; }
public List<CannonTurret> Turrets { get; set; }
public List<Mobile> Warned { get; set; }
public VvVPriest VicePriest { get; private set; }
public VvVPriest VirtuePriest { get; private set; }
public Timer Timer { get; private set; }
public int TrapCount { get { return Traps.Where(t => !t.Deleted).Count(); } }
public int TurretCount { get { return Turrets.Where(t => !t.Deleted).Count(); } }
[CommandProperty(AccessLevel.GameMaster)]
public bool InCooldown
{
get { return CooldownEnds > DateTime.UtcNow; }
}
public DateTime NextCombatHeatCycle { get; private set; }
public VvVBattle(ViceVsVirtueSystem sys)
{
System = sys;
}
public void Begin()
{
OnGoing = true;
NextCombatHeatCycle = DateTime.UtcNow;
VvVCity newCity = City;
List<VvVCity> cities = new List<VvVCity>();
Teams = new List<BattleTeam>();
KillCooldown = new Dictionary<Mobile, DateTime>();
Messages = new List<string>();
Altars = new List<VvVAltar>();
Traps = new List<VvVTrap>();
Warned = new List<Mobile>();
Turrets = new List<CannonTurret>();
for (int i = 0; i < 8; i++)
{
if (!System.ExemptCities.Contains((VvVCity)i) && (VvVCity)i != newCity)
cities.Add((VvVCity)i);
}
if (cities.Count > 0)
{
newCity = cities[Utility.Random(cities.Count)];
}
else if (System.ExemptCities.Contains(newCity))
{
System.SendVvVMessage("All VvV cities are currently exempt.");
return;
}
ColUtility.Free(cities);
City = newCity;
BeginTimer();
StartTime = DateTime.UtcNow;
NextSigilSpawn = DateTime.UtcNow + TimeSpan.FromMinutes(Utility.RandomMinMax(1, 3));
AltarIndex = 0;
SpawnAltars();
SpawnPriests(false);
if (Region is GuardedRegion)
{
GuardedRegion.Disable((GuardedRegion)Region);
}
NextAltarActivate = DateTime.UtcNow + TimeSpan.FromMinutes(1);
System.SendVvVMessage(1154721, String.Format("#{0}", ViceVsVirtueSystem.GetCityLocalization(City).ToString()));
// A Battle between Vice and Virtue is active! To Arms! The City of ~1_CITY~ is besieged!
}
public void SpawnAltars()
{
foreach (Point3D p in CityInfo.Infos[City].AltarLocs)
{
VvVAltar altar = new VvVAltar(this);
altar.MoveToWorld(p, Map.Felucca);
Altars.Add(altar);
}
}
public void SpawnPriests(bool movetoworld = true)
{
if(VicePriest == null || VicePriest.Deleted)
VicePriest = new VvVPriest(VvVType.Vice, this);
if(VirtuePriest == null || VirtuePriest.Deleted)
VirtuePriest = new VvVPriest(VvVType.Virtue, this);
if (movetoworld)
{
Point3D p;
do
{
p = Map.Felucca.GetRandomSpawnPoint(CityInfo.Infos[City].PriestLocation);
}
while (!Map.Felucca.CanSpawnMobile(p));
VicePriest.MoveToWorld(p, Map.Felucca);
do
{
p = Map.Felucca.GetRandomSpawnPoint(CityInfo.Infos[City].PriestLocation);
}
while (!Map.Felucca.CanSpawnMobile(p));
VirtuePriest.MoveToWorld(p, Map.Felucca);
}
}
public void BeginTimer()
{
EndTimer();
Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), OnTick);
Timer.Start();
}
public void EndTimer()
{
if (Timer != null)
{
Timer.Stop();
Timer = null;
}
}
public void OnTick()
{
if (!OnGoing)
return;
CheckParticipation();
UpdateAllGumps();
if (StartTime + TimeSpan.FromMinutes(Duration) < DateTime.UtcNow)
{
EndBattle();
return;
}
if (LastOccupationCheck + TimeSpan.FromMinutes(1) < DateTime.UtcNow)
{
CheckOccupation();
LastOccupationCheck = DateTime.UtcNow;
}
if (NextAltarActivate != DateTime.MinValue && NextAltarActivate < DateTime.UtcNow)
{
ActivateAltar();
NextAltarActivate = DateTime.MinValue;
}
if (NextSigilSpawn != DateTime.MinValue && NextSigilSpawn < DateTime.UtcNow)
{
if (Sigil == null || Sigil.Deleted)
{
SpawnSigil();
}
}
ActivateArrows();
if (KillCooldown != null)
{
List<Mobile> list = KillCooldown.Keys.Where(mob => KillCooldown[mob] < DateTime.UtcNow).ToList();
foreach (Mobile m in list)
{
KillCooldown.Remove(m);
}
ColUtility.Free(list);
}
if (Turrets != null)
{
Turrets.ForEach(t => { t.Scan(); });
}
}
public void CheckParticipation()
{
if (Region == null)
return;
BattleTeam team = null;
UnContested = true;
bool checkAggression = ViceVsVirtueSystem.EnhancedRules && NextCombatHeatCycle < DateTime.UtcNow;
foreach (PlayerMobile pm in this.Region.GetEnumeratedMobiles().OfType<PlayerMobile>())
{
bool vvv = ViceVsVirtueSystem.IsVvV(pm);
if (!vvv && !Warned.Contains(pm) && pm.AccessLevel == AccessLevel.Player)
{
pm.SendGump(new BattleWarningGump(pm));
Warned.Add(pm);
}
else if (vvv && pm.Alive && !pm.Hidden && BaseBoat.FindBoatAt(pm.Location, pm.Map) == null && BaseHouse.FindHouseAt(pm) == null)
{
Guild g = pm.Guild as Guild;
if (g != null)
{
var t = GetTeam(g);
if (team == null)
{
team = t;
}
else if (t != team && UnContested)
{
UnContested = false;
}
}
}
if (checkAggression && (vvv || ViceVsVirtueSystem.IsVvVCombatant(pm)))
{
AddAggression(pm);
}
}
if (checkAggression)
{
CheckBattleAggression();
NextCombatHeatCycle = DateTime.UtcNow + TimeSpan.FromMinutes(1);
}
}
public void AddAggression(Mobile m)
{
if (m is PlayerMobile)
{
if (BattleAggression == null)
{
BattleAggression = new Dictionary<Mobile, DateTime>();
}
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.HeatOfBattleStatus, 1153801, 1153827, Aggression.CombatHeatDelay, m, true));
BattleAggression[m] = DateTime.UtcNow + TimeSpan.FromMinutes(2);
}
}
private void CheckBattleAggression()
{
if (BattleAggression == null)
return;
var list = new List<Mobile>(BattleAggression.Keys);
foreach (var m in list)
{
if (BattleAggression[m] < DateTime.UtcNow && !m.Region.IsPartOf(Region))
{
BattleAggression.Remove(m);
}
}
ColUtility.Free(list);
}
public bool HasBattleAggression(Mobile m)
{
if (BattleAggression == null || !BattleAggression.ContainsKey(m))
{
return false;
}
if (BattleAggression[m] < DateTime.UtcNow)
{
BattleAggression.Remove(m);
return false;
}
return true;
}
public void EndBattle()
{
OnGoing = false;
EndTimer();
if (Region is GuardedRegion)
{
((GuardedRegion)Region).Disabled = false;
foreach (PlayerMobile pm in Region.GetEnumeratedMobiles().OfType<PlayerMobile>())
{
pm.RecheckTownProtection();
}
}
foreach (VvVAltar altar in Altars)
{
if(!altar.Deleted)
altar.Delete();
}
foreach (VvVTrap trap in Traps)
{
if(!trap.Deleted)
trap.Delete();
}
foreach (CannonTurret turret in Turrets)
{
if (!turret.Deleted)
turret.Delete();
}
if (VicePriest != null)
{
VicePriest.Delete();
VicePriest = null;
}
if (VirtuePriest != null)
{
VirtuePriest.Delete();
VirtuePriest = null;
}
if (Sigil != null)
{
Sigil.Delete();
Sigil = null;
}
TallyStats();
SendBattleStatsGump();
System.SendVvVMessage(1154722); // A VvV battle has just concluded. The next battle will begin in less than five minutes!
if (BattleAggression != null)
{
BattleAggression.Clear();
}
ColUtility.Free(Altars);
ColUtility.Free(Teams);
KillCooldown.Clear();
ColUtility.Free(Messages);
ColUtility.Free(Traps);
ColUtility.Free(Warned);
ColUtility.Free(Turrets);
if (Region is GuardedRegion)
{
((GuardedRegion)Region).Disabled = false;
}
NextSigilSpawn = DateTime.MinValue;
LastOccupationCheck = DateTime.MinValue;
NextAnnouncement = DateTime.MinValue;
StartTime = DateTime.MinValue;
NextAltarActivate = DateTime.MinValue;
ManaSpikeEndEffects = DateTime.MinValue;
NextManaSpike = DateTime.MinValue;
CooldownEnds = DateTime.UtcNow + TimeSpan.FromMinutes(Cooldown);
Timer.DelayCall(TimeSpan.FromMinutes(Cooldown), () =>
{
System.CheckBattleStatus();
});
}
public void TallyStats()
{
BattleTeam leader = GetLeader();
List<Guild> added = new List<Guild>();
if (leader == null || leader.Guild == null)
return;
leader.Silver += AwardSilver(WinSilver + (OppositionCount(leader.Guild) * 50));
foreach (Mobile m in this.Region.GetEnumeratedMobiles())
{
Guild g = m.Guild as Guild;
if (g == null)
continue;
PlayerMobile pm = m as PlayerMobile;
if (pm != null)
{
BattleTeam team = GetTeam(g);
VvVPlayerBattleStats stats = GetPlayerStats(pm);
VvVPlayerEntry entry = ViceVsVirtueSystem.Instance.GetPlayerEntry<VvVPlayerEntry>(pm);
if (entry != null)
{
entry.Score += team.Score;
entry.Points += team.Silver;
entry.Kills += stats.Kills;
entry.Deaths += stats.Deaths;
entry.Assists += stats.Assists;
entry.ReturnedSigils += stats.ReturnedSigils;
entry.DisarmedTraps += stats.Disarmed;
entry.StolenSigils += stats.Stolen;
if (added.Contains(g))
continue;
else
added.Add(g);
if (!ViceVsVirtueSystem.Instance.GuildStats.ContainsKey(g))
ViceVsVirtueSystem.Instance.GuildStats[g] = new VvVGuildStats(g);
VvVGuildStats gstats = ViceVsVirtueSystem.Instance.GuildStats[g];
gstats.Kills += team.Kills;
gstats.ReturnedSigils += team.ReturnedSigils;
gstats.Score += team.Score;
}
}
}
ColUtility.Free(added);
}
public void SpawnSigil()
{
Point3D p = CityInfo.Infos[City].SigilLocs[Utility.Random(CityInfo.Infos[City].SigilLocs.Length)];
Sigil = new VvVSigil(this, p);
Sigil.MoveToWorld(p, Map.Felucca);
UpdateAllGumps();
}
public void ActivateAltar()
{
if (AltarIndex == 2)
AltarIndex = 0;
else
AltarIndex++;
Altars[AltarIndex].Activate();
ActivateArrows();
SendStatusMessage("Fight for the altar!", true);
}
public void CheckArrow(PlayerMobile pm)
{
if (pm.NetState == null)
return;
foreach (VvVAltar altar in Altars)
{
if (altar.IsActive)
{
pm.QuestArrow = new AltarArrow(pm, altar);
break;
}
}
}
public void ActivateArrows()
{
if (Altars == null || Region == null)
return;
foreach (PlayerMobile pm in this.Region.GetEnumeratedMobiles().OfType<PlayerMobile>())
{
if (pm.NetState != null && pm.QuestArrow == null)
{
foreach (VvVAltar altar in Altars)
{
if (altar.IsActive)
{
pm.QuestArrow = new AltarArrow(pm, altar);
break;
}
}
}
}
}
public VvVPlayerBattleStats GetPlayerStats(PlayerMobile pm)
{
if (pm == null || pm.Guild == null)
return null;
Guild g = pm.Guild as Guild;
BattleTeam team = GetTeam(g);
VvVPlayerBattleStats stats = team.PlayerStats.FirstOrDefault(s => s.Player == pm);
if (stats == null)
{
stats = new VvVPlayerBattleStats(pm);
team.PlayerStats.Add(stats);
}
return stats;
}
public BattleTeam GetTeam(Guild g)
{
BattleTeam team = Teams.FirstOrDefault(t => t.Guild != null && (t.Guild == g || t.Guild.IsAlly(g)));
if (team != null)
return team;
team = new BattleTeam(g);
Teams.Add(team);
return team;
}
public void Update(Mobile m, UpdateType type)
{
VvVPlayerEntry entry = System.GetPlayerEntry<VvVPlayerEntry>(m);
if (entry != null)
{
Update(null, entry, type);
}
}
public void Update(VvVPlayerEntry victim, VvVPlayerEntry killer, UpdateType type)
{
if (killer == null || killer.Player == null || killer.Guild == null)
return;
VvVPlayerBattleStats killerStats = GetPlayerStats(killer.Player);
VvVPlayerBattleStats victimStats = victim == null ? null : GetPlayerStats(victim.Player);
BattleTeam killerTeam = GetTeam(killer.Guild);
BattleTeam victimTeam = null;
if(victim != null)
victimTeam = GetTeam(victim.Guild);
switch (type)
{
case UpdateType.Kill:
if (killerStats != null) killerStats.Kills++;
if (victimStats != null) victimStats.Deaths++;
if (killerTeam != null)
killerTeam.Kills++;
if (victimTeam != null)
victimTeam.Deaths++;
if (victim != null && victim.Player != null)
{
if (!KillCooldown.ContainsKey(victim.Player) || KillCooldown[victim.Player] < DateTime.UtcNow)
{
if (killerTeam != null)
{
killerTeam.Score += (int)KillPoints;
killerTeam.Silver += AwardSilver(KillSilver + (OppositionCount(killer.Guild) * 50));
}
SendStatusMessage(String.Format("{0} has killed {1}!", killer.Player.Name, victim.Player.Name));
KillCooldown[victim.Player] = DateTime.UtcNow + TimeSpan.FromMinutes(KillCooldownDuration);
}
}
break;
case UpdateType.Assist:
if (killerStats != null)
killerStats.Assists++;
if (killerTeam != null)
killerTeam.Assists++;
break;
case UpdateType.Steal:
if (killerStats != null)
{
killerStats.Stolen++;
SendStatusMessage(String.Format("{0} has stolen the sigil!", killer.Player.Name));
}
if (killerTeam != null)
killerTeam.Stolen++;
break;
case UpdateType.TurnInVice:
case UpdateType.TurnInVirtue:
if (killerTeam != null)
{
killerTeam.Score += (int)TurnInPoints;
killerTeam.Silver += AwardSilver(TurnInSilver + (OppositionCount(killer.Guild) * 50));
}
if (killerStats != null && killerTeam != null)
{
if (type == UpdateType.TurnInVirtue)
{
killerStats.VirtueReturned++;
killerTeam.VirtueReturned++;
}
else
{
killerStats.ViceReturned++;
killerTeam.ViceReturned++;
}
}
SendStatusMessage(String.Format("{0} has returned the sigil!", killer.Player.Name));
NextSigilSpawn = DateTime.UtcNow + TimeSpan.FromMinutes(1);
RemovePriests();
break;
case UpdateType.Disarm:
SendStatusMessage(String.Format("{0} has disarmed a trap!", killer.Player.Name));
if (killerStats != null)
{
killerStats.Disarmed++;
}
if (killerTeam != null)
{
killerTeam.Silver += AwardSilver(DisarmSilver + (OppositionCount(killer.Guild) * 50));
killerTeam.Disarmed++;
}
break;
}
CheckScore();
}
public int AwardSilver(int amount)
{
return (int)((double)amount * SilverPenalty);
}
public void RemovePriests()
{
Timer.DelayCall(TimeSpan.FromSeconds(4), () =>
{
if (VicePriest != null)
VicePriest.Internalize();
if (VirtuePriest != null)
VirtuePriest.Internalize();
});
}
public void OccupyAltar(Guild g)
{
if (!OnGoing || g == null)
return;
BattleTeam team = GetTeam(g);
team.Score += (int)AltarPoints;
team.Silver += AwardSilver(AltarSilver + (OppositionCount(g) * 50));
SendStatusMessage(String.Format("{0} claimed the altar!", g != null ? g.Abbreviation : "somebody"));
foreach (PlayerMobile p in Region.GetEnumeratedMobiles().Where(player => player is PlayerMobile))
{
if (p.QuestArrow != null)
p.QuestArrow = null;
}
CheckScore();
NextAltarActivate = DateTime.UtcNow + TimeSpan.FromMinutes(2);
}
public void CheckOccupation()
{
if (!OnGoing)
return;
if (Teams.Count == 1)
{
BattleTeam team = Teams[0];
team.Score += (int)OccupyPoints;
UpdateAllGumps();
CheckScore();
if (OnGoing && NextAnnouncement < DateTime.UtcNow)
{
System.SendVvVMessage(1154957, team.Guild.Name); // ~1_NAME~ is occupying the city!
NextAnnouncement = DateTime.UtcNow + TimeSpan.FromMinutes(Announcement);
}
}
else // Is this a bug? Verified on EA this is how it behaves
{
if (NextAnnouncement < DateTime.UtcNow)
{
System.SendVvVMessage(1154958); // The City is unoccupied! Slay opposing forces to claim the city for your guild!
NextAnnouncement = DateTime.UtcNow + TimeSpan.FromMinutes(Announcement);
}
}
}
public void CheckScore()
{
int score;
GetLeader(out score);
if (score >= ScoreToWin)
{
EndBattle();
return;
}
UpdateAllGumps();
}
public BattleTeam GetLeader()
{
int score;
return GetLeader(out score);
}
/// <summary>
/// Gets real time leader of battle, out parameter of their score
/// </summary>
/// <param name="score"></param>
/// <returns></returns>
public BattleTeam GetLeader(out int score)
{
score = 0;
List<BattleTeam> teams = new List<BattleTeam>(Teams);
teams.Sort();
if (teams.Count > 0)
{
score = teams[0].Score;
return teams[0];
}
return null;
}
/// <summary>
/// Returns enemy count, by alliance
/// </summary>
/// <param name="g"></param>
/// <returns></returns>
public int OppositionCount(Guild g)
{
List<Guild> exempt = new List<Guild>();
int count = 0;
foreach (BattleTeam team in Teams)
{
if (team.Guild == null || team.Guild == g || team.Guild.IsAlly(g) || exempt.Contains(g))
continue;
count++;
if (team.Guild.Alliance != null)
{
foreach (Guild guil in team.Guild.Alliance.Members.Where(guil => !exempt.Contains(guil)))
exempt.Add(guil);
}
}
ColUtility.Free(exempt);
return count;
}
public bool IsInActiveBattle(Mobile one, Mobile two)
{
return IsInActiveBattle(one) && IsInActiveBattle(two);
}
public bool IsInActiveBattle(Mobile m)
{
if (!OnGoing)
return false;
Region r = Region.Find(m.Location, m.Map);
return r == this.Region;
}
public void OnEnterRegion(Mobile m)
{
if (m is PlayerMobile && OnGoing)
{
if (m.HasGump(typeof(VvVBattleStatusGump)))
m.CloseGump(typeof(VvVBattleStatusGump));
BaseGump.SendGump(new VvVBattleStatusGump((PlayerMobile)m, this));
}
}
public void CheckGump(Mobile m)
{
if (m is PlayerMobile && OnGoing)
{
BaseGump.SendGump(new VvVBattleStatusGump((PlayerMobile)m, this));
}
}
public void UpdateAllGumps()
{
if (Region == null)
return;
foreach (PlayerMobile m in this.Region.GetEnumeratedMobiles().OfType<PlayerMobile>())
{
if (!ViceVsVirtueSystem.IsVvV(m) || m.NetState == null)
continue;
VvVBattleStatusGump g = m.FindGump(typeof(VvVBattleStatusGump)) as VvVBattleStatusGump;
if (g == null)
{
BaseGump.SendGump(new VvVBattleStatusGump(m, this));
}
else
{
g.Refresh(true, false);
}
}
}
public void SendBattleStatsGump()
{
if (Region == null)
return;
foreach (PlayerMobile m in this.Region.GetEnumeratedMobiles().OfType<PlayerMobile>())
{
if (ViceVsVirtueSystem.IsVvV(m))
{
m.CloseGump(typeof(VvVBattleStatusGump));
m.SendGump(new BattleStatsGump((PlayerMobile)m, this));
}
}
}
public void SendStatusMessage(string message, bool sendgumps = false)
{
Messages.Add(message);
if(sendgumps)
UpdateAllGumps();
}
public void AddCannonTurret(CannonTurret turret)
{
if (!Turrets.Contains(turret))
Turrets.Add(turret);
}
public VvVBattle(GenericReader reader, ViceVsVirtueSystem system)
{
int version = reader.ReadInt();
System = system;
Altars = new List<VvVAltar>();
KillCooldown = new Dictionary<Mobile, DateTime>();
Messages = new List<string>();
Traps = new List<VvVTrap>();
Warned = new List<Mobile>();
Turrets = new List<CannonTurret>();
Teams = new List<BattleTeam>();
OnGoing = reader.ReadBool();
if (reader.ReadInt() == 0)
{
StartTime = reader.ReadDateTime();
CooldownEnds = reader.ReadDateTime();
LastOccupationCheck = reader.ReadDateTime();
NextSigilSpawn = reader.ReadDateTime();
NextAnnouncement = reader.ReadDateTime();
NextAltarActivate = reader.ReadDateTime();
City = (VvVCity)reader.ReadInt();
Sigil = reader.ReadItem() as VvVSigil;
VicePriest = reader.ReadMobile() as VvVPriest;
VirtuePriest = reader.ReadMobile() as VvVPriest;
if (Sigil != null)
Sigil.Battle = this;
if (VicePriest != null)
VicePriest.Battle = this;
if (VirtuePriest != null)
VirtuePriest.Battle = this;
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
VvVAltar altar = reader.ReadItem() as VvVAltar;
if (altar != null)
{
altar.Battle = this;
Altars.Add(altar);
}
}
if (version == 1)
{
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
BattleTeam team = new BattleTeam(reader);
Teams.Add(team);
}
}
else
{
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Guild g = reader.ReadGuild() as Guild;
VvVGuildBattleStats stats = new VvVGuildBattleStats(reader, g);
}
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
VvVTrap t = reader.ReadItem() as VvVTrap;
if (t != null)
Traps.Add(t);
}
Timer.DelayCall(TimeSpan.FromSeconds(10), () =>
{
if (Region is GuardedRegion)
{
GuardedRegion.Disable((GuardedRegion)Region);
}
BeginTimer();
ActivateArrows();
});
}
}
public void Serialize(GenericWriter writer)
{
writer.Write(1);
writer.Write(OnGoing);
if (OnGoing)
{
writer.Write(0);
writer.Write(StartTime);
writer.Write(CooldownEnds);
writer.Write(LastOccupationCheck);
writer.Write(NextSigilSpawn);
writer.Write(NextAnnouncement);
writer.Write(NextAltarActivate);
writer.Write((int)City);
writer.Write(Sigil);
writer.Write(VicePriest);
writer.Write(VirtuePriest);
writer.Write(Altars.Count);
Altars.ForEach(altar => writer.Write(altar));
/*writer.Write(GuildStats.Count);
foreach (KeyValuePair<Guild, VvVGuildBattleStats> kvp in GuildStats)
{
writer.Write(kvp.Key);
kvp.Value.Serialize(writer);
}*/
writer.Write(Teams.Count);
foreach (BattleTeam team in Teams)
{
team.Serialize(writer);
}
writer.Write(Traps.Count);
Traps.ForEach(t => writer.Write(t));
}
else
writer.Write(1);
}
}
}