Files
abysmal-isle/Scripts/Services/PVP Arena System/PVPArenaSystem.cs
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

647 lines
20 KiB
C#

using Server;
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
using Server.Engines.Points;
using System.Linq;
using Server.Commands;
using Server.Gumps;
//TODO: Party: 1152064 You cannot invite other players in an arena to your party!
namespace Server.Engines.ArenaSystem
{
public class PVPArenaSystem : PointsSystem
{
public static PVPArenaSystem Instance { get; set; }
public static bool Enabled { get { return Core.HS; } }
public static bool BlockSameIP { get { return true; } }
public override PointsType Loyalty { get { return PointsType.PVPArena; } }
public override TextDefinition Name { get { return m_Name; } }
public override bool AutoAdd { get { return true; } }
public override double MaxPoints { get { return double.MaxValue; } }
public override bool ShowOnLoyaltyGump { get { return false; } }
private TextDefinition m_Name = new TextDefinition("Arena Stats");
public static List<PVPArena> Arenas { get; set; }
public static List<string> BlockedArenas { get; set; }
public static bool SystemInitialized { get; set; }
public PVPArenaSystem()
{
Instance = this;
if (Enabled)
{
CommandSystem.Register("ResetArenaStats", AccessLevel.Administrator, ResetStats_OnTarget);
CommandSystem.Register("ArenaSetup", AccessLevel.Administrator, ArenaSetup);
}
}
public void OnTick()
{
Arenas.ForEach(a => a.OnTick());
}
public List<ArenaDuel> GetBookedDuels()
{
List<ArenaDuel> booked = new List<ArenaDuel>();
foreach (var arena in Arenas.Where(a => a.BookedDuels.Count > 0))
{
booked.AddRange(arena.BookedDuels);
}
return booked;
}
public ArenaDuel GetBookedDuel(PlayerMobile pm)
{
foreach (var arena in Arenas.Where(a => a.BookedDuels.Count > 0))
{
foreach (var duel in arena.BookedDuels.Where(d => d.IsParticipant(pm)))
{
return duel;
}
}
return null;
}
public override void SendMessage(PlayerMobile from, double old, double points, bool quest)
{
}
public override TextDefinition GetTitle(PlayerMobile from)
{
return new TextDefinition("Arena Stats");
}
public override PointsEntry GetSystemEntry(PlayerMobile pm)
{
return new PlayerStatsEntry(pm);
}
public void Register(PVPArena arena)
{
if (Arenas == null)
Arenas = new List<PVPArena>();
if (!Arenas.Contains(arena))
Arenas.Add(arena);
}
public void Unregister(PVPArena arena)
{
if (Arenas != null)
{
Arenas.Remove(arena);
}
arena.Unregister();
}
public void AddBlockedArena(PVPArena arena)
{
if (BlockedArenas == null)
{
BlockedArenas = new List<string>();
}
if (!IsBlocked(arena.Definition))
{
Utility.WriteConsoleColor(ConsoleColor.Green, "Adding blocked EA PVP Arena: {0}", arena.Definition.Name);
BlockedArenas.Add(arena.Definition.Name);
Unregister(arena);
}
}
public void RemoveBlockedArena(ArenaDefinition def)
{
if (BlockedArenas == null)
{
return;
}
BlockedArenas.Remove(def.Name);
if (Arenas == null || Arenas.Count == 0)
{
Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), () => Instance.OnTick());
}
var arena = new PVPArena(def);
Instance.Register(arena);
Utility.WriteConsoleColor(ConsoleColor.Green, "Removing blocked EA PVP Arena: {0}", arena.Definition.Name);
arena.ConfigureArena();
}
public bool IsBlocked(ArenaDefinition def)
{
return BlockedArenas != null && BlockedArenas.Contains(def.Name);
}
public static bool IsEnemy(Mobile source, Mobile target)
{
var sourceRegion = Region.Find(source.Location, source.Map) as ArenaRegion;
var targetRegion = Region.Find(target.Location, target.Map) as ArenaRegion;
if (sourceRegion != null && sourceRegion.Arena.CurrentDuel != null && sourceRegion == targetRegion)
{
return sourceRegion.Arena.CurrentDuel.IsEnemy(source, target);
}
return false;
}
public static bool IsFriendly(Mobile source, Mobile target)
{
var sourceRegion = Region.Find(source.Location, source.Map) as ArenaRegion;
var targetRegion = Region.Find(target.Location, target.Map) as ArenaRegion;
if (sourceRegion != null && sourceRegion.Arena.CurrentDuel != null && sourceRegion == targetRegion)
{
return sourceRegion.Arena.CurrentDuel.IsFriendly(source, target);
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(2);
writer.Write(BlockedArenas == null ? 0 : BlockedArenas.Count);
if (BlockedArenas != null)
{
for (int i = 0; i < BlockedArenas.Count; i++)
{
writer.Write(BlockedArenas[i]);
}
}
writer.Write(Arenas == null ? 0 : Arenas.Count);
if (Arenas != null)
{
for (int i = 0; i < Arenas.Count; i++)
{
writer.Write(Arenas[i].Definition.Name);
Arenas[i].Serialize(writer);
}
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
SystemInitialized = true;
int version = reader.ReadInt();
if (version < 2)
{
InitializeArenas();
}
switch (version)
{
case 2:
case 1:
int c = reader.ReadInt();
for (int i = 0; i < c; i++)
{
if (BlockedArenas == null)
BlockedArenas = new List<string>();
BlockedArenas.Add(reader.ReadString());
}
goto case 0;
case 0:
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
if (Arenas == null)
Arenas = new List<PVPArena>();
if (version >= 2)
{
var arena = new PVPArena(GetDefinition(reader.ReadString()));
Register(arena);
arena.Deserialize(reader);
}
else
{
Arenas[i].Deserialize(reader);
}
}
break;
}
}
private ArenaDefinition GetDefinition(string name)
{
var def = ArenaDefinition.Definitions.FirstOrDefault(d => d.Name == name);
if (def == null)
{
return ArenaDefinition.Definitions[0];
}
return def;
}
public static void SendMessage(Mobile from, string message, int hue = 0x1F)
{
from.SendMessage(hue, message);
}
public static void SendMessage(Mobile from, int message, string args = "", int hue = 0x1F)
{
from.SendLocalizedMessage(message, args, hue);
}
public static void SendParticipantMessage(ArenaDuel duel, int message, bool inRegion = false, string args = "", int hue = 0x1F)
{
foreach (var part in duel.GetParticipants(inRegion))
{
SendMessage(part.Key, message, args, hue);
}
}
public void CheckTitle(PlayerMobile pm)
{
var entry = GetPlayerEntry<PlayerStatsEntry>(pm);
int title = 0;
switch (entry.TotalDuels)
{
case 1: title = 1152068 + (int)ArenaTitle.FledglingGladiator; break;
case 50: title = 1152068 + (int)ArenaTitle.BuddingGladiator; break;
case 100: title = 1152068 + (int)ArenaTitle.Gladiator; break;
case 250: title = 1152068 + (int)ArenaTitle.WellKnownGladiator; break;
case 500: title = 1152068 + (int)ArenaTitle.VeteranGladiator; break;
}
if (title > 0)
{
pm.AddRewardTitle(title);
pm.SendLocalizedMessage(1152067, String.Format("#{0}", title.ToString())); // You have gotten a new subtitle, ~1_VAL~, in reward for your duel!
}
}
public static bool HasSameIP(Mobile m, ArenaDuel duel)
{
if (duel == null || m.AccessLevel > AccessLevel.Player)
return false;
foreach (var kvp in duel.GetParticipants())
{
if (IsSameIP(m, kvp.Key))
{
return true;
}
}
return false;
}
public static bool IsSameIP(Mobile one, Mobile two)
{
if (one.NetState == null || two.NetState == null || one.AccessLevel > AccessLevel.Player || two.AccessLevel > AccessLevel.Player)
return false;
var oneAddress = one.NetState.Address;
var twoAddress = two.NetState.Address;
return one.NetState.Address == two.NetState.Address;
}
public static void Initialize()
{
if (Enabled)
{
if (!SystemInitialized)
{
InitializeArenas();
SystemInitialized = true;
}
if (Arenas != null)
{
foreach (var arena in Arenas)
{
arena.ConfigureArena();
}
Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), () => Instance.OnTick());
}
}
}
public static void InitializeArenas()
{
if (CanInitialize(ArenaDefinition.LostLandsTrammel))
{
Instance.Register(new PVPArena(ArenaDefinition.LostLandsTrammel));
}
if (CanInitialize(ArenaDefinition.LostLandsFelucca))
{
Instance.Register(new PVPArena(ArenaDefinition.LostLandsFelucca));
}
if (CanInitialize(ArenaDefinition.HavenTrammel))
{
Instance.Register(new PVPArena(ArenaDefinition.HavenTrammel));
}
if (CanInitialize(ArenaDefinition.HavenFelucca))
{
Instance.Register(new PVPArena(ArenaDefinition.HavenFelucca));
}
}
private static bool CanInitialize(ArenaDefinition def)
{
return !Instance.IsBlocked(def) && (Arenas == null || !Arenas.Any(arena => arena.Definition == def));
}
[Usage("ArenaSetup")]
[Description("Gives gump for arena setup.")]
public static void ArenaSetup(CommandEventArgs e)
{
var pm = e.Mobile as PlayerMobile;
if(pm != null)
{
BaseGump.SendGump(new PVPArenaSystemSetupGump(pm));
}
}
[Usage("ResetArenaStats")]
[Description("Target an arena stone to reset/wipe the stats associated with that arena.")]
public static void ResetStats_OnTarget(CommandEventArgs e)
{
Mobile m = e.Mobile;
m.BeginTarget(-1, false, Server.Targeting.TargetFlags.None, (fro, targeted) =>
{
if (m is PlayerMobile && targeted is ArenaStone)
{
var stone = (ArenaStone)targeted;
if (stone.Arena != null)
{
var arena = stone.Arena;
BaseGump.SendGump(new GenericConfirmCallbackGump<PVPArena>((PlayerMobile)m,
String.Format("Reset {0} Statistics?", arena.Definition.Name),
"By selecting yes, you will permanently wipe the stats associated to this arena.",
arena,
null,
(from, a) =>
{
ColUtility.Free(a.TeamRankings);
ColUtility.Free(a.SurvivalRankings);
from.SendMessage("Arena stats cleared.");
}));
}
}
});
}
}
public class PlayerStatsEntry : PointsEntry
{
public int SurvivalWins { get; set; }
public int SurvivalLosses { get; set; }
public int SurvivalDraws { get; set; }
public int TeamWins { get; set; }
public int TeamLosses { get; set; }
public int TeamDraws { get; set; }
public int Kills { get; set; }
public int Deaths { get; set; }
public bool IgnoreInvites { get; set; }
public bool OpenStats { get; set; }
public int TotalDuels { get { return SurvivalWins + SurvivalLosses + SurvivalDraws + TeamWins + TeamLosses + TeamDraws; } }
public List<DuelRecord> Record { get; set; }
public DuelProfile Profile { get; set; }
public PlayerStatsEntry(PlayerMobile pm)
: base(pm)
{
IgnoreInvites = true;
OpenStats = true;
Record = new List<DuelRecord>();
}
public void HandleDeath(Mobile m, bool killedBy)
{
Record.Add(new DuelRecord(m, killedBy));
if (Record.Count > 12)
{
Record.RemoveAt(12);
}
}
// Rating, seems to start at 10000, then +33 for win, -33 for loss
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
if (Profile != null)
{
writer.Write(1);
Profile.Serialize(writer);
}
else
{
writer.Write(0);
}
writer.Write(Record.Count);
for (int i = 0; i < Record.Count; i++)
{
Record[i].Serialize(writer);
}
writer.Write(OpenStats);
writer.Write(IgnoreInvites);
writer.Write(SurvivalWins);
writer.Write(SurvivalLosses);
writer.Write(SurvivalDraws);
writer.Write(TeamWins);
writer.Write(TeamLosses);
writer.Write(TeamDraws);
writer.Write(Kills);
writer.Write(Deaths);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Record = new List<DuelRecord>();
if (reader.ReadInt() == 1)
{
Profile = new DuelProfile(reader);
}
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Record.Add(new DuelRecord(reader));
}
OpenStats = reader.ReadBool();
IgnoreInvites = reader.ReadBool();
SurvivalWins = reader.ReadInt();
SurvivalLosses = reader.ReadInt();
SurvivalDraws = reader.ReadInt();
TeamWins = reader.ReadInt();
TeamLosses = reader.ReadInt();
TeamDraws = reader.ReadInt();
Kills = reader.ReadInt();
Deaths = reader.ReadInt();
}
public class DuelRecord
{
public Mobile Opponent { get; set; }
public bool KilledBy { get; set; }
public DateTime DuelDate { get; set; }
public DuelRecord(Mobile opponent, bool killedBy)
{
Opponent = opponent;
KilledBy = killedBy;
DuelDate = DateTime.Now;
}
public DuelRecord(GenericReader reader)
{
int version = reader.ReadInt();
Opponent = reader.ReadMobile();
KilledBy = reader.ReadBool();
DuelDate = reader.ReadDateTime();
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Opponent);
writer.Write(KilledBy);
writer.Write(DuelDate);
}
}
public class DuelProfile
{
public int Entries { get; set; }
public RoomType RoomType { get; set; }
public BattleMode BattleMode { get; set; }
public bool Ranked { get; set; }
public TimeLimit TimeLimit { get; set; }
public EntryFee EntryFee { get; set; }
public int PetSlots { get; set; }
public bool RidingFlyingAllowed { get; set; }
public bool RangedWeaponsAllowed { get; set; }
public bool SummonSpellsAllowed { get; set; }
public bool FieldSpellsAllowed { get; set; }
public PotionRules PotionRules { get; set; }
public DuelProfile(ArenaDuel duel)
{
Entries = duel.Entries;
RoomType = duel.RoomType;
BattleMode = duel.BattleMode;
Ranked = duel.Ranked;
TimeLimit = duel.TimeLimit;
EntryFee = duel.EntryFee;
PetSlots = duel.PetSlots;
RidingFlyingAllowed = duel.RidingFlyingAllowed;
RangedWeaponsAllowed = duel.RangedWeaponsAllowed;
SummonSpellsAllowed = duel.SummonSpellsAllowed;
FieldSpellsAllowed = duel.FieldSpellsAllowed;
PotionRules = duel.PotionRules;
}
public DuelProfile(GenericReader reader)
{
int version = reader.ReadInt();
Entries = reader.ReadInt();
RoomType = (RoomType)reader.ReadInt();
BattleMode = (BattleMode)reader.ReadInt();
Ranked = reader.ReadBool();
TimeLimit = (TimeLimit)reader.ReadInt();
EntryFee = (EntryFee)reader.ReadInt();
PetSlots = reader.ReadInt();
RidingFlyingAllowed = reader.ReadBool();
RangedWeaponsAllowed = reader.ReadBool();
SummonSpellsAllowed = reader.ReadBool();
FieldSpellsAllowed = reader.ReadBool();
PotionRules = (PotionRules)reader.ReadInt();
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Entries);
writer.Write((int)RoomType);
writer.Write((int)BattleMode);
writer.Write(Ranked);
writer.Write((int)TimeLimit);
writer.Write((int)EntryFee);
writer.Write(PetSlots);
writer.Write(RidingFlyingAllowed);
writer.Write(RangedWeaponsAllowed);
writer.Write(SummonSpellsAllowed);
writer.Write(FieldSpellsAllowed);
writer.Write((int)PotionRules);
}
}
}
}
namespace Server.Mobiles
{
public enum ArenaTitle
{
FledglingGladiator = 0,
BuddingGladiator = 1,
Gladiator = 3,
WellKnownGladiator = 4,
VeteranGladiator =5
}
}