Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
512
Scripts/Services/PVP Arena System/PVPArena.cs
Normal file
512
Scripts/Services/PVP Arena System/PVPArena.cs
Normal file
@@ -0,0 +1,512 @@
|
||||
using Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using System.Linq;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Engines.ArenaSystem
|
||||
{
|
||||
[PropertyObject]
|
||||
public class PVPArena
|
||||
{
|
||||
public static TimeSpan PendingDuelExpirationTime = TimeSpan.FromMinutes(10);
|
||||
public static TimeSpan BookedDuelBegin = TimeSpan.FromSeconds(10);
|
||||
public static int StartRank = 10000;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaManager Manager { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaStone Stone { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaExitBanner Banner1 { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaExitBanner Banner2 { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaDefinition Definition { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool InUse { get { return CurrentDuel != null; } }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ArenaDuel CurrentDuel { get; set; }
|
||||
|
||||
public ArenaRegion Region { get; set; }
|
||||
public GuardedRegion GuardRegion { get; set; }
|
||||
|
||||
public Dictionary<ArenaDuel, DateTime> PendingDuels { get; set; }
|
||||
public List<ArenaDuel> BookedDuels { get; set; }
|
||||
public List<Item> Blockers { get; set; }
|
||||
|
||||
public List<ArenaStats> TeamRankings { get; set; }
|
||||
public List<ArenaStats> SurvivalRankings { get; set; }
|
||||
|
||||
public PVPArena(ArenaDefinition definition)
|
||||
{
|
||||
Definition = definition;
|
||||
|
||||
PendingDuels = new Dictionary<ArenaDuel, DateTime>();
|
||||
BookedDuels = new List<ArenaDuel>();
|
||||
Blockers = new List<Item>();
|
||||
|
||||
TeamRankings = new List<ArenaStats>();
|
||||
SurvivalRankings = new List<ArenaStats>();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "...";
|
||||
}
|
||||
|
||||
public void ConfigureArena()
|
||||
{
|
||||
if (Manager == null)
|
||||
{
|
||||
Manager = new ArenaManager(this);
|
||||
Manager.MoveToWorld(Definition.ManagerLocation, Definition.Map);
|
||||
}
|
||||
|
||||
if (Stone == null)
|
||||
{
|
||||
Stone = new ArenaStone(this);
|
||||
Stone.MoveToWorld(Definition.StoneLocation, Definition.Map);
|
||||
}
|
||||
|
||||
if (Banner1 == null)
|
||||
{
|
||||
Banner1 = new ArenaExitBanner(Definition.BannerID1, this);
|
||||
Banner1.MoveToWorld(Definition.BannerLocation1, Definition.Map);
|
||||
}
|
||||
|
||||
if (Banner2 == null)
|
||||
{
|
||||
Banner2 = new ArenaExitBanner(Definition.BannerID2, this);
|
||||
Banner2.MoveToWorld(Definition.BannerLocation2, Definition.Map);
|
||||
}
|
||||
|
||||
if (Region == null)
|
||||
{
|
||||
Region = new ArenaRegion(this);
|
||||
Region.Register();
|
||||
}
|
||||
|
||||
if (GuardRegion == null)
|
||||
{
|
||||
GuardRegion = new GuardedArenaRegion(String.Format("{0}_Guarded", Definition.Name), Definition.Map, Definition.GuardBounds);
|
||||
GuardRegion.Register();
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister()
|
||||
{
|
||||
if (Region != null)
|
||||
{
|
||||
Region.Unregister();
|
||||
Region = null;
|
||||
}
|
||||
|
||||
if (GuardRegion != null)
|
||||
{
|
||||
GuardRegion.Unregister();
|
||||
GuardRegion = null;
|
||||
}
|
||||
|
||||
if (Manager != null)
|
||||
{
|
||||
Manager.Delete();
|
||||
}
|
||||
|
||||
if (Stone != null && !Stone.Deleted)
|
||||
{
|
||||
Stone.Delete();
|
||||
}
|
||||
|
||||
if (Banner1 != null)
|
||||
{
|
||||
Banner1.Delete();
|
||||
}
|
||||
|
||||
if (Banner2 != null)
|
||||
{
|
||||
Banner2.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ArenaDuel> _Remove = new List<ArenaDuel>();
|
||||
|
||||
public void OnTick()
|
||||
{
|
||||
if (CurrentDuel != null)
|
||||
{
|
||||
CurrentDuel.OnTick();
|
||||
}
|
||||
|
||||
foreach (var kvp in PendingDuels)
|
||||
{
|
||||
if (kvp.Value < DateTime.UtcNow)
|
||||
{
|
||||
_Remove.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (_Remove.Count > 0)
|
||||
{
|
||||
foreach (var duel in _Remove)
|
||||
{
|
||||
if (PendingDuels.ContainsKey(duel))
|
||||
PendingDuels.Remove(duel);
|
||||
}
|
||||
|
||||
_Remove.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPendingDuel(ArenaDuel duel)
|
||||
{
|
||||
if (!PendingDuels.ContainsKey(duel))
|
||||
{
|
||||
PendingDuels[duel] = DateTime.UtcNow + PendingDuelExpirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePendingDuel(ArenaDuel duel, bool cancel = false)
|
||||
{
|
||||
if(PendingDuels.ContainsKey(duel))
|
||||
{
|
||||
PendingDuels.Remove(duel);
|
||||
|
||||
if (cancel)
|
||||
{
|
||||
PVPArenaSystem.SendParticipantMessage(duel, 1115947); // The session owner has canceled the duel.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ArenaDuel GetPendingDuel(Mobile m)
|
||||
{
|
||||
return PendingDuels.Keys.FirstOrDefault(d => m is PlayerMobile && d.IsParticipant((PlayerMobile)m));
|
||||
}
|
||||
|
||||
public List<ArenaDuel> GetPendingPublic()
|
||||
{
|
||||
return PendingDuels.Keys.Where(d => d.RoomType == RoomType.Public && d.ParticipantCount < d.Entries).ToList();
|
||||
}
|
||||
|
||||
public void TryBeginDuel(ArenaDuel duel)
|
||||
{
|
||||
if (PendingDuels.ContainsKey(duel))
|
||||
{
|
||||
PendingDuels.Remove(duel);
|
||||
}
|
||||
|
||||
if (CurrentDuel == null && BookedDuels.Count == 0)
|
||||
{
|
||||
CurrentDuel = duel;
|
||||
duel.DoPreDuel();
|
||||
}
|
||||
else
|
||||
{
|
||||
BookedDuels.Add(duel);
|
||||
PVPArenaSystem.SendParticipantMessage(duel, 1115960); // There are currently no open arenas. Your duel session has been added to the booking queue.
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDuelEnd(ArenaDuel duel)
|
||||
{
|
||||
CurrentDuel = null;
|
||||
|
||||
foreach (var corpse in Region.GetEnumeratedItems().OfType<Corpse>())
|
||||
{
|
||||
if (corpse.Owner != null && corpse.Owner.InRange(corpse.Location, 30))
|
||||
{
|
||||
corpse.MoveToWorld(corpse.Owner.Location, corpse.Owner.Map);
|
||||
}
|
||||
else
|
||||
{
|
||||
corpse.MoveToWorld(GetRandomRemovalLocation(), Definition.Map);
|
||||
}
|
||||
}
|
||||
|
||||
if (BookedDuels.Count > 0)
|
||||
{
|
||||
var newDuel = BookedDuels[0];
|
||||
CurrentDuel = newDuel;
|
||||
|
||||
PVPArenaSystem.SendParticipantMessage(newDuel, 1153141); // Your session has been booked. Please wait a few moments to start the fight.
|
||||
|
||||
Timer.DelayCall(BookedDuelBegin, () =>
|
||||
{
|
||||
newDuel.DoPreDuel();
|
||||
});
|
||||
|
||||
BookedDuels.Remove(newDuel);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemovePlayer(Mobile m, bool winner = false)
|
||||
{
|
||||
Map map = Definition.Map;
|
||||
Point3D p = GetRandomRemovalLocation(m);
|
||||
|
||||
m.MoveToWorld(p, map);
|
||||
m.Delta(MobileDelta.Noto);
|
||||
|
||||
// lets remove pets, too
|
||||
if (m is PlayerMobile && ((PlayerMobile)m).AllFollowers.Count > 0)
|
||||
{
|
||||
foreach (var mob in ((PlayerMobile)m).AllFollowers.Where(pet => pet.Region.IsPartOf<ArenaRegion>()))
|
||||
{
|
||||
mob.MoveToWorld(p, map);
|
||||
mob.Delta(MobileDelta.Noto);
|
||||
}
|
||||
}
|
||||
|
||||
if(winner)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
Timer.DelayCall(TimeSpan.FromMilliseconds(i * 1000), () =>
|
||||
{
|
||||
m.FixedParticles(0x373A, 10, 15, 5018, 0x36, 0, EffectLayer.Waist);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!m.Alive)
|
||||
{
|
||||
IPooledEnumerable eable = map.GetMobilesInRange(m.Location, 5);
|
||||
|
||||
foreach(Mobile mob in eable)
|
||||
{
|
||||
if (mob is ArenaManager)
|
||||
{
|
||||
((ArenaManager)mob).OfferResurrection(m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
private Point3D GetRandomRemovalLocation(Mobile m = null)
|
||||
{
|
||||
Rectangle2D rec = (m == null || m.Alive) ? Definition.EjectLocation : Definition.DeadEjectLocation;
|
||||
Point3D loc = (m == null || m.Alive) ? Definition.StoneLocation : Definition.ManagerLocation;
|
||||
Point3D p = loc;
|
||||
|
||||
Map map = Definition.Map;
|
||||
|
||||
while (p == loc || !map.CanSpawnMobile(p.X, p.Y, p.Z))
|
||||
{
|
||||
p = map.GetRandomSpawnPoint(rec);
|
||||
|
||||
if (m == null || m.Alive)
|
||||
p.Z = Definition.StoneLocation.Z;
|
||||
else
|
||||
p.Z = Definition.ManagerLocation.Z;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public void RecordRankings(ArenaDuel duel, ArenaTeam winners)
|
||||
{
|
||||
List<ArenaStats> rankings;
|
||||
|
||||
if (duel.BattleMode == BattleMode.Team)
|
||||
rankings = TeamRankings;
|
||||
else
|
||||
rankings = SurvivalRankings;
|
||||
|
||||
foreach (var part in duel.GetParticipants())
|
||||
{
|
||||
var pm = part.Key;
|
||||
ArenaStats stats = rankings.FirstOrDefault(r => r.Owner == pm);
|
||||
|
||||
if (stats == null)
|
||||
{
|
||||
stats = new ArenaStats(pm);
|
||||
rankings.Add(stats);
|
||||
}
|
||||
|
||||
var team = duel.GetTeam(pm);
|
||||
|
||||
if (team != winners)
|
||||
{
|
||||
stats.Ranking -= 33;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.Ranking += 33;
|
||||
}
|
||||
}
|
||||
|
||||
rankings.Sort();
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(0);
|
||||
|
||||
writer.Write(SurvivalRankings.Count);
|
||||
foreach (var ranking in SurvivalRankings)
|
||||
{
|
||||
ranking.Serialize(writer);
|
||||
}
|
||||
|
||||
writer.Write(TeamRankings.Count);
|
||||
foreach (var ranking in TeamRankings)
|
||||
{
|
||||
ranking.Serialize(writer);
|
||||
}
|
||||
|
||||
writer.Write(Blockers.Count);
|
||||
foreach (var blocker in Blockers)
|
||||
{
|
||||
writer.Write(blocker);
|
||||
}
|
||||
|
||||
writer.Write(Stone);
|
||||
writer.Write(Manager);
|
||||
writer.Write(Banner1);
|
||||
writer.Write(Banner2);
|
||||
|
||||
writer.Write(PendingDuels.Count);
|
||||
foreach (var kvp in PendingDuels)
|
||||
{
|
||||
kvp.Key.Serialize(writer);
|
||||
writer.WriteDeltaTime(kvp.Value);
|
||||
}
|
||||
|
||||
writer.Write(BookedDuels.Count);
|
||||
foreach (var duel in BookedDuels)
|
||||
{
|
||||
duel.Serialize(writer);
|
||||
}
|
||||
|
||||
if (CurrentDuel != null)
|
||||
{
|
||||
writer.Write(1);
|
||||
CurrentDuel.Serialize(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
int count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ArenaStats stats = new ArenaStats(reader);
|
||||
|
||||
if (stats.Owner != null)
|
||||
SurvivalRankings.Add(stats);
|
||||
}
|
||||
|
||||
count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ArenaStats stats = new ArenaStats(reader);
|
||||
|
||||
if (stats.Owner != null)
|
||||
TeamRankings.Add(stats);
|
||||
}
|
||||
|
||||
count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Item blocker = reader.ReadItem();
|
||||
|
||||
if (blocker != null)
|
||||
Blockers.Add(blocker);
|
||||
}
|
||||
|
||||
Stone = reader.ReadItem() as ArenaStone;
|
||||
Manager = reader.ReadMobile() as ArenaManager;
|
||||
Banner1 = reader.ReadItem() as ArenaExitBanner;
|
||||
Banner2 = reader.ReadItem() as ArenaExitBanner;
|
||||
|
||||
count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ArenaDuel duel = new ArenaDuel(reader, this);
|
||||
DateTime dt = reader.ReadDeltaTime();
|
||||
|
||||
PendingDuels[duel] = dt;
|
||||
}
|
||||
|
||||
count = reader.ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
BookedDuels.Add(new ArenaDuel(reader, this));
|
||||
}
|
||||
|
||||
if (reader.ReadInt() == 1)
|
||||
{
|
||||
CurrentDuel = new ArenaDuel(reader, this);
|
||||
}
|
||||
|
||||
if (Stone != null)
|
||||
Stone.Arena = this;
|
||||
|
||||
if (Manager != null)
|
||||
Manager.Arena = this;
|
||||
|
||||
if (Banner1 != null)
|
||||
Banner1.Arena = this;
|
||||
|
||||
if (Banner2 != null)
|
||||
Banner2.Arena = this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ArenaStats : IComparable<ArenaStats>
|
||||
{
|
||||
public PlayerMobile Owner { get; set; }
|
||||
public int Ranking { get; set; }
|
||||
|
||||
public ArenaStats(PlayerMobile pm)
|
||||
{
|
||||
Owner = pm;
|
||||
Ranking = 10000;
|
||||
}
|
||||
|
||||
public int CompareTo(ArenaStats stats)
|
||||
{
|
||||
if(Ranking > stats.Ranking)
|
||||
return -1;
|
||||
|
||||
if(Ranking < stats.Ranking)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ArenaStats(GenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Owner = reader.ReadMobile() as PlayerMobile;
|
||||
Ranking = reader.ReadInt();
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
writer.Write(0);
|
||||
|
||||
writer.Write(Owner);
|
||||
writer.Write(Ranking);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user