Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,678 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Accounting;
using Server.Mobiles;
using VitaNex.IO;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public delegate void SeasonChangedHandler(PvPSeason newSeason, PvPSeason oldSeason);
public static partial class AutoPvP
{
public const AccessLevel Access = AccessLevel.Seer;
public static ScheduleInfo DefaultSeasonSchedule = new ScheduleInfo(ScheduleMonths.All, ScheduleDays.Monday, ScheduleTimes.Midnight);
public static AutoPvPOptions CMOptions { get; private set; }
public static BinaryDataStore<int, PvPSeason> Seasons { get; private set; }
public static BinaryDataStore<PlayerMobile, PvPProfile> Profiles { get; private set; }
public static BinaryDirectoryDataStore<PvPSerial, PvPBattle> Battles { get; private set; }
public static Dictionary<IAccount, Timer> Deserters { get; private set; }
public static Type[] BattleTypes { get; set; }
public static PvPScenario[] Scenarios { get; set; }
public static Schedule SeasonSchedule { get; set; }
public static PvPSeason CurrentSeason => EnsureSeason(CMOptions.Advanced.Seasons.CurrentSeason);
public static DateTime NextSeasonTime => SeasonSchedule.NextGlobalTick ?? DateTime.UtcNow;
private static DateTime LastSort { get; set; }
private static TimeSpan CacheDelay { get; set; }
private static List<PvPProfile> CachedSort { get; set; }
public static event Action<PvPSeason> OnSeasonChanged;
public static event Action<PvPBattle, PvPTeam, PlayerMobile> OnQueueJoin;
public static event Action<PvPBattle, PvPTeam, PlayerMobile> OnQueueLeave;
public static event Action<PvPBattle, PvPTeam, PlayerMobile> OnQueueUpdate;
public static event Action<PvPBattle, PvPRegion, Mobile> OnEnterBattle;
public static event Action<PvPBattle, PvPRegion, Mobile> OnExitBattle;
public static event Action<PvPBattle, string> OnBattleLocalBroadcast;
public static event Action<PvPBattle, string> OnBattleWorldBroadcast;
public static event Action<PvPBattle> OnBattleStateChanged;
public static void ChangeSeason(Schedule schedule)
{
if (!CMOptions.ModuleEnabled)
{
return;
}
if (CMOptions.Advanced.Seasons.SkippedTicks < CMOptions.Advanced.Seasons.SkipTicks)
{
++CMOptions.Advanced.Seasons.SkippedTicks;
return;
}
CMOptions.Advanced.Seasons.SkippedTicks = 0;
var old = CurrentSeason;
EnsureSeason(++CMOptions.Advanced.Seasons.CurrentSeason).Start();
old.End();
SeasonChanged(old);
}
public static void SeasonChanged(PvPSeason old)
{
var idx = 0;
foreach (var profile in GetSortedProfiles(old).Where(o => o.Owner.AccessLevel <= AccessLevel.Player))
{
if (idx < CMOptions.Advanced.Seasons.TopListCount)
{
IssueWinnerRewards(old, ++idx, profile);
}
else if (idx < CMOptions.Advanced.Seasons.TopListCount + CMOptions.Advanced.Seasons.RunnersUpCount)
{
IssueLoserRewards(old, ++idx, profile);
}
else
{
break;
}
}
if (OnSeasonChanged != null)
{
OnSeasonChanged(old);
}
}
public static void IssueWinnerRewards(this PvPSeason season, int rank, PvPProfile profile)
{
var rewards = CMOptions.Advanced.Seasons.Rewards.Winner.GiveReward(profile.Owner);
if (rewards == null)
{
rewards = new List<Item>();
}
else
{
var fmt = "{0} (Season {1} - Rank {2})";
rewards.ForEach(r => r.Name = String.Format(fmt, r.ResolveName(profile.Owner), season.Number, rank));
}
if (!season.Winners.TryGetValue(profile.Owner, out var list) || list == null)
{
season.Winners[profile.Owner] = rewards;
}
else
{
list.AddRange(rewards);
rewards.Free(true);
}
}
public static void IssueLoserRewards(this PvPSeason season, int rank, PvPProfile profile)
{
var rewards = CMOptions.Advanced.Seasons.Rewards.Loser.GiveReward(profile.Owner);
if (rewards == null)
{
rewards = new List<Item>();
}
else
{
var fmt = "{0} (Season {1} - Rank {2})";
rewards.ForEach(r => r.Name = String.Format(fmt, r.ResolveName(profile.Owner), season.Number, rank));
}
if (!season.Losers.TryGetValue(profile.Owner, out var list) || list == null)
{
season.Losers[profile.Owner] = rewards;
}
else
{
list.AddRange(rewards);
rewards.Free(true);
}
}
public static PvPSeason EnsureSeason(int num, bool replace = false)
{
if (!Seasons.TryGetValue(num, out var season) || season == null || replace)
{
Seasons[num] = season = new PvPSeason(num);
}
return season;
}
public static PvPProfile EnsureProfile(PlayerMobile pm, bool replace = false)
{
if (!Profiles.ContainsKey(pm))
{
Profiles.Add(pm, new PvPProfile(pm));
}
else if (replace || Profiles[pm] == null || Profiles[pm].Deleted)
{
Profiles[pm] = new PvPProfile(pm);
}
return Profiles[pm];
}
public static IEnumerable<PvPProfile> GetSortedProfiles(PvPSeason season = null)
{
return GetSortedProfiles(CMOptions.Advanced.Profiles.RankingOrder, season);
}
public static IEnumerable<PvPProfile> GetSortedProfiles(IEnumerable<PvPProfile> profiles, PvPSeason season = null)
{
return GetSortedProfiles(CMOptions.Advanced.Profiles.RankingOrder, profiles, season);
}
public static IEnumerable<PvPProfile> GetSortedProfiles(PvPProfileRankOrder order, PvPSeason season = null)
{
return GetSortedProfiles(order, null, season);
}
public static IEnumerable<PvPProfile> GetSortedProfiles(PvPProfileRankOrder order, IEnumerable<PvPProfile> profiles, PvPSeason season = null)
{
if (profiles == null)
{
profiles = Profiles.Values;
if (Profiles.Count > 1024)
{
profiles = profiles.AsParallel();
}
}
return profiles.OrderByDescending(p => GetSortedValue(order, p, season));
}
public static long GetSortedValue(PvPProfileRankOrder order, PvPProfile profile, PvPSeason season = null)
{
switch (order)
{
case PvPProfileRankOrder.Points:
{
if (season == null)
{
return profile.TotalPoints;
}
return profile.History.EnsureEntry(season).Points;
}
case PvPProfileRankOrder.Wins:
{
if (season == null)
{
return profile.TotalWins;
}
return profile.History.EnsureEntry(season).Wins;
}
case PvPProfileRankOrder.Kills:
{
if (season == null)
{
return profile.TotalKills;
}
return profile.History.EnsureEntry(season).Kills;
}
}
return 0;
}
public static void InvokeQueueJoin(PvPBattle battle, PvPTeam team, PlayerMobile m)
{
if (OnQueueJoin != null)
{
OnQueueJoin(battle, team, m);
}
}
public static void InvokeQueueLeave(PvPBattle battle, PvPTeam team, PlayerMobile m)
{
if (OnQueueLeave != null)
{
OnQueueLeave(battle, team, m);
}
}
public static void InvokeQueueUpdate(PvPBattle battle, PvPTeam team, PlayerMobile m)
{
if (OnQueueUpdate != null)
{
OnQueueUpdate(battle, team, m);
}
}
public static void InvokeEnterBattle(PvPBattle battle, PvPRegion region, Mobile m)
{
if (OnEnterBattle != null)
{
OnEnterBattle(battle, region, m);
}
}
public static void InvokeExitBattle(PvPBattle battle, PvPRegion region, Mobile m)
{
if (OnExitBattle != null)
{
OnExitBattle(battle, region, m);
}
}
public static void InvokeBattleLocalBroadcast(PvPBattle battle, string message)
{
if (OnBattleLocalBroadcast != null)
{
OnBattleLocalBroadcast(battle, message);
}
}
public static void InvokeBattleWorldBroadcast(PvPBattle battle, string message)
{
if (OnBattleWorldBroadcast != null)
{
OnBattleWorldBroadcast(battle, message);
}
}
public static void InvokeBattleStateChanged(PvPBattle battle)
{
if (OnBattleStateChanged != null)
{
OnBattleStateChanged(battle);
}
}
public static PvPBattle FindBattleByID(int uid)
{
return Battles.Where(o => o.Key.ValueHash.Equals(uid)).Select(kvp => kvp.Value).FirstOrDefault();
}
public static PvPBattle FindBattleByID(PvPSerial serial)
{
return Battles.Where(o => o.Key.Equals(serial)).Select(kvp => kvp.Value).FirstOrDefault();
}
public static PvPBattle FindBattle(PlayerMobile pm)
{
return FindBattle<PvPBattle>(pm);
}
public static T FindBattle<T>(PlayerMobile pm)
where T : PvPBattle
{
if (IsParticipant(pm, out T battle) || IsSpectator(pm, out battle))
{
return battle;
}
return default(T);
}
public static bool IsParticipant(PlayerMobile pm)
{
return pm != null && IsParticipant<PvPBattle>(pm);
}
public static bool IsParticipant<T>(PlayerMobile pm)
where T : PvPBattle
{
return pm != null && Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().Any(b => b.IsParticipant(pm));
}
public static bool IsParticipant<T>(PlayerMobile pm, out T battle)
where T : PvPBattle
{
battle = default(T);
if (pm == null)
{
return false;
}
battle = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().FirstOrDefault(b => b.IsParticipant(pm));
return battle != null;
}
public static ILookup<PvPBattle, IEnumerable<PlayerMobile>> GetParticipants()
{
return GetParticipants<PvPBattle>();
}
public static ILookup<T, IEnumerable<PlayerMobile>> GetParticipants<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.ToLookup(b => b, b => b.GetParticipants());
}
public static ILookup<PvPBattle, int> CountParticipants()
{
return CountParticipants<PvPBattle>();
}
public static ILookup<T, int> CountParticipants<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.ToLookup(b => b, b => b.GetParticipants().Count());
}
public static int TotalParticipants()
{
return TotalParticipants<PvPBattle>();
}
public static int TotalParticipants<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.Aggregate(0, (c, b) => c + b.GetParticipants().Count());
}
public static bool IsSpectator(PlayerMobile pm)
{
return pm != null && IsSpectator<PvPBattle>(pm);
}
public static bool IsSpectator<T>(PlayerMobile pm)
where T : PvPBattle
{
return pm != null && Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().Any(b => b.IsSpectator(pm));
}
public static bool IsSpectator<T>(PlayerMobile pm, out T battle)
where T : PvPBattle
{
battle = default(T);
if (pm == null)
{
return false;
}
battle = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().FirstOrDefault(b => b.IsSpectator(pm));
return battle != null;
}
public static ILookup<PvPBattle, IEnumerable<PlayerMobile>> GetSpectators()
{
return GetSpectators<PvPBattle>();
}
public static ILookup<T, IEnumerable<PlayerMobile>> GetSpectators<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.ToLookup(b => b, b => b.GetSpectators());
}
public static ILookup<PvPBattle, int> CountSpectators()
{
return CountSpectators<PvPBattle>();
}
public static ILookup<T, int> CountSpectators<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.ToLookup(b => b, b => b.Spectators.Count);
}
public static int TotalSpectators()
{
return TotalSpectators<PvPBattle>();
}
public static int TotalSpectators<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.Aggregate(0, (c, b) => c + b.Spectators.Count);
}
public static void AddDeserter(PlayerMobile pm)
{
AddDeserter(pm, true);
}
public static void AddDeserter(PlayerMobile pm, bool message)
{
SetDeserter(pm, true, message);
}
public static void RemoveDeserter(PlayerMobile pm)
{
RemoveDeserter(pm, true);
}
public static void RemoveDeserter(PlayerMobile pm, bool message)
{
SetDeserter(pm, false, message);
}
public static void SetDeserter(PlayerMobile pm, bool state, bool message)
{
if (pm == null)
{
return;
}
var t = Deserters.GetValue(pm.Account);
if (t != null && t.Running)
{
t.Stop();
}
if (state && CMOptions.Advanced.Misc.DeserterLockout > TimeSpan.Zero)
{
Deserters[pm.Account] = t = Timer.DelayCall(CMOptions.Advanced.Misc.DeserterLockout, RemoveDeserter, pm);
if (message)
{
pm.SendMessage(0x22, "You have deserted your team and must wait until you can join another battle.");
}
if (!CMOptions.Advanced.Misc.DeserterAssoc)
{
return;
}
foreach (var a in pm.Account.FindSharedAccounts().Where(a => a != pm.Account && !Deserters.ContainsKey(a)))
{
Deserters[a] = t;
var p = a.GetOnlineMobile();
if (p != null)
{
p.SendMessage(0x22, "{0} has deserted a battle!", pm.RawName);
p.SendMessage(0x22, "You must wait until you can join a battle because you have associated accounts.");
}
}
}
else
{
if (Deserters.Remove(pm.Account) && message)
{
pm.SendMessage(0x55, "You are no longer known as a deserter and may now join battles.");
}
if (t == null)
{
return;
}
Deserters.RemoveRange(
o =>
{
if (o.Value == null)
{
return true;
}
if (o.Value == t)
{
var p = o.Key.GetOnlineMobile();
if (p != null)
{
p.SendMessage(0x55, "You are no longer associated with a deserter and may now join battles.");
}
return true;
}
return false;
});
}
}
public static bool IsDeserter(PlayerMobile pm)
{
return pm != null && pm.Account != null && Deserters.GetValue(pm.Account) != null;
}
public static IEnumerable<PvPBattle> GetBattles(params PvPBattleState[] states)
{
return GetBattles<PvPBattle>(states);
}
public static IEnumerable<T> GetBattles<T>(params PvPBattleState[] states)
where T : PvPBattle
{
if (states == null || states.Length == 0)
{
return Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
}
return Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().Where(b => states.Contains(b.State));
}
public static int CountBattles(params PvPBattleState[] states)
{
return CountBattles<PvPBattle>(states);
}
public static int CountBattles<T>(params PvPBattleState[] states)
where T : PvPBattle
{
if (states == null || states.Length == 0)
{
return Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().Count();
}
return Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>().Count(b => states.Contains(b.State));
}
public static void DeleteAllBattles()
{
Battles.Values.Where(b => b != null && !b.Deleted).ForEach(b => b.Delete());
}
public static void InternalizeAllBattles()
{
Battles.Values.Where(b => b != null && !b.Deleted).ForEach(b => b.State = PvPBattleState.Internal);
}
public static PvPBattle CreateBattle(PvPScenario scenario)
{
if (scenario == null)
{
return null;
}
var battle = scenario.CreateBattle();
Battles[battle.Serial] = battle;
battle.Init();
return battle;
}
public static bool RemoveBattle(PvPBattle battle)
{
return battle != null && Battles.Remove(battle.Serial);
}
public static bool RemoveProfile(PvPProfile profile)
{
if (profile != null && Profiles.GetValue(profile.Owner) == profile && Profiles.Remove(profile.Owner))
{
profile.Remove();
return true;
}
return false;
}
public static void DeleteAllProfiles()
{
Profiles.Values.Where(p => p != null && !p.Deleted).ForEach(p => p.Delete());
}
public static int TotalQueued()
{
return TotalQueued<PvPBattle>();
}
public static int TotalQueued<T>()
where T : PvPBattle
{
var battles = Battles.Values.Where(b => b != null && !b.Deleted).OfType<T>();
return battles.Aggregate(0, (c, b) => c + b.Queue.Count);
}
}
}

View File

@@ -0,0 +1,495 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Accounting;
using Server.Mobiles;
using VitaNex.IO;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[CoreModule("Auto PvP", "3.1.0.0", false, TaskPriority.High)]
public static partial class AutoPvP
{
static AutoPvP()
{
CMOptions = new AutoPvPOptions();
Scenarios = new PvPScenario[0];
BattleTypes = typeof(PvPBattle).GetConstructableChildren();
SeasonSchedule = new Schedule(CMOptions.ModuleName + " Seasons", false, DefaultSeasonSchedule);
Seasons = new BinaryDataStore<int, PvPSeason>(VitaNexCore.SavesDirectory + "/AutoPvP", "Seasons")
{
OnSerialize = SerializeSeasons,
OnDeserialize = DeserializeSeasons
};
Battles = new BinaryDirectoryDataStore<PvPSerial, PvPBattle>(VitaNexCore.SavesDirectory + "/AutoPvP", "Battles", "pvp")
{
OnSerialize = SerializeBattle,
OnDeserialize = DeserializeBattle
};
Profiles = new BinaryDataStore<PlayerMobile, PvPProfile>(VitaNexCore.SavesDirectory + "/AutoPvP", "Profiles")
{
Async = true,
OnSerialize = SerializeProfiles,
OnDeserialize = DeserializeProfiles
};
Deserters = new Dictionary<IAccount, Timer>();
}
private static void CMConfig()
{
SeasonSchedule.OnGlobalTick += ChangeSeason;
}
private static void CMEnabled()
{
PvPBattle.Bind();
BattleNotoriety.Enable();
}
private static void CMDisabled()
{
InternalizeAllBattles();
PvPBattle.Unbind();
BattleNotoriety.Disable();
}
private static void CMInvoke()
{
PvPBattle.Bind();
BattleNotoriety.Enable();
var scenarios = new List<PvPScenario>();
foreach (var type in BattleTypes.Where(t => t != null))
{
VitaNexCore.TryCatch(
() =>
{
var battle = type.CreateInstanceSafe<PvPBattle>();
if (battle == null)
{
throw new Exception("PvPBattle Type could not be constructed, requires a constructor with 0 arguments.");
}
PvPScenario scenario = battle;
scenarios.Add(scenario);
battle.Delete();
CMOptions.ToConsole("Created scenario ({0}) '{1}'", scenario.TypeOf.Name, scenario.Name);
},
CMOptions.ToConsole);
}
Scenarios = scenarios.ToArray();
scenarios.Clear();
foreach (var battle in Battles.Values.Where(b => b != null && !b.Deleted).ToArray())
{
VitaNexCore.TryCatch(
battle.Init,
ex =>
{
VitaNexCore.TryCatch(battle.Delete);
CMOptions.ToConsole("Failed to initialize battle #{0} '{1}'", battle.Serial, battle.Name);
CMOptions.ToConsole(ex);
});
}
foreach (var profile in Profiles.Values.Where(p => p != null && !p.Deleted).ToArray())
{
VitaNexCore.TryCatch(
profile.Init,
ex =>
{
VitaNexCore.TryCatch(profile.Delete);
CMOptions.ToConsole("Failed to initialize profile #{0} '{1}'", profile.Owner.Serial.Value, profile.Owner.RawName);
CMOptions.ToConsole(ex);
});
}
}
private static void CMSave()
{
Save();
Sync();
}
private static void CMLoad()
{
Load();
Sync();
}
public static void Save()
{
VitaNexCore.TryCatch(SaveSeasons, CMOptions.ToConsole);
VitaNexCore.TryCatch(SaveBattles, CMOptions.ToConsole);
VitaNexCore.TryCatch(SaveProfiles, CMOptions.ToConsole);
}
public static void SaveSeasons()
{
var result = Seasons.Export();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Seasons.HasErrors)
{
CMOptions.ToConsole("Seasons database has errors...");
Seasons.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Season count: {0:#,0}", Seasons.Count);
break;
}
}
public static void SaveProfiles()
{
var result = Profiles.Export();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Profiles.HasErrors)
{
CMOptions.ToConsole("Profiles database has errors...");
Profiles.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Profile count: {0:#,0}", Profiles.Count);
break;
}
}
public static void SaveBattles()
{
var result = Battles.Export();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Battles.HasErrors)
{
CMOptions.ToConsole("Battles database has errors...");
Battles.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Battle count: {0:#,0}", Battles.Count);
break;
}
}
public static void Load()
{
VitaNexCore.TryCatch(LoadSeasons, CMOptions.ToConsole);
VitaNexCore.TryCatch(LoadBattles, CMOptions.ToConsole);
VitaNexCore.TryCatch(LoadProfiles, CMOptions.ToConsole);
}
public static void LoadSeasons()
{
var result = Seasons.Import();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Seasons.HasErrors)
{
CMOptions.ToConsole("Seasons database has errors...");
Seasons.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Season count: {0:#,0}", Seasons.Count);
break;
}
}
public static void LoadProfiles()
{
var result = Profiles.Import();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Profiles.HasErrors)
{
CMOptions.ToConsole("Profiles database has errors...");
Profiles.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Profile count: {0:#,0}", Profiles.Count);
break;
}
}
public static void LoadBattles()
{
var result = Battles.Import();
CMOptions.ToConsole("Result: {0}", result.ToString());
switch (result)
{
case DataStoreResult.Null:
case DataStoreResult.Busy:
case DataStoreResult.Error:
{
if (Battles.HasErrors)
{
CMOptions.ToConsole("Battles database has errors...");
Battles.Errors.ForEach(CMOptions.ToConsole);
}
}
break;
case DataStoreResult.OK:
CMOptions.ToConsole("Battle count: {0:#,0}", Battles.Count);
break;
}
}
public static void Sync()
{
VitaNexCore.TryCatch(SyncSeasons, CMOptions.ToConsole);
VitaNexCore.TryCatch(SyncBattles, CMOptions.ToConsole);
}
public static void SyncSeasons()
{
foreach (var season in Seasons.Values)
{
VitaNexCore.TryCatch(
season.Sync,
ex =>
{
CMOptions.ToConsole("Failed to sync season #{0}", season.Number);
CMOptions.ToConsole(ex);
});
}
}
public static void SyncBattles()
{
foreach (var battle in Battles.Values)
{
VitaNexCore.TryCatch(
battle.Sync,
ex =>
{
CMOptions.ToConsole("Failed to sync battle #{0} '{1}'", battle.Serial, battle.Name);
CMOptions.ToConsole(ex);
});
}
}
private static bool SerializeSeasons(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlockDictionary(
Seasons,
(w, key, val) =>
{
w.Write(key);
w.WriteType(val, t => val.Serialize(w));
});
}
break;
}
return true;
}
private static bool DeserializeSeasons(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlockDictionary(
r =>
{
var key = r.ReadInt();
var val = r.ReadTypeCreate<PvPSeason>(r) ?? new PvPSeason(key);
return new KeyValuePair<int, PvPSeason>(key, val);
},
Seasons);
}
break;
}
return true;
}
private static bool SerializeProfiles(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlockDictionary(
Profiles,
(w, key, val) =>
{
w.Write(key);
w.WriteType(val, t => val.Serialize(w));
});
}
break;
}
return true;
}
private static bool DeserializeProfiles(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlockDictionary(
r =>
{
var key = r.ReadMobile<PlayerMobile>();
var val = r.ReadTypeCreate<PvPProfile>(r);
return new KeyValuePair<PlayerMobile, PvPProfile>(key, val);
},
Profiles);
}
break;
}
return true;
}
private static bool SerializeBattle(GenericWriter writer, PvPSerial key, PvPBattle val)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlock(w => w.WriteType(key, t => key.Serialize(w)));
writer.WriteBlock(w => w.WriteType(val, t => val.Serialize(w)));
}
break;
}
return true;
}
private static Tuple<PvPSerial, PvPBattle> DeserializeBattle(GenericReader reader)
{
PvPSerial key = null;
PvPBattle val = null;
var version = reader.GetVersion();
switch (version)
{
case 0:
{
key = reader.ReadBlock(r => r.ReadTypeCreate<PvPSerial>(r));
val = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattle>(r));
}
break;
}
if (key == null)
{
if (val != null && val.Serial != null)
{
key = val.Serial;
}
else
{
return null;
}
}
return new Tuple<PvPSerial, PvPBattle>(key, val);
}
}
}

View File

@@ -0,0 +1,282 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Mobiles;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class CTFBattle : PvPBattle
{
[CommandProperty(AutoPvP.Access)]
public virtual double FlagDamageInc { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual double FlagDamageIncMax { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int FlagCapturePoints { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int FlagReturnPoints { get; set; }
public CTFBattle()
{
Name = "Capture The Flag";
Category = "Capture The Flag";
Description = "Capture the enemy flag and return it to your podium to score points!" +
"\nDefend your flag from the enemy, you can only capture their flag when your flag is on your podium.";
AddTeam(NameList.RandomName("daemon"), 1, 5, 0x22);
AddTeam(NameList.RandomName("daemon"), 1, 5, 0x55);
Options.Missions.Enabled = true;
Options.Missions.Team = new CTFBattleObjectives
{
FlagsCaptured = 5
};
Schedule.Info.Months = ScheduleMonths.All;
Schedule.Info.Days = ScheduleDays.All;
Schedule.Info.Times = ScheduleTimes.EveryQuarterHour;
Options.Timing.QueuePeriod = TimeSpan.FromMinutes(5.0);
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(5.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(15.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(5.0);
Options.Rules.AllowBeneficial = true;
Options.Rules.AllowHarmful = true;
Options.Rules.AllowHousing = false;
Options.Rules.AllowPets = false;
Options.Rules.AllowSpawn = false;
Options.Rules.AllowSpeech = true;
Options.Rules.CanBeDamaged = true;
Options.Rules.CanDamageEnemyTeam = true;
Options.Rules.CanDamageOwnTeam = false;
Options.Rules.CanDie = false;
Options.Rules.CanHeal = true;
Options.Rules.CanHealEnemyTeam = false;
Options.Rules.CanHealOwnTeam = true;
Options.Rules.CanMount = false;
Options.Rules.CanFly = false;
Options.Rules.CanResurrect = true;
Options.Rules.CanUseStuckMenu = false;
Options.Rules.CanEquip = true;
}
public CTFBattle(GenericReader reader)
: base(reader)
{ }
public override bool Validate(Mobile viewer, List<string> errors, bool pop = true)
{
if (!base.Validate(viewer, errors, pop) && pop)
{
return false;
}
if (!Teams.All(t => t is CTFTeam))
{
errors.Add("One or more teams are not of the CTFTeam type.");
errors.Add("[Options] -> [View Teams]");
if (pop)
{
return false;
}
}
return true;
}
public override bool AddTeam(string name, int minCapacity, int capacity, int color)
{
return AddTeam(new CTFTeam(this, name, minCapacity, capacity, color));
}
public override bool AddTeam(PvPTeam team)
{
if (team == null || team.Deleted)
{
return false;
}
if (team is CTFTeam)
{
return base.AddTeam(team);
}
var added = AddTeam(team.Name, team.MinCapacity, team.MinCapacity, team.Color);
team.Delete();
return added;
}
public virtual void OnFlagDropped(CTFFlag flag, PlayerMobile attacker, CTFTeam enemyTeam)
{
UpdateStatistics(enemyTeam, attacker, s => ++s["Flags Dropped"]);
PlaySound(746);
LocalBroadcast("[{0}]: {1} has dropped the flag of {2}!", enemyTeam.Name, attacker.Name, flag.Team.Name);
}
public virtual void OnFlagCaptured(CTFFlag flag, PlayerMobile attacker, CTFTeam enemyTeam)
{
UpdateStatistics(enemyTeam, attacker, s => ++s["Flags Captured"]);
if (FlagCapturePoints > 0)
{
AwardPoints(attacker, FlagCapturePoints);
}
PlaySound(747);
LocalBroadcast("[{0}]: {1} has captured the flag of {2}!", enemyTeam.Name, attacker.Name, flag.Team.Name);
}
public virtual void OnFlagStolen(CTFFlag flag, PlayerMobile attacker, CTFTeam enemyTeam)
{
UpdateStatistics(enemyTeam, attacker, s => ++s["Flags Stolen"]);
PlaySound(748);
LocalBroadcast("[{0}]: {1} has stolen the flag of {2}!", enemyTeam.Name, attacker.Name, flag.Team.Name);
}
public virtual void OnFlagReturned(CTFFlag flag, PlayerMobile defender)
{
UpdateStatistics(flag.Team, defender, s => ++s["Flags Returned"]);
if (FlagReturnPoints > 0)
{
AwardPoints(defender, FlagReturnPoints);
}
PlaySound(749);
LocalBroadcast("[{0}]: {1} has returned the flag of {0}!", flag.Team.Name, defender.Name);
}
public virtual void OnFlagTimeout(CTFFlag flag)
{
PlaySound(749);
LocalBroadcast("[{0}]: Flag has been returned to the base!", flag.Team.Name);
}
public override bool CheckDamage(Mobile damaged, ref int damage)
{
if (!base.CheckDamage(damaged, ref damage))
{
return false;
}
if (damaged != null && damaged.Player && damaged.Backpack != null && damage > 0)
{
var flag = damaged.Backpack.FindItemByType<CTFFlag>();
if (flag != null)
{
damage += (int)(damage * flag.DamageInc);
}
}
return true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(3);
switch (version)
{
case 3:
case 2:
{
writer.Write(FlagDamageInc);
writer.Write(FlagDamageIncMax);
}
goto case 1;
case 1:
{
writer.Write(FlagCapturePoints);
writer.Write(FlagReturnPoints);
}
goto case 0;
case 0:
writer.Write(-1); // CapsToWin
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
if (!(Options.Missions.Team is CTFBattleObjectives))
{
Options.Missions.Enabled = true;
Options.Missions.Team = new CTFBattleObjectives
{
FlagsCaptured = 5
};
}
var version = reader.ReadInt();
switch (version)
{
case 3:
case 2:
{
FlagDamageInc = reader.ReadDouble();
FlagDamageIncMax = reader.ReadDouble();
}
goto case 1;
case 1:
{
FlagCapturePoints = reader.ReadInt();
FlagReturnPoints = reader.ReadInt();
}
goto case 0;
case 0:
{
var capsToWin = reader.ReadInt();
if (capsToWin >= 0)
{
((CTFBattleObjectives)Options.Missions.Team).FlagsCaptured = capsToWin;
}
}
break;
}
if (version < 3)
{
RewardTeam = true;
}
}
}
}

View File

@@ -0,0 +1,313 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using System.Text;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class CTFBattleObjectives : PvPBattleObjectives
{
[CommandProperty(AutoPvP.Access)]
public long FlagsCaptured { get; set; }
[CommandProperty(AutoPvP.Access)]
public long FlagsDropped { get; set; }
[CommandProperty(AutoPvP.Access)]
public long FlagsStolen { get; set; }
[CommandProperty(AutoPvP.Access)]
public long FlagsReturned { get; set; }
public override bool IsEmpty => base.IsEmpty && FlagsCaptured + FlagsDropped + FlagsStolen + FlagsReturned <= 0;
public CTFBattleObjectives()
{ }
public CTFBattleObjectives(GenericReader reader)
: base(reader)
{ }
public override void SetDefaults()
{
base.SetDefaults();
FlagsCaptured = 0;
FlagsDropped = 0;
FlagsStolen = 0;
FlagsReturned = 0;
}
public override double ComputeScore(PvPTeam t, ref double min, ref double max, ref double total)
{
var score = base.ComputeScore(t, ref min, ref max, ref total);
if (t == null || t.Deleted)
{
return score;
}
var ct = t as CTFTeam;
if (ct == null)
{
return score;
}
double val;
if (FlagsCaptured > 0)
{
score += val = Math.Min(1.0, ct.GetTotalFlagsCaptured() / (double)FlagsCaptured);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsDropped > 0)
{
score += val = Math.Min(1.0, ct.GetTotalFlagsDropped() / (double)FlagsDropped);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsStolen > 0)
{
score += val = Math.Min(1.0, ct.GetTotalFlagsStolen() / (double)FlagsStolen);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsReturned > 0)
{
score += val = Math.Min(1.0, ct.GetTotalFlagsReturned() / (double)FlagsReturned);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
return score;
}
public override double ComputeScore(PvPBattle b, PlayerMobile p, ref double min, ref double max, ref double total)
{
var score = base.ComputeScore(b, p, ref min, ref max, ref total);
if (b == null || b.Deleted)
{
return score;
}
if (p == null || p.Deleted)
{
return score;
}
double val;
if (FlagsCaptured > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o["Flags Captured"]) / (double)FlagsCaptured);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsDropped > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o["Flags Dropped"]) / (double)FlagsDropped);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsStolen > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o["Flags Stolen"]) / (double)FlagsStolen);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (FlagsReturned > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o["Flags Returned"]) / (double)FlagsReturned);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
return score;
}
public override string GetStatus(PvPTeam t)
{
var status = base.GetStatus(t);
if (t == null || t.Deleted)
{
return status;
}
var ct = t as CTFTeam;
if (ct == null)
{
return status;
}
var lines = new StringBuilder(status);
if (FlagsCaptured > 0)
{
lines.AppendLine("Flags Captured: {0:#,0} / {1:#,0}", ct.GetTotalFlagsCaptured(), FlagsCaptured);
}
if (FlagsDropped > 0)
{
lines.AppendLine("Flags Dropped: {0:#,0} / {1:#,0}", ct.GetTotalFlagsDropped(), FlagsDropped);
}
if (FlagsStolen > 0)
{
lines.AppendLine("Flags Stolen: {0:#,0} / {1:#,0}", ct.GetTotalFlagsStolen(), FlagsStolen);
}
if (FlagsReturned > 0)
{
lines.AppendLine("Flags Returned: {0:#,0} / {1:#,0}", ct.GetTotalFlagsReturned(), FlagsReturned);
}
return lines.ToString();
}
public override string GetStatus(PvPBattle b, PlayerMobile p)
{
var status = base.GetStatus(b, p);
if (b == null || b.Deleted)
{
return status;
}
if (p == null || p.Deleted)
{
return status;
}
var lines = new StringBuilder(status);
if (FlagsCaptured > 0)
{
lines.AppendLine("Flags Captured: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o["Flags Captured"]), FlagsCaptured);
}
if (FlagsDropped > 0)
{
lines.AppendLine("Flags Dropped: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o["Flags Dropped"]), FlagsDropped);
}
if (FlagsStolen > 0)
{
lines.AppendLine("Flags Stolen: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o["Flags Stolen"]), FlagsStolen);
}
if (FlagsReturned > 0)
{
lines.AppendLine("Flags Returned: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o["Flags Returned"]), FlagsReturned);
}
return lines.ToString();
}
public override void GetHtmlString(StringBuilder html)
{
base.GetHtmlString(html);
var len = html.Length;
if (FlagsCaptured > 0)
{
html.AppendLine("Flags Captured: {0:#,0}", FlagsCaptured);
}
if (FlagsDropped > 0)
{
html.AppendLine("Flags Dropped: {0:#,0}", FlagsDropped);
}
if (FlagsStolen > 0)
{
html.AppendLine("Flags Stolen: {0:#,0}", FlagsStolen);
}
if (FlagsReturned > 0)
{
html.AppendLine("Flags Returned: {0:#,0}", FlagsReturned);
}
if (len < html.Length)
{
html.Insert(len, String.Empty.WrapUOHtmlColor(Color.PaleGoldenrod, false));
html.AppendLine(String.Empty.WrapUOHtmlColor(Color.White, false));
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(FlagsCaptured);
writer.Write(FlagsDropped);
writer.Write(FlagsStolen);
writer.Write(FlagsReturned);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
FlagsCaptured = reader.ReadLong();
FlagsDropped = reader.ReadLong();
FlagsStolen = reader.ReadLong();
FlagsReturned = reader.ReadLong();
}
}
}

View File

@@ -0,0 +1,447 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using VitaNex.FX;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class CTFFlag : Item
{
private static readonly TimeSpan SplitSecond = TimeSpan.FromMilliseconds(250.0);
private static readonly TimeSpan HalfSecond = TimeSpan.FromSeconds(0.5);
private static readonly TimeSpan OneSecond = TimeSpan.FromSeconds(1.0);
private static readonly TimeSpan FiveSeconds = TimeSpan.FromSeconds(5.0);
private static readonly TimeSpan TenSeconds = TimeSpan.FromSeconds(10.0);
private static readonly TimeSpan TwentySeconds = TimeSpan.FromSeconds(20.0);
private DateTime _NextMultiUpdate = DateTime.UtcNow;
private DateTime _NextFlagReturn = DateTime.UtcNow;
[CommandProperty(AutoPvP.Access)]
public virtual CTFTeam Team { get; set; }
private PlayerMobile _Carrier;
[CommandProperty(AutoPvP.Access)]
public virtual PlayerMobile Carrier
{
get => _Carrier;
set
{
if (_Carrier == null || _Carrier == value)
{
return;
}
if (value == null)
{
Drop(_Carrier);
}
else
{
Drop(_Carrier);
Steal(value);
}
}
}
[CommandProperty(AutoPvP.Access)]
public virtual double DamageInc { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual DateTime NextAssault { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual DateTime NextEffect { get; set; }
public override bool HandlesOnMovement => RootParent == null;
public override bool Nontransferable => RootParent != null;
public override bool IsVirtualItem => RootParent != null;
public CTFFlag(CTFTeam team)
: base(8351)
{
Team = team;
Name = Team.Name;
Hue = Team.Color;
Weight = 10.1;
Movable = false;
NextAssault = NextEffect = DateTime.UtcNow;
}
public CTFFlag(Serial serial)
: base(serial)
{ }
public CTFTeam GetTeam(PlayerMobile pm)
{
return Team.Battle.FindTeam<CTFTeam>(pm);
}
public void Reset()
{
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted)
{
Delete();
return;
}
if (Team.FlagPodium != null && !Team.FlagPodium.Deleted)
{
MoveToWorld(Team.FlagPodium.Location.Clone3D(0, 0, Team.FlagPodium.ItemData.Height + 5), Team.FlagPodium.Map);
DamageInc = 0;
}
else
{
MoveToWorld(Team.HomeBase, Team.Battle.Options.Locations.Map);
DamageInc = 0;
}
NextAssault = DateTime.UtcNow;
}
public void Drop(PlayerMobile attacker)
{
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted)
{
Delete();
return;
}
if (attacker == null || attacker.Deleted || attacker != _Carrier)
{
return;
}
var enemy = GetTeam(attacker);
if (enemy != null)
{
attacker.SolidHueOverride = enemy.Color;
}
NextAssault = DateTime.UtcNow + FiveSeconds;
_Carrier = null;
_NextFlagReturn = DateTime.UtcNow + TwentySeconds;
MoveToWorld(attacker.Location, attacker.Map);
Team.OnFlagDropped(attacker, enemy);
InvalidateCarrier();
}
public void Steal(PlayerMobile attacker)
{
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted)
{
Delete();
return;
}
if (attacker == null || attacker.Deleted || attacker == _Carrier || attacker.Backpack == null || attacker.Backpack.Deleted)
{
return;
}
if (NextAssault > DateTime.UtcNow)
{
attacker.SendMessage(54, "This flag cannot be picked up for another {0} seconds.", (NextAssault - DateTime.UtcNow).TotalSeconds);
return;
}
if (attacker.HasItem<CTFFlag>())
{
attacker.SendMessage("You may only carry one flag at any given time!");
return;
}
if (!attacker.Backpack.TryDropItem(attacker, this, true))
{
return;
}
var enemy = GetTeam(attacker);
attacker.SolidHueOverride = 2498;
_Carrier = attacker;
Team.OnFlagStolen(attacker, enemy);
InvalidateCarrier();
}
public void Capture(PlayerMobile attacker)
{
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted)
{
Delete();
return;
}
if (attacker == null || attacker.Deleted)
{
return;
}
var enemy = GetTeam(attacker);
if (enemy != null)
{
attacker.SolidHueOverride = enemy.Color;
}
Team.OnFlagCaptured(attacker, enemy);
InvalidateCarrier();
Delete();
}
public void Return(PlayerMobile defender)
{
if (Team == null || Team.Deleted)
{
Delete();
return;
}
if (defender == null || defender.Deleted)
{
return;
}
if (Team.FlagPodium != null && !Team.FlagPodium.Deleted)
{
MoveToWorld(Team.FlagPodium.Location.Clone3D(0, 0, Team.FlagPodium.ItemData.Height + 5), Team.FlagPodium.Map);
}
else
{
MoveToWorld(Team.HomeBase, Team.Battle.Options.Locations.Map);
}
NextAssault = DateTime.UtcNow;
DamageInc = 0;
Team.OnFlagReturned(defender);
InvalidateCarrier();
}
public bool IsAtPodium()
{
return Carrier == null && (this.InRange2D(Team.FlagPodium, 0) || this.InRange2D(Team.HomeBase, 0));
}
public void UpdateDamageIncrease()
{
if (DateTime.UtcNow < _NextMultiUpdate)
{
return;
}
if (IsAtPodium())
{
DamageInc = 0;
}
else if (Carrier != null && DamageInc < Team.CTFBattle.FlagDamageIncMax)
{
DamageInc += Team.CTFBattle.FlagDamageInc;
_NextMultiUpdate = DateTime.UtcNow + TenSeconds;
}
}
public void CheckReset()
{
if (DateTime.UtcNow < _NextFlagReturn || Carrier != null || IsAtPodium())
{
return;
}
Team.CTFBattle.OnFlagTimeout(this);
Reset();
}
#if NEWPARENT
public override void OnParentDeleted(IEntity parent)
#else
public override void OnParentDeleted(object parent)
#endif
{
Drop(parent as PlayerMobile);
base.OnParentDeleted(parent);
}
public override DeathMoveResult OnParentDeath(Mobile parent)
{
Drop(parent as PlayerMobile);
return base.OnParentDeath(parent);
}
public override void OnDoubleClick(Mobile m)
{
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted ||
!this.CheckDoubleClick(m, true, false, 1) || !(m is PlayerMobile))
{
return;
}
var pm = (PlayerMobile)m;
var battle = Team.CTFBattle;
if (battle == null || !battle.IsParticipant(pm))
{
pm.SendMessage("You must be a participant to perform that action.");
return;
}
if (Team.IsMember(pm))
{
if (Team.FlagPodium != null && !Team.FlagPodium.Deleted)
{
if (!this.InRange3D(Team.FlagPodium, 1, -10, 10))
{
Return(pm);
}
}
else if (!this.InRange3D(Team.HomeBase, 1, -10, 10))
{
Return(pm);
}
}
else if (Carrier != pm)
{
Steal(pm);
}
else
{
Drop(pm);
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
if (Deleted || Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted || !(m is PlayerMobile) ||
!this.CheckDoubleClick(m, false, false, 1))
{
return;
}
var pm = (PlayerMobile)m;
var battle = Team.CTFBattle;
if (battle == null || !battle.IsParticipant(pm))
{
return;
}
if (Team.IsMember(pm))
{
if (Team.FlagPodium != null && !Team.FlagPodium.Deleted)
{
if (!this.InRange3D(Team.FlagPodium, 1, -10, 10))
{
Return(pm);
}
}
else if (!this.InRange3D(Team.HomeBase, 1, -10, 10))
{
Return(pm);
}
}
else if (Carrier != pm)
{
Steal(pm);
}
}
public void InvalidateCarrier()
{
if (Deleted)
{
_Carrier = null;
return;
}
if (Team == null || Team.Deleted)
{
Delete();
return;
}
InvalidateCarryEffect();
}
public void InvalidateCarryEffect()
{
if (Deleted || Carrier == null || Carrier.Deleted || !IsChildOf(Carrier.Backpack))
{
_Carrier = null;
return;
}
if (DateTime.UtcNow < NextEffect)
{
return;
}
new EffectInfo(Carrier.Clone3D(0, 0, 22), Carrier.Map, ItemID, Team.Color).Send();
NextEffect = DateTime.UtcNow + SplitSecond;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(_Carrier);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
_Carrier = reader.ReadMobile<PlayerMobile>();
break;
}
}
}
}

View File

@@ -0,0 +1,102 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Mobiles;
using VitaNex.FX;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class CTFPodium : Item
{
[CommandProperty(AutoPvP.Access)]
public virtual CTFTeam Team { get; set; }
public override bool HandlesOnMovement => true;
public CTFPodium(CTFTeam team)
: base(16144)
{
Team = team;
Name = Team.Name;
Hue = Team.Color;
Movable = false;
}
public CTFPodium(Serial serial)
: base(serial)
{ }
public override void OnDoubleClick(Mobile from)
{
if (this.CheckDoubleClick(from, true, false, 2))
{
CheckCapture(from as PlayerMobile);
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
CheckCapture(m as PlayerMobile);
}
public virtual void CheckCapture(PlayerMobile attacker)
{
if (Team == null || Team.Deleted || Team.Flag == null || Team.Flag.Deleted)
{
return;
}
if (attacker == null || attacker.Deleted || !attacker.InRange3D(this, 2, -10, 10) || !Team.IsMember(attacker))
{
return;
}
if (Team.Flag.Carrier != null && !Team.Flag.Carrier.Deleted)
{
return;
}
Team.Battle.ForEachTeam<CTFTeam>(
t =>
{
if (t == Team || t.Flag == null || t.Flag.Deleted || t.Flag.Carrier != attacker)
{
return;
}
t.Flag.Capture(attacker);
ExplodeFX.Random.CreateInstance(this, Map, 3, 0, null, e => e.Hue = t.Color).Send();
});
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,554 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Server;
using Server.Mobiles;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class CTFTeam : PvPTeam
{
private static readonly TimeSpan _OneSecond = TimeSpan.FromSeconds(1.0);
private CTFPodium _FlagPodium;
private bool _SolidHueOverride = true;
public Dictionary<PlayerMobile, int> Attackers { get; private set; }
public Dictionary<PlayerMobile, int> Defenders { get; private set; }
[CommandProperty(AutoPvP.Access)]
public CTFBattle CTFBattle => Battle as CTFBattle;
[CommandProperty(AutoPvP.Access, true)]
public CTFFlag Flag { get; private set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool SolidHueOverride
{
get => _SolidHueOverride;
set
{
_SolidHueOverride = value;
InvalidateSolidHueOverride();
}
}
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan FlagRespawnDelay { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual CTFPodium FlagPodium
{
get => _FlagPodium;
set
{
_FlagPodium = value;
InvalidateFlagPodium();
}
}
[CommandProperty(AutoPvP.Access)]
public override Point3D HomeBase
{
get => base.HomeBase;
set
{
base.HomeBase = value;
InvalidateFlagPodium();
}
}
[CommandProperty(AutoPvP.Access)]
public override Point3D SpawnPoint
{
get => base.SpawnPoint;
set
{
base.SpawnPoint = value;
InvalidateFlagPodium();
}
}
protected override void EnsureConstructDefaults()
{
base.EnsureConstructDefaults();
Attackers = new Dictionary<PlayerMobile, int>();
Defenders = new Dictionary<PlayerMobile, int>();
}
public CTFTeam(PvPBattle battle, string name = "Team", int minCapacity = 0, int maxCapacity = 1, int color = 12)
: base(battle, name, minCapacity, maxCapacity, color)
{
FlagRespawnDelay = TimeSpan.FromSeconds(10.0);
RespawnOnDeath = true;
KickOnDeath = false;
}
public CTFTeam(PvPBattle battle, GenericReader reader)
: base(battle, reader)
{ }
protected override void OnMicroSync()
{
base.OnMicroSync();
if (Flag == null || Flag.Deleted)
{
Flag = null;
return;
}
if (Battle == null || Battle.Deleted || Battle.Hidden || Battle.IsInternal)
{
Flag.Delete();
Flag = null;
return;
}
Flag.InvalidateCarrier();
if (Flag.IsAtPodium())
{
return;
}
Flag.UpdateDamageIncrease();
Flag.CheckReset();
}
public override void Reset()
{
base.Reset();
if (Flag != null)
{
Flag.Delete();
Flag = null;
}
if (Attackers != null)
{
Attackers.Clear();
}
else
{
Attackers = new Dictionary<PlayerMobile, int>();
}
if (Defenders != null)
{
Defenders.Clear();
}
else
{
Defenders = new Dictionary<PlayerMobile, int>();
}
}
public virtual void InvalidateFlagPodium()
{
if (Deserializing || SpawnPoint == Point3D.Zero || Battle.Options.Locations.Map == null ||
Battle.Options.Locations.Map == Map.Internal)
{
return;
}
if (FlagPodium == null || FlagPodium.Deleted)
{
FlagPodium = new CTFPodium(this);
}
else
{
FlagPodium.Hue = Color;
FlagPodium.Name = Name;
}
FlagPodium.MoveToWorld(SpawnPoint, Battle.Options.Locations.Map);
}
public virtual void InvalidateSolidHueOverride()
{
if (!Deserializing)
{
ForEachMember(InvalidateSolidHueOverride);
}
}
public virtual void InvalidateSolidHueOverride(PlayerMobile pm)
{
if (!Deserializing && pm != null && !pm.Deleted && IsMember(pm) && pm.InRegion(Battle.BattleRegion))
{
if ((Battle.IsPreparing || Battle.IsRunning) && _SolidHueOverride)
{
pm.SolidHueOverride = Color;
}
else
{
pm.SolidHueOverride = -1;
}
}
}
public override void OnMemberAdded(PlayerMobile pm)
{
base.OnMemberAdded(pm);
InvalidateSolidHueOverride(pm);
}
public override void OnMemberRemoved(PlayerMobile pm)
{
base.OnMemberRemoved(pm);
if (Battle != null && !Battle.Deleted)
{
Battle.ForEachTeam<CTFTeam>(
t =>
{
if (t.Flag != null && !t.Flag.Deleted && t.Flag.Carrier == pm)
{
t.Flag.Carrier = null;
}
});
}
InvalidateSolidHueOverride(pm);
}
public override void OnBattleOpened()
{
base.OnBattleOpened();
InvalidateFlagPodium();
InvalidateSolidHueOverride();
}
public override void OnBattlePreparing()
{
base.OnBattlePreparing();
InvalidateFlagPodium();
InvalidateSolidHueOverride();
}
public override void OnBattleStarted()
{
base.OnBattleStarted();
InvalidateFlagPodium();
InvalidateSolidHueOverride();
if (Flag == null || Flag.Deleted)
{
RespawnFlag();
}
else
{
Flag.Reset();
}
}
public override void OnBattleEnded()
{
base.OnBattleEnded();
InvalidateFlagPodium();
InvalidateSolidHueOverride();
}
public override void OnMemberDeath(PlayerMobile pm)
{
if (Battle != null && !Battle.Deleted)
{
Battle.ForEachTeam<CTFTeam>(
t =>
{
if (t.Flag != null && !t.Flag.Deleted && t.Flag.Carrier == pm)
{
t.Flag.Carrier = null;
}
});
}
InvalidateSolidHueOverride(pm);
base.OnMemberDeath(pm);
}
public virtual void SpawnFlag()
{
if (!Battle.IsRunning)
{
if (Flag != null && !Flag.Deleted)
{
Flag.Delete();
}
Flag = null;
return;
}
if (Flag == null || Flag.Deleted)
{
Flag = new CTFFlag(this);
}
Flag.Carrier = null;
Flag.Reset();
}
public virtual void RespawnFlag()
{
Timer.DelayCall(FlagRespawnDelay, SpawnFlag);
}
public virtual void OnFlagDropped(PlayerMobile attacker, CTFTeam enemyTeam)
{
if (attacker == null || enemyTeam == null || Flag == null || Flag.Deleted || CTFBattle == null || CTFBattle.Deleted)
{
return;
}
Broadcast("[{0}]: {1} has dropped your flag!", enemyTeam.Name, attacker.RawName);
CTFBattle.OnFlagDropped(Flag, attacker, enemyTeam);
}
public virtual void OnFlagCaptured(PlayerMobile attacker, CTFTeam enemyTeam)
{
if (attacker == null || enemyTeam == null || Flag == null || Flag.Deleted || CTFBattle == null || CTFBattle.Deleted)
{
return;
}
if (enemyTeam.Attackers.ContainsKey(attacker))
{
enemyTeam.Attackers[attacker]++;
}
else
{
enemyTeam.Attackers.Add(attacker, 1);
}
Broadcast("[{0}]: {1} has captured your flag!", enemyTeam.Name, attacker.RawName);
CTFBattle.OnFlagCaptured(Flag, attacker, enemyTeam);
RespawnFlag();
}
public virtual void OnFlagStolen(PlayerMobile attacker, CTFTeam enemyTeam)
{
if (attacker == null || enemyTeam == null || Flag == null || Flag.Deleted || CTFBattle == null || CTFBattle.Deleted)
{
return;
}
Broadcast("[{0}]: {1} has stolen your flag!", enemyTeam.Name, attacker.RawName);
CTFBattle.OnFlagStolen(Flag, attacker, enemyTeam);
}
public virtual void OnFlagReturned(PlayerMobile defender)
{
if (defender == null || Flag == null || Flag.Deleted || CTFBattle == null || CTFBattle.Deleted)
{
return;
}
if (Defenders.ContainsKey(defender))
{
Defenders[defender]++;
}
else
{
Defenders.Add(defender, 1);
}
Broadcast("[{0}]: {1} has returned your flag!", Name, defender.RawName);
CTFBattle.OnFlagReturned(Flag, defender);
}
public long GetTotalFlagsCaptured()
{
return Statistics.Values.Aggregate(0L, (v, o) => v + o["Flags Captured"]);
}
public long GetTotalFlagsDropped()
{
return Statistics.Values.Aggregate(0L, (v, o) => v + o["Flags Dropped"]);
}
public long GetTotalFlagsStolen()
{
return Statistics.Values.Aggregate(0L, (v, o) => v + o["Flags Stolen"]);
}
public long GetTotalFlagsReturned()
{
return Statistics.Values.Aggregate(0L, (v, o) => v + o["Flags Returned"]);
}
protected override void OnDeleted()
{
if (Flag != null)
{
Flag.Delete();
Flag = null;
}
if (FlagPodium != null)
{
FlagPodium.Delete();
FlagPodium = null;
}
base.OnDeleted();
}
public override void GetHtmlStatistics(Mobile viewer, StringBuilder html)
{
base.GetHtmlStatistics(viewer, html);
html.AppendLine("----------");
html.AppendLine("Flags Captured: {0:#,0}", GetTotalFlagsCaptured());
html.AppendLine("Flags Dropped: {0:#,0}", GetTotalFlagsDropped());
html.AppendLine("Flags Stolen: {0:#,0}", GetTotalFlagsStolen());
html.AppendLine("Flags Returned: {0:#,0}", GetTotalFlagsReturned());
html.AppendLine();
html.Append(String.Empty.WrapUOHtmlColor(System.Drawing.Color.LawnGreen, false));
html.AppendLine("Defenders:");
html.AppendLine();
string t;
var i = 0;
foreach (var o in Defenders.OrderBy(kv => kv.Value))
{
t = String.Format("{0:#,0}: {1} ({2:#,0} Returns)", ++i, o.Key.RawName, o.Value);
t = t.WrapUOHtmlColor(viewer.GetNotorietyColor(o.Key), SuperGump.DefaultHtmlColor);
html.AppendLine(t);
}
html.AppendLine();
html.Append(String.Empty.WrapUOHtmlColor(System.Drawing.Color.OrangeRed, false));
html.AppendLine("Attackers:");
html.AppendLine();
i = 0;
foreach (var o in Attackers.OrderBy(kv => kv.Value))
{
t = String.Format("{0:#,0}: {1} ({2:#,0} Captures)", ++i, o.Key.RawName, o.Value);
t = t.WrapUOHtmlColor(viewer.GetNotorietyColor(o.Key), SuperGump.DefaultHtmlColor);
html.AppendLine(t);
}
html.Append(String.Empty.WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Flag);
writer.Write(FlagPodium);
writer.Write(-1); // Caps
writer.Write(FlagRespawnDelay);
writer.Write(SolidHueOverride);
writer.WriteDictionary(
Attackers,
(w, m, c) =>
{
w.Write(m);
w.Write(c);
});
writer.WriteDictionary(
Defenders,
(w, m, c) =>
{
w.Write(m);
w.Write(c);
});
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Flag = reader.ReadItem<CTFFlag>();
if (Flag != null)
{
Flag.Team = this;
}
FlagPodium = reader.ReadItem<CTFPodium>();
if (FlagPodium != null)
{
FlagPodium.Team = this;
}
reader.ReadInt(); // Caps
FlagRespawnDelay = reader.ReadTimeSpan();
SolidHueOverride = reader.ReadBool();
reader.ReadDictionary(
r => new KeyValuePair<PlayerMobile, int>(r.ReadMobile<PlayerMobile>(), r.ReadInt()),
Attackers);
reader.ReadDictionary(
r => new KeyValuePair<PlayerMobile, int>(r.ReadMobile<PlayerMobile>(), r.ReadInt()),
Defenders);
}
break;
}
}
}
}

View File

@@ -0,0 +1,77 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class FFABattle : PvPBattle
{
public FFABattle()
{
Name = "Free For All";
Category = "Free For All";
Description = "The last participant alive wins!";
AddTeam(NameList.RandomName("daemon"), 5, 40, 85);
Schedule.Info.Months = ScheduleMonths.All;
Schedule.Info.Days = ScheduleDays.All;
Schedule.Info.Times = ScheduleTimes.EveryHour;
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(5.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(15.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(5.0);
Options.Rules.AllowBeneficial = true;
Options.Rules.AllowHarmful = true;
Options.Rules.AllowHousing = false;
Options.Rules.AllowPets = false;
Options.Rules.AllowSpawn = false;
Options.Rules.AllowSpeech = true;
Options.Rules.CanBeDamaged = true;
Options.Rules.CanDamageEnemyTeam = true;
Options.Rules.CanDamageOwnTeam = true;
Options.Rules.CanDie = false;
Options.Rules.CanHeal = true;
Options.Rules.CanHealEnemyTeam = false;
Options.Rules.CanHealOwnTeam = false;
Options.Rules.CanMount = false;
Options.Rules.CanFly = false;
Options.Rules.CanResurrect = false;
Options.Rules.CanUseStuckMenu = false;
}
public FFABattle(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,50 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public sealed class PvPCustomBattle : PvPBattle
{
public PvPCustomBattle()
{
Name = "Generic Battle";
Description =
"This generic battle serves as a template to create standard battles with general rules, using no advanced features.";
AddTeam("Team Alpha", 5, 10, 11);
AddTeam("Team Bravo", 5, 10, 22);
AddTeam("Team Gamma", 5, 10, 33);
AddTeam("Team Omega", 5, 10, 44);
}
public PvPCustomBattle(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,82 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public sealed class TournamentArchive : PropertyObject, IEnumerable<TournamentMatch>
{
[CommandProperty(AutoPvP.Access)]
public List<TournamentMatch> Matches { get; private set; }
[CommandProperty(AutoPvP.Access)]
public int Count => Matches.Count;
[CommandProperty(AutoPvP.Access)]
public string Name { get; private set; }
[CommandProperty(AutoPvP.Access)]
public DateTime Date { get; private set; }
public TournamentArchive(string name, DateTime date)
{
Name = name;
Date = date;
Matches = new List<TournamentMatch>();
}
public TournamentArchive(GenericReader reader)
: base(reader)
{ }
public IEnumerator<TournamentMatch> GetEnumerator()
{
return Matches.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Name);
writer.Write(Date);
writer.WriteList(Matches, (w, o) => o.Serialize(w));
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Name = reader.ReadString();
Date = reader.ReadDateTime();
Matches = reader.ReadList(r => new TournamentMatch(r), Matches);
}
}
}

View File

@@ -0,0 +1,564 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TournamentArchivesUI : ListGump<TournamentArchive>
{
public TournamentArchivesUI(Mobile user, Gump parent = null)
: base(user, parent)
{ }
protected override void CompileList(List<TournamentArchive> list)
{
list.Clear();
list.AddRange(TournamentArchives.Registry);
base.CompileList(list);
}
public override string GetSearchKeyFor(TournamentArchive key)
{
if (key != null)
{
return key.Name + " @ " + key.Date;
}
return base.GetSearchKeyFor(null);
}
protected override string GetLabelText(int index, int pageIndex, TournamentArchive entry)
{
if (entry != null)
{
return entry.Name + " @ " + entry.Date.ToShortDateString();
}
return base.GetLabelText(index, pageIndex, null);
}
protected override void SelectEntry(GumpButton button, TournamentArchive entry)
{
base.SelectEntry(button, entry);
new TournamentArchiveUI(User, entry, this).Send();
}
}
public class TournamentArchiveUI : SuperGumpList<TournamentMatch>
{
public IEnumerable<TournamentMatch> Archive { get; private set; }
public string Title { get; set; }
public int EntryWidth { get; set; }
public int EntryHeight { get; set; }
public int Width { get; private set; }
public int Height { get; private set; }
public PlayerMobile Leader { get; private set; }
public TournamentArchiveUI(Mobile user, TournamentBattle battle, Gump parent = null)
: this(user, (IEnumerable<TournamentMatch>)battle, parent)
{ }
public TournamentArchiveUI(Mobile user, TournamentArchive archive, Gump parent = null)
: this(user, (IEnumerable<TournamentMatch>)archive, parent)
{ }
private TournamentArchiveUI(Mobile user, IEnumerable<TournamentMatch> archive, Gump parent = null)
: base(user, parent)
{
Archive = archive;
Title = "Tournament Records";
if (Archive is TournamentArchive)
{
var a = (TournamentArchive)Archive;
Title = String.Format("{0} - {1}", a.Name, a.Date.ToSimpleString("t@h:m:s@ D d M y"));
}
else if (Archive is TournamentBattle)
{
var b = (TournamentBattle)Archive;
Title = b.Name;
if (b.State == PvPBattleState.Running)
{
AutoRefresh = true;
AutoRefreshRate = TimeSpan.FromSeconds(30.0);
}
}
CanClose = true;
CanDispose = true;
CanMove = true;
CanResize = true;
EntriesPerPage = 5;
EntryWidth = 400;
EntryHeight = 120;
Init();
}
protected override void Compile()
{
EntryWidth = Math.Max(400, EntryWidth);
EntryHeight = Math.Max(120, EntryHeight);
base.Compile();
}
protected virtual void Init()
{
if (Archive != null)
{
Leader = List.Where(m => m.Winner != null)
.GroupBy(m => m.Winner)
.OrderByDescending(o => o.Count())
.ThenByDescending(o => o.Aggregate(0.0, (c, m) => c + m.ComputeScore(o.Key)))
.Select(o => o.Key)
.FirstOrDefault();
}
var pad = SupportsUltimaStore ? 10 : 15;
var count = Math.Max(1, Math.Min(EntryCount, EntriesPerPage));
Width = 30 + (pad * 3) + EntryWidth;
Height = 90 + (pad * 3) + (count * EntryHeight);
}
protected override bool OnBeforeSend()
{
return base.OnBeforeSend() && Archive != null;
}
protected override void CompileList(List<TournamentMatch> list)
{
list.Clear();
if (Archive != null)
{
list.AddRange(Archive.Not(o => o.IsEmpty));
}
base.CompileList(list);
Init();
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
var sup = SupportsUltimaStore;
var pad = sup ? 10 : 15;
var bgID = sup ? 40000 : 9270;
var bgCol = sup ? Color.FromArgb(0xFF, 0x29, 0x31, 0x39) : Color.Black;
layout.Add(
"bg",
() =>
{
var x = 0;
var y = 0;
var w = Width;
var h = Height;
AddBackground(x, y, w, h, bgID);
x = pad;
y = (Height - pad) - 60;
w = Width - (pad * 2);
h = 60;
AddRectangle(x, y, w, h, bgCol, true);
});
layout.Add(
"title",
() =>
{
var title = Title;
title = title.WrapUOHtmlBig();
title = title.WrapUOHtmlCenter();
title = title.WrapUOHtmlColor(Color.Gold, false);
AddHtml(pad, pad, Width - (pad * 2), 40, title, false, false);
});
layout.Add("results", CompileResults);
layout.Add(
"scroll",
() =>
{
var x = Width - (pad + 30);
var y = pad + 30;
var h = Height - ((pad * 3) + 90);
AddScrollbarV(x, y, h, PageCount, Page, PreviousPage, NextPage);
});
layout.Add("cpanel", CompileControls);
}
private void CompileControls()
{
var sup = SupportsUltimaStore;
var pad = sup ? 10 : 15;
//var bgCol = sup ? Color.FromArgb(0xFF, 0x29, 0x31, 0x39) : Color.Black;
var x = pad;
var y = Height - (pad + 60);
var w = (Width - (pad * 2)) / 4;
//////////
var players = List.SelectMany(o => o.Players.Where(p => p != null)).Distinct().Count();
var text = String.Format("PLAYERS:\n{0:#,0}", players);
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(Color.PaleGoldenrod, false);
AddRectangle(x, y, w, 60, Color.White);
AddHtml(x + pad, y + pad, w - (pad * 2), 60, text, false, false);
x += w;
//////////
text = String.Format("MATCHES:\n{0:#,0}", EntryCount);
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(Color.PaleGoldenrod, false);
AddRectangle(x, y, w, 60, Color.White);
AddHtml(x + pad, y + pad, w - (pad * 2), 60, text, false, false);
x += w;
//////////
var ticks = List.Select(o => o.IsRunning ? o.Expire : o.TotalTime).Aggregate(0L, (v, o) => v + o.Ticks);
var duration = TimeSpan.FromTicks(ticks).ToSimpleString(@"!<d\d ><h\h >m\m");
text = String.Format("DURATION:\n{0}", duration);
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(Color.PaleGoldenrod, false);
AddRectangle(x, y, w, 60, Color.White);
AddHtml(x + pad, y + pad, w - (pad * 2), 60, text, false, false);
x += w;
//////////
if (Archive is TournamentArchive || (Archive is TournamentBattle && !((TournamentBattle)Archive).IsRunning))
{
text = String.Format("WINNER:\n{0}", Leader != null ? Leader.RawName : "N/A");
}
else
{
text = String.Format("LEADER:\n{0}", Leader != null ? Leader.RawName : "N/A");
}
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(Color.PaleGoldenrod, false);
AddRectangle(x, y, w, 60, Color.White);
AddHtml(x + pad, y + pad, w - (pad * 2), 60, text, false, false);
}
private void CompileResults()
{
var sup = SupportsUltimaStore;
var pad = sup ? 10 : 15;
var x = pad;
var y = pad + 30;
var range = GetListRange();
foreach (var o in range.Values)
{
CompileMatchLayout(x, y, EntryWidth, EntryHeight, o);
y += EntryHeight;
}
range.Clear();
}
private void CompileMatchLayout(int x, int y, int w, int h, TournamentMatch match)
{
var sup = SupportsUltimaStore;
var pad = sup ? 10 : 15;
var bgID = sup ? 40000 : 9270;
//var bgCol = sup ? Color.FromArgb(0xFF, 0x29, 0x31, 0x39) : Color.Black;
AddTileButton(x, y, w, h, b => Select(match));
AddBackground(x, y, w, h, bgID);
var capacity = match.Capacity;
if (capacity <= 0)
{
return;
}
var xx = x + pad;
var yy = y + pad;
var ww = (w - (pad * 2)) / capacity;
//var hh = h - (pad * 2);
string t;
Color c;
Size s;
Point o;
int ox, oy, tx, ty;
for (var i = 0; i < capacity; i++)
{
var p = match.Players[i];
if (p != null)
{
t = p.RawName;
}
else
{
t = "???";
}
t = t.WrapUOHtmlBig();
t = t.WrapUOHtmlCenter();
if (p != null)
{
t = t.WrapUOHtmlColor(User.GetNotorietyColor(p), false);
}
else
{
t = t.WrapUOHtmlColor(Color.White, false);
}
AddHtml(xx, yy, ww, 40, t, false, false);
if (p != null)
{
s = GetImageSize(7034);
o = new Point(ComputeCenter(xx, ww - s.Width), yy + 30);
AddImage(o.X, o.Y, 7034);
c = match.Winner == null ? Color.Silver : match.Winner == p ? Color.LawnGreen : Color.IndianRed;
AddRectangle(o.X, o.Y, s.Width, s.Height, c, 2);
}
else
{
s = GetImageSize(7034);
o = new Point(ComputeCenter(xx, ww - s.Width), yy + 30);
AddImage(o.X, o.Y, 7034);
c = Color.White;
AddRectangle(o.X, o.Y, s.Width, s.Height, c, 2);
}
if (i + 1 < capacity)
{
ox = o.X + s.Width;
tx = xx + (ww - 30);
}
else
{
ox = xx + 30;
tx = o.X;
}
oy = ComputeCenter(o.Y, s.Height - 4);
ty = oy + 4;
AddRectangle(ox, oy, tx - ox, ty - oy, c, true);
if (i + 1 < capacity)
{
AddImageShadow(xx + (ww - 30), yy + 30, 5578, 0, 90);
}
xx += ww;
}
}
public void GetHtml(StringBuilder html, TournamentMatch match, bool extended)
{
var text = String.Format("Match #{0}", match.Index + 1);
text = text.WrapUOHtmlBig();
text = text.WrapUOHtmlColor(Color.Gold, false);
html.AppendLine(text);
var sep = " vs ".WrapUOHtmlColor(Color.IndianRed, Color.White);
text = String.Join(sep, match.Players.Select(o => o != null ? o.RawName : "???"));
text = text.WrapUOHtmlColor(Color.White, false);
html.AppendLine(text);
if (extended)
{
html.AppendLine();
}
if (match.Winner != null)
{
text = String.Format("Winner: {0}", match.Winner.RawName);
text = text.WrapUOHtmlColor(Color.PaleGoldenrod, false);
}
else if (match.IsComplete)
{
text = "Draw";
text = text.WrapUOHtmlColor(Color.LightGray, false);
}
else
{
var exp = match.Expire;
if (exp > TimeSpan.Zero)
{
text = String.Format("Expire: {0}", exp.ToSimpleString("h:m:s"));
text = text.WrapUOHtmlColor(Color.SkyBlue, false);
}
else
{
text = "Expired";
text = text.WrapUOHtmlColor(Color.IndianRed, false);
}
}
html.AppendLine(text);
if (!extended)
{
return;
}
html.AppendLine();
if (match.DateStart > DateTime.MinValue)
{
text = String.Format("Start: {0}", match.DateStart.ToSimpleString("t@h:m:s@ D d M y"));
text = text.WrapUOHtmlColor(Color.SkyBlue, false);
html.AppendLine(text);
}
if (match.DateEnd < DateTime.MaxValue)
{
text = String.Format("Finish: {0}", match.DateEnd.ToSimpleString("t@h:m:s@ D d M y"));
text = text.WrapUOHtmlColor(Color.SkyBlue, false);
html.AppendLine(text);
}
html.AppendLine();
text = "Records";
text = text.WrapUOHtmlBig();
text = text.WrapUOHtmlColor(Color.Gold, false);
html.AppendLine(text);
html.AppendLine(String.Empty.WrapUOHtmlColor(Color.White, false));
foreach (var o in match.Records)
{
html.AppendLine("[{0}]: {1}", o.Time.ToSimpleString("t@h:m:s@"), o.Value);
}
}
private void Select(TournamentMatch match)
{
var html = new StringBuilder();
GetHtml(html, match, true);
new NoticeDialogGump(User, Refresh(true))
{
Width = 600,
Height = 400,
Title = String.Format("Match #{0:#,0}", match.Index + 1),
Html = html.ToString()
}.Send();
}
public override int SortCompare(TournamentMatch a, TournamentMatch b)
{
var res = 0;
if (a.CompareNull(b, ref res))
{
return res;
}
if (a.Index < b.Index)
{
return -1;
}
if (a.Index > b.Index)
{
return 1;
}
return base.SortCompare(a, b);
}
protected override void OnAutoRefresh()
{
base.OnAutoRefresh();
AutoRefresh = Archive is TournamentBattle && ((TournamentBattle)Archive).IsRunning;
}
}
}

View File

@@ -0,0 +1,88 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Server;
using VitaNex.IO;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public static class TournamentArchives
{
static TournamentArchives()
{
Registry = new List<TournamentArchive>();
}
public static void Initialize()
{
CommandUtility.Register("TournamentArchives", AutoPvP.Access, e => new TournamentArchivesUI(e.Mobile).Send());
CommandUtility.RegisterAlias("TournamentArchives", "TArchives");
}
public static FileInfo File => IOUtility.EnsureFile(VitaNexCore.SavesDirectory + "/AutoPvP/Tournament/Archives.bin");
public static List<TournamentArchive> Registry { get; private set; }
public static int Count => Registry.Count;
public static void Configure()
{
VitaNexCore.OnModuleLoaded += OnModuleLoaded;
VitaNexCore.OnModuleSaved += OnModuleSaved;
}
private static void OnModuleLoaded(CoreModuleInfo cmi)
{
if (cmi.Enabled && cmi.TypeOf == typeof(AutoPvP))
{
File.Deserialize(r => r.ReadBlockList(r1 => new TournamentArchive(r1), Registry));
}
}
private static void OnModuleSaved(CoreModuleInfo cmi)
{
if (cmi.Enabled && cmi.TypeOf == typeof(AutoPvP))
{
File.Serialize(w => w.WriteBlockList(Registry, (w1, o) => o.Serialize(w1)));
}
}
public static TournamentArchive CreateArchive(TournamentBattle b)
{
TournamentArchive a = null;
foreach (var r in b.Matches.Where(o => !o.IsDisposed && o.IsComplete && o.Records.Count > 0))
{
if (a == null)
{
a = new TournamentArchive(b.Name, DateTime.UtcNow);
}
a.Matches.Add(r);
}
if (a != null)
{
Registry.Add(a);
}
return a;
}
}
}

View File

@@ -0,0 +1,58 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TournamentRecord : PropertyObject
{
[CommandProperty(AutoPvP.Access, true)]
public DateTime Time { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public string Value { get; private set; }
public TournamentRecord(string value)
{
Time = DateTime.UtcNow;
Value = value ?? String.Empty;
}
public TournamentRecord(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Time);
writer.Write(Value);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Time = reader.ReadDateTime();
Value = reader.ReadString();
}
}
}

View File

@@ -0,0 +1,83 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public sealed class TournamentRecords : PropertyObject, IEnumerable<TournamentRecord>
{
[CommandProperty(AutoPvP.Access)]
public List<TournamentRecord> Entries { get; private set; }
[CommandProperty(AutoPvP.Access)]
public int Count => Entries.Count;
[CommandProperty(AutoPvP.Access)]
public DateTime DateBegin => Count > 0 ? Entries.Lowest(o => o.Time.Ticks).Time : DateTime.MinValue;
[CommandProperty(AutoPvP.Access)]
public DateTime DateEnd => Count > 0 ? Entries.Highest(o => o.Time.Ticks).Time : DateTime.MaxValue;
public TournamentRecords()
{
Entries = new List<TournamentRecord>();
}
public TournamentRecords(GenericReader reader)
: base(reader)
{ }
public void Record(string format, params object[] args)
{
Record(String.Format(format, args));
}
public void Record(string value)
{
Entries.Add(new TournamentRecord(value));
}
public IEnumerator<TournamentRecord> GetEnumerator()
{
return Entries.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.WriteList(Entries, (w, o) => o.Serialize(w));
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Entries = reader.ReadList(r => new TournamentRecord(r), Entries);
}
}
}

View File

@@ -0,0 +1,544 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public sealed class TournamentMatch : PropertyObject, IDisposable
{
private long _MessageBuffer;
public bool IsDisposed { get; private set; }
[CommandProperty(AutoPvP.Access)]
public TournamentRecords Records { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public int Index { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public int Team { get; private set; }
[CommandProperty(AutoPvP.Access)]
public PlayerMobile[] Players { get; private set; }
[CommandProperty(AutoPvP.Access)]
public bool[] Dead { get; private set; }
[CommandProperty(AutoPvP.Access)]
public int[][] Statistics { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public PlayerMobile Winner { get; set; }
[CommandProperty(AutoPvP.Access, true)]
public DateTime DateStart { get; set; }
[CommandProperty(AutoPvP.Access, true)]
public DateTime DateEnd { get; set; }
[CommandProperty(AutoPvP.Access, true)]
public TimeSpan Delay { get; set; }
[CommandProperty(AutoPvP.Access, true)]
public TimeSpan Duration { get; set; }
[CommandProperty(AutoPvP.Access)]
public TimeSpan TotalTime => Delay + Duration;
[CommandProperty(AutoPvP.Access)]
public TimeSpan Expire
{
get
{
if (DateStart > DateTime.MinValue)
{
var now = DateTime.UtcNow;
var exp = DateStart + TotalTime;
if (exp > now)
{
return exp - now;
}
}
return TimeSpan.Zero;
}
}
[CommandProperty(AutoPvP.Access)]
public bool IsRunning => Expire > TimeSpan.Zero;
[CommandProperty(AutoPvP.Access)]
public bool IsDelayed => DateStart + Delay > DateTime.UtcNow;
[CommandProperty(AutoPvP.Access)]
public bool IsComplete => DateEnd < DateTime.MaxValue;
[CommandProperty(AutoPvP.Access)]
public int Capacity => Players.Length;
[CommandProperty(AutoPvP.Access)]
public int Count => Players.Count(o => o != null);
[CommandProperty(AutoPvP.Access)]
public int CountAlive => Players.Count(o => o != null && IsAlive(o));
[CommandProperty(AutoPvP.Access)]
public int CountDead => Players.Count(o => o != null && IsDead(o));
[CommandProperty(AutoPvP.Access)]
public bool IsEmpty => Count == 0;
[CommandProperty(AutoPvP.Access)]
public bool IsFull => Count == Capacity;
public TournamentMatch(int index, int team, TimeSpan delay, TimeSpan duration)
{
Index = index;
Team = team;
Delay = delay;
Duration = duration;
Records = new TournamentRecords();
Players = new PlayerMobile[2];
Dead = new bool[Players.Length];
Statistics = new int[Players.Length][];
Statistics.SetAll(i => new int[2]); // Damage, Healing
DateStart = DateTime.MinValue;
DateEnd = DateTime.MaxValue;
}
public TournamentMatch(int index, TournamentBattle battle, TournamentTeam team)
: this(index, team.Serial.ValueHash, battle.MatchDelay, battle.MatchDuration)
{ }
public TournamentMatch(GenericReader reader)
: base(reader)
{ }
public void RecordDamage(PlayerMobile pm, int amount)
{
var i = Players.IndexOf(pm);
if (i >= 0)
{
Statistics[i][0] += amount;
Record("{0} deals {1:#,0} damage.", pm.RawName, amount);
}
}
public void RecordHeal(PlayerMobile pm, int amount)
{
var i = Players.IndexOf(pm);
if (i >= 0)
{
Statistics[i][1] += amount;
Record("{0} heals {1:#,0} health.", pm.RawName, amount);
}
}
public int GetDamageDone(PlayerMobile pm)
{
var i = Players.IndexOf(pm);
if (i >= 0)
{
return Statistics[i][0];
}
return -1;
}
public int GetHealingDone(PlayerMobile pm)
{
var i = Players.IndexOf(pm);
if (i >= 0)
{
return Statistics[i][1];
}
return -1;
}
public double ComputeScore(PlayerMobile pm)
{
return GetDamageDone(pm) - GetHealingDone(pm);
}
public void Record(string format, params object[] args)
{
Records.Record(format, args);
}
public void Record(string value)
{
Records.Record(value);
}
public void ForEachPlayer(Action<PlayerMobile> action)
{
if (action == null)
{
return;
}
foreach (var pm in Players.Where(o => o != null))
{
action(pm);
}
}
public void Broadcast(int hue, string format, params object[] args)
{
Record(format, args);
ForEachPlayer(pm => pm.SendMessage(hue, format, args));
}
public void Broadcast(int hue, string message)
{
Record(message);
ForEachPlayer(pm => pm.SendMessage(hue, message));
}
public void Broadcast(string format, params object[] args)
{
Record(format, args);
ForEachPlayer(pm => pm.SendMessage(format, args));
}
public void Broadcast(string message)
{
Record(message);
ForEachPlayer(pm => pm.SendMessage(message));
}
public void HandleDeath(PlayerMobile pm)
{
var i = Players.IndexOf(pm);
if (Dead.InBounds(i))
{
Dead[i] = true;
}
}
public bool IsDead(PlayerMobile pm)
{
var i = Players.IndexOf(pm);
if (Dead.InBounds(i))
{
return Dead[i];
}
return false;
}
public bool IsAlive(PlayerMobile pm)
{
var i = Players.IndexOf(pm);
if (Dead.InBounds(i))
{
return !Dead[i];
}
return false;
}
public bool Contains(PlayerMobile pm)
{
return Players.Contains(pm);
}
public void Sync(TournamentBattle b, TournamentTeam t)
{
if (IsDisposed || IsComplete)
{
return;
}
if (b == null || b.Deleted || b.IsInternal || b.IsQueueing || b.IsPreparing)
{
return;
}
if (t == null || t.Deleted || t.Serial.ValueHash != Team)
{
return;
}
if (b.IsRunning && DateStart == DateTime.MinValue) // Populate & Start
{
for (var i = 0; i < Capacity; i++)
{
var pm = Players[i];
if (pm != null && !b.IsAliveParticipant(pm))
{
Players[i] = null;
Dead[i] = false;
Statistics[i].SetAll(0);
Broadcast(0x22, "{0} has left the match! [{1} / {2}]", pm.RawName, Count, Capacity);
}
}
if (!IsFull)
{
var q = b.GetMatchQueue(Capacity - Count);
for (var i = 0; i < Capacity && q.Count > 0; i++)
{
var pm = Players[i];
if (pm == null)
{
Players[i] = pm = q.Dequeue();
Dead[i] = false;
Statistics[i].SetAll(0);
Broadcast(0x55, "{0} has joined the match! [{1} / {2}]", pm.RawName, Count, Capacity);
}
}
q.Free(true);
}
if (IsFull)
{
Broadcast("The match is now full, prepare to fight!");
Start(b, t);
}
}
else if (b.IsRunning && Expire > TimeSpan.Zero) // Tick
{
var started = !IsDelayed;
if (_MessageBuffer <= Core.TickCount)
{
var time = started ? Expire : ((DateStart + Delay) - DateTime.UtcNow);
if (time.Hours > 0 && time.Hours <= 3)
{
_MessageBuffer = Core.TickCount + (Math.Min(15, time.Minutes) * 60000);
}
else if (time.Minutes > 0 && time.Minutes <= 5)
{
_MessageBuffer = Core.TickCount + (Math.Min(15, time.Seconds) * 1000);
}
else if (time.Seconds > 0 && time.Seconds <= 10)
{
_MessageBuffer = Core.TickCount + Math.Min(1000, time.Milliseconds);
}
else
{
_MessageBuffer = Int64.MaxValue;
}
var seconds = (int)Math.Ceiling(time.TotalSeconds);
if (seconds > 5)
{
Broadcast(
"The match will {0} in {1} second{2}!",
!started ? "begin" : "end",
seconds,
seconds != 1 ? "s" : String.Empty);
}
else if (seconds > 0)
{
Broadcast("{0}...", seconds);
}
else
{
Broadcast(!started ? "FIGHT!" : "CEASE!");
}
}
PlayerMobile o = null;
var count = 0;
foreach (var pm in Players.Where(p => IsAlive(p) && b.IsAliveParticipant(p)).OrderBy(ComputeScore))
{
o = pm;
++count;
}
if (count <= 1)
{
if (!started)
{
Broadcast("Not enough players to start the match.");
}
Winner = o;
if (Winner != null)
{
if (!started)
{
Broadcast("{0} has won the match by default!", Winner.RawName);
}
else
{
Broadcast("{0} has won the match!", Winner.RawName);
}
}
else
{
Broadcast("No winner has been declared.");
}
End(b, t);
}
}
else if ((b.IsRunning || b.IsEnded) && DateEnd == DateTime.MaxValue) // End
{
var started = !IsDelayed;
if (started)
{
Broadcast("TIME UP!");
}
Winner = Players.Where(p => IsAlive(p) && b.IsAliveParticipant(p)).Highest(ComputeScore);
if (Winner != null)
{
if (!started)
{
Broadcast("{0} has won the match by default!", Winner.RawName);
}
else
{
Broadcast("{0} has won the match!", Winner.RawName);
}
}
else
{
Broadcast("No winner has been declared.");
}
End(b, t);
}
}
private void Start(TournamentBattle b, TournamentTeam t)
{
DateStart = DateTime.UtcNow;
foreach (var pm in Players.Where(p => IsAlive(p) && b.IsParticipant(p)))
{
b.RefreshStats(pm, true, true);
b.TeleportToSpawnPoint(t, pm);
}
}
private void End(TournamentBattle b, TournamentTeam t)
{
DateEnd = DateTime.UtcNow;
foreach (var pm in Players.Where(p => IsAlive(p) && b.IsParticipant(p)))
{
b.RefreshStats(pm, true, true);
b.TeleportToHomeBase(t, pm);
}
}
public void Dispose()
{
if (IsDisposed)
{
return;
}
Players.Clear();
Records = null;
Players = null;
Dead = null;
Statistics = null;
Winner = null;
IsDisposed = true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Index);
writer.Write(Team);
writer.WriteArray(Players, (w, o) => w.Write(o));
writer.WriteArray(Dead, (w, o) => w.Write(o));
writer.WriteArray(Statistics, (w, o) => w.WriteArray(o, (w1, o1) => w1.Write(o1)));
writer.Write(Delay);
writer.Write(Duration);
writer.Write(DateStart);
writer.Write(DateEnd);
writer.Write(Winner);
Records.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Index = reader.ReadInt();
Team = reader.ReadInt();
Players = reader.ReadArray(r => r.ReadMobile<PlayerMobile>(), Players);
Dead = reader.ReadArray(r => r.ReadBool(), Dead);
Statistics = reader.ReadArray(r => r.ReadArray(r1 => r1.ReadInt()), Statistics);
Delay = reader.ReadTimeSpan();
Duration = reader.ReadTimeSpan();
DateStart = reader.ReadDateTime();
DateEnd = reader.ReadDateTime();
Winner = reader.ReadMobile<PlayerMobile>();
Records = new TournamentRecords(reader);
}
}
}

View File

@@ -0,0 +1,71 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TournamentTeam : PvPTeam
{
public TournamentTeam(
PvPBattle battle,
string name = "Incognito",
int minCapacity = 10,
int maxCapacity = 50,
int color = 12)
: base(battle, name, minCapacity, maxCapacity, color)
{
RespawnOnStart = false;
RespawnOnDeath = false;
KickOnDeath = true;
}
public TournamentTeam(PvPBattle battle, GenericReader reader)
: base(battle, reader)
{ }
public override void AddMember(PlayerMobile pm, bool teleport)
{
if (IsMember(pm))
{
return;
}
Members[pm] = DateTime.UtcNow;
if (teleport)
{
Battle.TeleportToHomeBase(this, pm);
}
OnMemberAdded(pm);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,609 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Mobiles;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TournamentBattle : PvPBattle, IEnumerable<TournamentMatch>
{
[CommandProperty(AutoPvP.Access)]
public List<TournamentMatch> Matches { get; private set; }
[CommandProperty(AutoPvP.Access)]
public TimeSpan MatchDelay { get; set; }
[CommandProperty(AutoPvP.Access)]
public TimeSpan MatchDuration { get; set; }
[CommandProperty(AutoPvP.Access)]
public double MatchSuddenDeath { get; set; }
[CommandProperty(AutoPvP.Access)]
public int FinalBestOfCur { get; set; }
[CommandProperty(AutoPvP.Access)]
public int FinalBestOfMax { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool IsFinalMatch => State == PvPBattleState.Running && Matches.Count > 0 && CurrentCapacity <= 2;
public TournamentBattle()
{
Name = "Tournament";
Category = "Tournaments";
Description = "An elimination tournament!";
AddTeam("Contenders", 10, 50, 85);
Schedule.Info.Months = ScheduleMonths.All;
Schedule.Info.Days = ScheduleDays.Sunday;
Schedule.Info.Times = ScheduleTimes.Noon;
Options.Timing.QueuePeriod = TimeSpan.FromHours(1.0);
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(10.0);
Options.Timing.RunningPeriod = TimeSpan.FromHours(5.0);
Options.Timing.EndedPeriod = TimeSpan.FromHours(5.0);
Options.Rules.AllowBeneficial = true;
Options.Rules.AllowHarmful = true;
Options.Rules.AllowHousing = false;
Options.Rules.AllowPets = false;
Options.Rules.AllowSpawn = false;
Options.Rules.AllowSpeech = true;
Options.Rules.CanBeDamaged = true;
Options.Rules.CanDamageEnemyTeam = true;
Options.Rules.CanDamageOwnTeam = true;
Options.Rules.CanDie = false;
Options.Rules.CanHeal = true;
Options.Rules.CanHealEnemyTeam = true;
Options.Rules.CanHealOwnTeam = true;
Options.Rules.CanMount = false;
Options.Rules.CanFly = false;
Options.Rules.CanResurrect = false;
Options.Rules.CanUseStuckMenu = false;
Options.Rules.CanMoveThrough = true;
Options.Rules.CanEquip = true;
RequireCapacity = true;
UseTeamColors = false;
IdleKick = false;
IdleThreshold = TimeSpan.FromMinutes(30.0);
LogoutDelay = TimeSpan.FromMinutes(5.0);
MatchDelay = TimeSpan.FromSeconds(10.0);
MatchDuration = TimeSpan.FromMinutes(15.0);
MatchSuddenDeath = 0.25;
FinalBestOfCur = 0;
FinalBestOfMax = 3;
}
public TournamentBattle(GenericReader reader)
: base(reader)
{ }
protected override void EnsureConstructDefaults()
{
base.EnsureConstructDefaults();
Matches = new List<TournamentMatch>();
}
protected override void RegisterSubCommands()
{
base.RegisterSubCommands();
RegisterSubCommand(
"scores",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
UpdateUI(state.Mobile, false);
return true;
},
"Display the current match rankings.");
}
public override bool Validate(Mobile viewer, List<string> errors, bool pop = true)
{
if (!base.Validate(viewer, errors, pop) && pop)
{
return false;
}
if (!Teams.All(t => t is TournamentTeam))
{
errors.Add("One or more teams are not of the TournamentTeam type.");
errors.Add("[Options] -> [View Teams]");
if (pop)
{
return false;
}
}
return true;
}
protected override void GetAssignPriority(PvPTeam team, out double weight)
{
base.GetAssignPriority(team, out weight);
if (weight > Double.MinValue && weight < Double.MaxValue)
{
weight = team.Members.Count;
}
}
public override bool AddTeam(string name, int minCapacity, int capacity, int color)
{
return AddTeam(new TournamentTeam(this, name, minCapacity, capacity, color));
}
public override bool AddTeam(PvPTeam team)
{
if (team == null || team.Deleted)
{
return false;
}
if (team is TournamentTeam)
{
return base.AddTeam(team);
}
var added = AddTeam(team.Name, team.MinCapacity, team.MinCapacity, team.Color);
team.Delete();
return added;
}
public override void OnTeamMemberDeath(PvPTeam team, PlayerMobile pm)
{
base.OnTeamMemberDeath(team, pm);
if (team is TournamentTeam)
{
var o = FindActiveMatch(pm);
if (o != null)
{
o.HandleDeath(pm);
o.Sync(this, (TournamentTeam)team);
}
}
}
public override void OnAfterTeamMemberDeath(PvPTeam team, PlayerMobile pm)
{
base.OnAfterTeamMemberDeath(team, pm);
UpdateUI(true);
}
public override bool TryKickOnDeath(PvPTeam team, PlayerMobile pm, bool isLoss)
{
if (isLoss && IsFinalMatch && FinalBestOfCur < FinalBestOfMax)
{
var o = FindActiveMatch(pm);
int min = 0, max = 0;
if (o == null)
{
++FinalBestOfCur;
}
else if (o.CountAlive <= 1)
{
foreach (var c in o.Players.Where(p => p != null).Select(CountMatchesWon))
{
min = Math.Min(min, c);
max = Math.Max(max, c);
}
++FinalBestOfCur;
}
if (max - min < (FinalBestOfMax / 2) + 1)
{
return false;
}
}
return base.TryKickOnDeath(team, pm, isLoss);
}
public void UpdateUI(bool refreshOnly)
{
foreach (var pm in GetLocalBroadcastList())
{
UpdateUI(pm, refreshOnly);
}
}
public void UpdateUI(PlayerMobile pm, bool refreshOnly)
{
var g = pm.FindGump<TournamentArchiveUI>();
if (g == null)
{
if (refreshOnly)
{
return;
}
g = new TournamentArchiveUI(pm, this);
}
g.Refresh(true);
}
public override void OnHeal(Mobile healer, Mobile healed, int heal)
{
base.OnHeal(healer, healed, heal);
if (heal > 0 && healer == healed && healer is PlayerMobile)
{
var p = (PlayerMobile)healer;
var o = FindActiveMatch(p);
if (o != null)
{
if (MatchSuddenDeath > 0)
{
var t = o.Expire.TotalSeconds / o.Duration.TotalSeconds;
if (t < MatchSuddenDeath)
{
heal = (int)(heal * (t / MatchSuddenDeath));
}
}
o.RecordHeal(p, heal);
}
}
}
public override void OnDamage(Mobile attacker, Mobile damaged, int damage)
{
base.OnDamage(attacker, damaged, damage);
if (damage > 0 && attacker != damaged && attacker is PlayerMobile)
{
var p = (PlayerMobile)attacker;
var o = FindActiveMatch(p);
if (o != null)
{
o.RecordDamage(p, damage);
}
}
}
protected override void OnSpectatorAdded(PlayerMobile pm)
{
base.OnSpectatorAdded(pm);
UpdateUI(pm, false);
}
protected override void OnBattleStarted()
{
base.OnBattleStarted();
SyncMatches();
UpdateUI(true);
}
protected override void OnBattleEnded()
{
SyncMatches();
Matches.RemoveAll(o => o.IsEmpty);
if (Matches.Count > 0)
{
var a = TournamentArchives.CreateArchive(this);
if (a != null)
{
foreach (var pm in GetLocalBroadcastList())
{
new TournamentArchiveUI(pm, a).Send();
}
}
else
{
UpdateUI(false);
}
}
base.OnBattleEnded();
}
protected override void OnBattleCancelled()
{
SyncMatches();
Matches.RemoveAll(o => o.IsEmpty);
base.OnBattleCancelled();
}
protected override void OnReset()
{
Matches.Clear();
FinalBestOfCur = 0;
base.OnReset();
}
protected override void OnMicroSync()
{
base.OnMicroSync();
SyncMatches();
}
protected void SyncMatches()
{
if (!IsInternal)
{
ForEachTeam<TournamentTeam>(SyncMatch);
}
}
protected void SyncMatch(TournamentTeam team)
{
var m = Matches.Find(o => o.Team == team.Serial.ValueHash && !o.IsComplete);
if (m == null || m.IsDisposed)
{
if (!IsRunning || CurrentCapacity <= CountActiveParticipants())
{
return;
}
Matches.Add(m = new TournamentMatch(Matches.Count, this, team));
}
m.Sync(this, team);
}
public Queue<PlayerMobile> GetMatchQueue(int capacity)
{
var list = GetParticipants();
list = list.ToLookup(CountMatchesCompleted).Lowest(o => o.Key);
list = list.Not(InActiveMatch);
list = list.Randomize();
if (capacity > 0)
{
list = list.Take(capacity);
}
return list.ToQueue();
}
public IEnumerable<PlayerMobile> GetMatchParticipants()
{
return Matches.SelectMany(o => o.Players.Where(p => p != null)).Distinct();
}
public int CountActiveParticipants()
{
return Matches.Where(o => !o.IsComplete).Aggregate(0, (v, o) => v + o.CountAlive);
}
public int CountMatchesWon(PlayerMobile pm)
{
return Matches.Count(o => o.IsComplete && o.Winner == pm);
}
public int CountMatchesCompleted(PlayerMobile pm)
{
return Matches.Count(o => o.IsComplete && o.Contains(pm));
}
public bool InActiveMatch(PlayerMobile pm)
{
return Matches.Any(o => !o.IsComplete && o.Contains(pm));
}
public TournamentMatch FindActiveMatch(PlayerMobile pm)
{
return Matches.Find(o => !o.IsComplete && o.Contains(pm));
}
public override bool CheckSkillUse(Mobile user, int skill)
{
if (!base.CheckSkillUse(user, skill))
{
return false;
}
var o = FindActiveMatch(user as PlayerMobile);
return o != null && !o.IsDelayed;
}
public override bool CheckSpellCast(Mobile caster, ISpell spell)
{
if (!base.CheckSpellCast(caster, spell))
{
return false;
}
var o = FindActiveMatch(caster as PlayerMobile);
return o != null && !o.IsDelayed;
}
public override bool CheckAllowHarmful(Mobile m, Mobile target, out bool handled)
{
var val = base.CheckAllowHarmful(m, target, out handled);
if (!handled || !val || !m.InRegion(BattleRegion) || !target.InRegion(BattleRegion))
{
return val;
}
var pmS = m as PlayerMobile;
var pmT = target as PlayerMobile;
var o = FindActiveMatch(pmS);
return o != null && !o.IsDelayed && o == FindActiveMatch(pmT);
}
public override bool CheckAllowBeneficial(Mobile m, Mobile target, out bool handled)
{
var val = base.CheckAllowBeneficial(m, target, out handled);
if (!handled || !val || !m.InRegion(BattleRegion) || !target.InRegion(BattleRegion))
{
return val;
}
var pmS = m as PlayerMobile;
var pmT = target as PlayerMobile;
var o = FindActiveMatch(pmS);
return o != null && !o.IsDelayed && o == FindActiveMatch(pmT);
}
protected override int NotorietyHandler(PlayerMobile source, PlayerMobile target, out bool handled)
{
var noto = base.NotorietyHandler(source, target, out handled);
if (!handled || noto == BattleNotoriety.Bubble || noto == Notoriety.Invulnerable)
{
return noto;
}
if (!source.InRegion(BattleRegion) || !target.InRegion(BattleRegion))
{
return noto;
}
var o = FindActiveMatch(source);
if (o != null && !o.IsDelayed && o == FindActiveMatch(target))
{
return noto;
}
return Notoriety.Invulnerable;
}
public override TimeSpan GetStateTimeLeft(DateTime when, PvPBattleState state)
{
var time = base.GetStateTimeLeft(when, state);
if (state == PvPBattleState.Running)
{
var o = Matches.Where(r => r.IsRunning).Highest(r => r.Expire);
if (o != null)
{
if (o.Expire > time)
{
time = o.Expire;
}
}
else if (HasCapacity())
{
time = MatchDelay + MatchDuration;
}
}
return time;
}
public IEnumerator<TournamentMatch> GetEnumerator()
{
return Matches.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(1);
writer.Write(MatchSuddenDeath);
writer.Write(MatchDelay);
writer.Write(MatchDuration);
writer.Write(FinalBestOfCur);
writer.Write(FinalBestOfMax);
writer.WriteBlockList(Matches, (w, r) => r.Serialize(w));
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var v = reader.GetVersion();
if (v > 0)
{
MatchSuddenDeath = reader.ReadDouble();
}
else
{
MatchSuddenDeath = 0.25;
}
MatchDelay = reader.ReadTimeSpan();
MatchDuration = reader.ReadTimeSpan();
FinalBestOfCur = reader.ReadInt();
FinalBestOfMax = reader.ReadInt();
Matches = reader.ReadBlockList(r => new TournamentMatch(r), Matches);
}
}
}

View File

@@ -0,0 +1,87 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TvTBattle : PvPBattle
{
public TvTBattle()
{
Name = "Team vs Team";
Category = "Team vs Team";
Description = "The last team alive wins!";
Ranked = true;
RewardTeam = true;
AddTeam(NameList.RandomName("daemon"), 1, 1, 0x22);
AddTeam(NameList.RandomName("daemon"), 1, 1, 0x55);
Schedule.Info.Months = ScheduleMonths.All;
Schedule.Info.Days = ScheduleDays.All;
Schedule.Info.Times = ScheduleTimes.EveryQuarterHour;
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(2.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(8.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(1.0);
Options.Rules.AllowBeneficial = true;
Options.Rules.AllowHarmful = true;
Options.Rules.AllowHousing = false;
Options.Rules.AllowPets = false;
Options.Rules.AllowSpawn = false;
Options.Rules.AllowSpeech = true;
Options.Rules.CanBeDamaged = true;
Options.Rules.CanDamageEnemyTeam = true;
Options.Rules.CanDamageOwnTeam = false;
Options.Rules.CanDie = false;
Options.Rules.CanHeal = true;
Options.Rules.CanHealEnemyTeam = false;
Options.Rules.CanHealOwnTeam = true;
Options.Rules.CanMount = false;
Options.Rules.CanFly = false;
Options.Rules.CanResurrect = false;
Options.Rules.CanUseStuckMenu = false;
Options.Rules.CanEquip = true;
}
public TvTBattle(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(1);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var v = reader.GetVersion();
if (v < 1)
{
RewardTeam = true;
}
}
}
}

View File

@@ -0,0 +1,65 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TvTBattle1v1 : TvTBattle
{
private static readonly TimeSpan[] _Times =
{
new TimeSpan(0, 30, 0), new TimeSpan(2, 30, 0), new TimeSpan(4, 30, 0), new TimeSpan(6, 30, 0),
new TimeSpan(8, 30, 0), new TimeSpan(10, 30, 0), new TimeSpan(13, 30, 0), new TimeSpan(15, 30, 0),
new TimeSpan(17, 30, 0), new TimeSpan(19, 30, 0), new TimeSpan(21, 30, 0), new TimeSpan(23, 45, 0)
};
public TvTBattle1v1()
{
Name = "1 vs 1";
Teams[0].MinCapacity = 1;
Teams[0].MaxCapacity = 1;
Teams[1].MinCapacity = 1;
Teams[1].MaxCapacity = 1;
Schedule.Info.Times.Clear();
Schedule.Info.Times.Add(_Times);
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(4.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(8.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(10.0);
}
public TvTBattle1v1(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,77 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TvTBattle2v2 : TvTBattle
{
private static readonly TimeSpan[] _Times =
{
new TimeSpan(0, 30, 0), new TimeSpan(2, 30, 0), new TimeSpan(4, 30, 0), new TimeSpan(6, 30, 0),
new TimeSpan(8, 30, 0), new TimeSpan(10, 30, 0), new TimeSpan(13, 30, 0), new TimeSpan(15, 30, 0),
new TimeSpan(17, 30, 0), new TimeSpan(19, 30, 0), new TimeSpan(21, 30, 0), new TimeSpan(23, 45, 0)
};
public TvTBattle2v2()
{
Name = "2 vs 2";
Teams[0].MinCapacity = 1;
Teams[0].MaxCapacity = 2;
Teams[1].MinCapacity = 1;
Teams[1].MaxCapacity = 2;
Schedule.Info.Times.Clear();
Schedule.Info.Times.Add(_Times);
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(4.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(8.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(10.0);
}
public TvTBattle2v2(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
break;
}
}
}
}

View File

@@ -0,0 +1,79 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TvTBattle3v3 : TvTBattle
{
private static readonly TimeSpan[] _Times =
{
new TimeSpan(1, 30, 0), new TimeSpan(3, 30, 0), new TimeSpan(5, 30, 0), new TimeSpan(7, 30, 0),
new TimeSpan(9, 30, 0), new TimeSpan(11, 30, 0), new TimeSpan(14, 30, 0), new TimeSpan(16, 30, 0),
new TimeSpan(18, 30, 0), new TimeSpan(20, 30, 0)
};
public TvTBattle3v3()
{
Name = "3 vs 3";
Teams[0].MinCapacity = 1;
Teams[0].MaxCapacity = 3;
Teams[1].MinCapacity = 1;
Teams[1].MaxCapacity = 3;
Schedule.Info.Times.Clear();
Schedule.Info.Times.Add(_Times);
Options.Broadcasts.World.MessageHue = 891;
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(3.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(12.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(10.0);
}
public TvTBattle3v3(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
break;
}
}
}
}

View File

@@ -0,0 +1,79 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP.Battles
{
public class TvTBattle5v5 : TvTBattle
{
private static readonly TimeSpan[] _Times =
{
new TimeSpan(1, 30, 0), new TimeSpan(3, 30, 0), new TimeSpan(5, 30, 0), new TimeSpan(7, 30, 0),
new TimeSpan(9, 30, 0), new TimeSpan(11, 30, 0), new TimeSpan(14, 30, 0), new TimeSpan(16, 30, 0),
new TimeSpan(18, 30, 0), new TimeSpan(20, 30, 0)
};
public TvTBattle5v5()
{
Name = "5 vs 5";
Teams[0].MinCapacity = 1;
Teams[0].MaxCapacity = 5;
Teams[1].MinCapacity = 1;
Teams[1].MaxCapacity = 5;
Schedule.Info.Times.Clear();
Schedule.Info.Times.Add(_Times);
Options.Broadcasts.World.MessageHue = 891;
Options.Timing.PreparePeriod = TimeSpan.FromMinutes(3.0);
Options.Timing.RunningPeriod = TimeSpan.FromMinutes(12.0);
Options.Timing.EndedPeriod = TimeSpan.FromMinutes(10.0);
}
public TvTBattle5v5(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
break;
}
}
}
}

View File

@@ -0,0 +1,147 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum AutoPvPStoneCommand
{
ViewBattles,
ViewProfiles,
GlobalConfig
}
public class AutoPvPStone : Item
{
[CommandProperty(AutoPvP.Access)]
public AutoPvPStoneCommand Command { get; set; }
[CommandProperty(AutoPvP.Access)]
public KnownColor UsageColor { get; set; }
public override bool DisplayLootType => false;
public override bool DisplayWeight => false;
[Constructable]
public AutoPvPStone()
: this(4963)
{ }
[Constructable]
public AutoPvPStone(int itemID)
: base(itemID)
{
Command = AutoPvPStoneCommand.ViewBattles;
UsageColor = KnownColor.SkyBlue;
Name = "PvP Battle Stone";
LootType = LootType.Blessed;
Weight = 0;
}
public AutoPvPStone(Serial serial)
: base(serial)
{ }
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
var color = Color.FromKnownColor(UsageColor).ToRgb();
switch (Command)
{
case AutoPvPStoneCommand.ViewBattles:
{
list.Add("<basefont color=#{0:X6}>Opens the PvP battles menu<basefont color=#ffffff>", color);
}
break;
case AutoPvPStoneCommand.ViewProfiles:
{
list.Add("<basefont color=#{0:X6}>Opens the PvP profiles menu<basefont color=#ffffff>", color);
}
break;
case AutoPvPStoneCommand.GlobalConfig:
{
list.Add("<basefont color=#{0:X6}>Use: Opens the PvP control panel<basefont color=#ffffff>", color);
}
break;
}
}
public override void OnDoubleClick(Mobile from)
{
if (from == null || from.Deleted)
{
return;
}
switch (Command)
{
case AutoPvPStoneCommand.ViewBattles:
{
AutoPvP.CMOptions.Advanced.Commands.InvokeBattlesCommand(from);
}
break;
case AutoPvPStoneCommand.ViewProfiles:
{
AutoPvP.CMOptions.Advanced.Commands.InvokeProfilesCommand(from);
}
break;
case AutoPvPStoneCommand.GlobalConfig:
{
AutoPvP.CMOptions.Advanced.Commands.InvokeConfigCommand(from);
}
break;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteFlag(Command);
writer.WriteFlag(UsageColor);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Command = reader.ReadFlag<AutoPvPStoneCommand>();
UsageColor = reader.ReadFlag<KnownColor>();
}
break;
}
}
}
}

View File

@@ -0,0 +1,118 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using VitaNex.Items;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPSpectatorGate : FloorTile<PlayerMobile>
{
[CommandProperty(AutoPvP.Access)]
public PvPBattle Battle { get; set; }
public override bool ForceShowProperties => true;
public PvPSpectatorGate(PvPBattle battle)
{
Battle = battle;
Name = "PvP Battle Gate";
ItemID = 19343;
Hue = 51;
Visible = true;
Movable = false;
}
public PvPSpectatorGate(Serial serial)
: base(serial)
{ }
public override void OnAosSingleClick(Mobile from)
{
OnSingleClick(from);
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
if (Battle == null)
{
return;
}
LabelTo(from, "Battle: {0}", Battle.Name);
LabelTo(from, "Status: {0} ({1})", Battle.State, Battle.GetStateTimeLeft().ToSimpleString("h:m:s"));
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Battle != null)
{
list.Add(
"Battle: {0}\nStatus: {1} ({2})",
Battle.Name,
Battle.State,
Battle.GetStateTimeLeft().ToSimpleString("h:m:s"));
}
}
public override bool OnMoveOver(PlayerMobile mob)
{
if (!base.OnMoveOver(mob) || mob == null || Battle == null || Battle.Deleted || !Battle.SpectateAllowed || Battle.IsInternal)
{
return false;
}
Timer.DelayCall(
TimeSpan.FromSeconds(1),
() =>
{
if (mob.X == X && mob.Y == Y)
{
new ConfirmDialogGump(mob)
{
Title = "Join as Spectator?",
Html = "Join " + Battle.Name +
" as a spectator.\nYou will be teleported to a safe area where you can watch the battle.\nClick OK to join!",
AcceptHandler = b => Battle.AddSpectator(mob, true)
}.Send();
}
});
return true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,118 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using VitaNex.Items;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPTeamGate : FloorTile<PlayerMobile>
{
[CommandProperty(AutoPvP.Access)]
public PvPTeam Team { get; set; }
public override bool ForceShowProperties => true;
public PvPTeamGate(PvPTeam team)
{
Team = team;
Name = "PvP Team Gate";
Hue = Team.Color;
ItemID = 19343;
Visible = true;
Movable = false;
}
public PvPTeamGate(Serial serial)
: base(serial)
{ }
public override void OnAosSingleClick(Mobile from)
{
OnSingleClick(from);
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
if (Team == null || Team.Battle == null)
{
return;
}
LabelTo(from, "Battle: {0}", Team.Battle.Name);
LabelTo(from, "Team: {0}", Team.Name);
LabelTo(from, "Status: {0} ({1})", Team.Battle.State, Team.Battle.GetStateTimeLeft().ToSimpleString("h:m:s"));
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Team != null && Team.Battle != null)
{
list.Add(
"Battle: {0}\nTeam: {1}\nStatus: {2} ({3})",
Team.Battle.Name,
Team.Name,
Team.Battle.State,
Team.Battle.GetStateTimeLeft().ToSimpleString("h:m:s"));
}
}
public override bool OnMoveOver(PlayerMobile mob)
{
if (mob == null || !base.OnMoveOver(mob))
{
return false;
}
if (Team == null || Team.Deleted || Team.Battle == null || Team.Battle.Deleted || !Team.Battle.QueueAllowed || Team.Battle.IsInternal)
{
return false;
}
Timer.DelayCall(
TimeSpan.FromSeconds(1),
() =>
{
if (mob.X == X && mob.Y == Y)
{
Team.Battle.Enqueue(mob, Team);
}
});
return true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,858 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
using VitaNex.Network;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public void Teleport(Mobile m, Point3D destLoc, Map destMap)
{
if (m == null || m.Deleted || destLoc == Point3D.Zero || destMap == Map.Internal)
{
return;
}
var oldLoc = m.Location;
var oldMap = m.Map;
var pm = m as PlayerMobile;
if (pm != null && !IsOnline(pm))
{
pm.LogoutLocation = destLoc;
pm.LogoutMap = destMap;
if (!pm.Alive && pm.Corpse != null && !pm.Corpse.Deleted)
{
pm.Corpse.MoveToWorld(destLoc, destMap);
}
OnTeleported(pm, oldLoc, oldMap);
return;
}
if (!m.Hidden)
{
var fx = EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration);
Effects.SendLocationParticles(fx, 0x3728, 10, 10, 5023);
}
m.MoveToWorld(destLoc, destMap);
m.Send(VNScreenLightFlash.Instance);
SendSound(Options.Sounds.Teleport);
if (!m.Hidden)
{
var fx = EffectItem.Create(destLoc, destMap, EffectItem.DefaultDuration);
Effects.SendLocationParticles(fx, 0x3728, 10, 10, 5023);
}
if (m.Location != destLoc || m.Map != destMap)
{
return;
}
if (!m.Alive && m.Corpse != null && !m.Corpse.Deleted)
{
m.Corpse.MoveToWorld(m.Location, m.Map);
}
OnTeleported(m, oldLoc, oldMap);
}
public virtual void TeleportToEjectLocation(PlayerMobile pm)
{
if (pm != null && !pm.Deleted && !Options.Locations.Eject.Zero && !Options.Locations.Eject.Internal)
{
Teleport(pm, Options.Locations.Eject, Options.Locations.Eject);
}
}
public virtual void TeleportToSpectateLocation(PlayerMobile pm)
{
if (pm != null && !pm.Deleted && Options.Locations.SpectateJoin != Point3D.Zero && Options.Locations.Map != null &&
Options.Locations.Map != Map.Internal)
{
Teleport(pm, Options.Locations.SpectateJoin, Options.Locations.Map);
}
}
public virtual void TeleportToHomeBase(PvPTeam team, PlayerMobile pm)
{
if (pm != null && !pm.Deleted && team != null && !team.Deleted)
{
Teleport(pm, team.HomeBase, Options.Locations.Map);
}
}
public virtual void TeleportToSpawnPoint(PvPTeam team, PlayerMobile pm)
{
if (pm == null || pm.Deleted || team == null || team.Deleted)
{
return;
}
var p = team.SpawnPoint;
if (team.RespawnRangeMin > 0 && team.RespawnRangeMax > 0)
{
p = p.GetRandomPoint3D(team.RespawnRangeMin, team.RespawnRangeMax);
}
Teleport(pm, p, Options.Locations.Map);
}
protected virtual void OnTeleported(Mobile m, Point3D oldLocation, Map oldMap)
{
if (m == null || m.Deleted)
{
return;
}
m.UpdateRegion();
if (m is PlayerMobile)
{
OnTeleported((PlayerMobile)m, oldLocation, oldMap);
}
m.Delta(MobileDelta.Noto);
m.ProcessDelta();
}
protected virtual void OnTeleported(PlayerMobile pm, Point3D oldLocation, Map oldMap)
{
if (pm == null || pm.Deleted)
{
return;
}
var old = Region.Find(oldLocation, oldMap);
if (!old.IsPartOf(BattleRegion))
{
if (pm.InRegion(BattleRegion))
{
Negate(pm);
}
}
else
{
if (!pm.InRegion(BattleRegion))
{
Negate(pm);
}
}
}
public virtual bool CheckMounted(Mobile m, bool dismount)
{
if (m == null || m.Deleted || !m.Mounted || m.Mount == null)
{
return false;
}
if (dismount)
{
CheckDismount(m);
}
return true;
}
public virtual bool CheckDismount(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return false;
}
if (State == PvPBattleState.Internal || Hidden)
{
return false;
}
if (m.Flying && Options.Rules.CanFly)
{
return false;
}
if (m.Mounted)
{
if (m.Mount is EtherealMount && Options.Rules.CanMountEthereal)
{
return false;
}
if (Options.Rules.CanMount)
{
return false;
}
}
Dismount(m);
return true;
}
public virtual void Dismount(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
if (m.Flying)
{
m.Flying = false;
OnDismounted(m, null);
}
else if (m.Mount != null)
{
var mount = m.Mount;
mount.Rider = null;
OnDismounted(m, mount);
}
}
public virtual void OnDismounted(Mobile m, IMount mount)
{
if (m != null && !m.Deleted)
{
m.SendMessage(mount != null ? "You have been dismounted." : "You have been wing clipped.");
}
}
public bool AllowSpawn()
{
if (CheckAllowSpawn())
{
OnAllowSpawnAccept();
return true;
}
OnAllowSpawnDeny();
return false;
}
public virtual bool CheckAllowSpawn()
{
return Options.Rules.AllowSpawn;
}
protected virtual void OnAllowSpawnAccept()
{ }
protected virtual void OnAllowSpawnDeny()
{ }
public bool CanMoveThrough(Mobile m, IEntity e)
{
if (CheckCanMoveThrough(m, e))
{
OnCanMoveThroughAccept(m, e);
return true;
}
OnCanMoveThroughDeny(m, e);
return false;
}
public virtual bool CheckCanMoveThrough(Mobile m, IEntity e)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
#if NEWENTITY
return e == null || e.Deleted || Options.Rules.CanMoveThrough;
#else
return e == null || (e is Mobile && ((Mobile)e).Deleted) || (e is Item && ((Item)e).Deleted) ||
Options.Rules.CanMoveThrough;
#endif
}
protected virtual void OnCanMoveThroughAccept(Mobile m, IEntity e)
{ }
protected virtual void OnCanMoveThroughDeny(Mobile m, IEntity e)
{ }
public bool AllowHousing(Mobile m, Point3D p)
{
if (CheckAllowHousing(m, p))
{
OnAllowHousingAccept(m, p);
return true;
}
OnAllowHousingDeny(m, p);
return false;
}
public virtual bool CheckAllowHousing(Mobile m, Point3D p)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return Options.Rules.AllowHousing;
}
protected virtual void OnAllowHousingAccept(Mobile m, Point3D p)
{ }
protected virtual void OnAllowHousingDeny(Mobile m, Point3D p)
{
if (m != null && !m.Deleted)
{
m.SendMessage("You can not place structures here at this time.");
}
}
public bool CanUseStuckMenu(Mobile m)
{
if (CheckCanUseStuckMenu(m))
{
OnCanUseStuckMenuAccept(m);
return true;
}
OnCanUseStuckMenuDeny(m);
return false;
}
public virtual bool CheckCanUseStuckMenu(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return Options.Rules.CanUseStuckMenu;
}
protected virtual void OnCanUseStuckMenuAccept(Mobile m)
{ }
protected virtual void OnCanUseStuckMenuDeny(Mobile m)
{
if (m != null && !m.Deleted)
{
m.SendMessage("You can not use the stuck menu at this time.");
}
}
public bool OnBeforeDeath(Mobile m)
{
if (CheckDeath(m))
{
OnDeathAccept(m);
return true;
}
OnDeathDeny(m);
return false;
}
public virtual bool CheckDeath(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return false;
}
return Options.Rules.CanDie;
}
protected virtual void OnDeathAccept(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
var pm = m as PlayerMobile;
if (pm == null)
{
return;
}
if (IsParticipant(pm, out var team) && team != null && !team.Deleted)
{
team.OnMemberDeath(pm);
}
}
protected virtual void OnDeathDeny(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
var pm = m as PlayerMobile;
if (pm == null)
{
return;
}
if (IsParticipant(pm, out var team) && team != null && !team.Deleted)
{
team.OnMemberDeath(pm);
}
}
public virtual void OnDeath(Mobile m)
{ }
public bool OnSkillUse(Mobile user, int skill)
{
if (CheckSkillUse(user, skill))
{
OnSkillUseAccept(user, skill);
return true;
}
OnSkillUseDeny(user, skill);
return false;
}
public virtual bool CheckSkillUse(Mobile user, int skill)
{
if (user == null || user.Deleted || skill < 0)
{
return false;
}
if (!DebugMode && user.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return !Options.Restrictions.Skills.IsRestricted(skill);
}
protected virtual void OnSkillUseAccept(Mobile user, int skill)
{ }
protected virtual void OnSkillUseDeny(Mobile user, int skill)
{
if (user != null && !user.Deleted && skill >= 0)
{
user.SendMessage("You can not use that skill at this time.");
}
}
public bool OnBeginSpellCast(Mobile caster, ISpell spell)
{
if (CheckSpellCast(caster, spell))
{
OnSpellCastAccept(caster, spell);
return true;
}
OnSpellCastDeny(caster, spell);
return false;
}
public virtual bool CheckSpellCast(Mobile caster, ISpell spell)
{
if (caster == null || caster.Deleted || spell == null)
{
return false;
}
if (!DebugMode && caster.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
if (!(spell is Spell))
{
return true;
}
if (!Options.Rules.CanFly)
{
var t = spell.GetType();
if (t.Name.ContainsAny("FlySpell", "FlightSpell"))
{
return false;
}
}
return !Options.Restrictions.Spells.IsRestricted((Spell)spell);
}
protected virtual void OnSpellCastAccept(Mobile caster, ISpell spell)
{ }
protected virtual void OnSpellCastDeny(Mobile caster, ISpell spell)
{
if (caster != null && !caster.Deleted && spell != null)
{
caster.SendMessage("You can not use that spell at this time.");
}
}
public virtual bool CheckDamage(Mobile damaged, ref int damage)
{
if (damaged == null || damaged.Deleted)
{
return false;
}
if (!DebugMode && damaged.AccessLevel >= AccessLevel.Counselor)
{
return false;
}
return Options.Rules.CanBeDamaged;
}
public virtual void OnDamage(Mobile damager, Mobile damaged, int damage)
{
if (damage <= 0)
{
return;
}
PlayerMobile pm;
PvPTeam t;
if (damager != null && !damager.Deleted && damager is PlayerMobile)
{
pm = (PlayerMobile)damager;
if (IsParticipant(pm, out t))
{
var d = damage;
UpdateStatistics(t, pm, o => o.DamageDone += d);
}
}
if (damaged != null && !damaged.Deleted && damaged is PlayerMobile)
{
pm = (PlayerMobile)damaged;
if (IsParticipant(pm, out t))
{
var d = damage;
UpdateStatistics(t, pm, o => o.DamageTaken += d);
}
}
}
public virtual bool CheckHeal(Mobile healed, ref int heal)
{
if (healed == null || healed.Deleted)
{
return false;
}
if (!DebugMode && healed.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return Options.Rules.CanHeal;
}
public virtual void OnHeal(Mobile healer, Mobile healed, int heal)
{
if (heal <= 0)
{
return;
}
PlayerMobile pm;
PvPTeam t;
if (healer != null && !healer.Deleted && healer is PlayerMobile)
{
pm = (PlayerMobile)healer;
if (IsParticipant(pm, out t))
{
var h = heal;
UpdateStatistics(t, pm, o => o.HealingDone += h);
}
}
if (healed != null && !healed.Deleted && healed is PlayerMobile)
{
pm = (PlayerMobile)healed;
if (IsParticipant(pm, out t))
{
var h = heal;
UpdateStatistics(t, pm, o => o.HealingTaken += h);
}
}
}
public bool OnResurrect(Mobile m)
{
if (CheckResurrect(m))
{
OnResurrectAccept(m);
return true;
}
OnResurrectDeny(m);
return false;
}
public virtual bool CheckResurrect(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (!DebugMode && m.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return Options.Rules.CanResurrect;
}
protected virtual void OnResurrectAccept(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
var pm = m as PlayerMobile;
if (pm == null)
{
return;
}
if (IsParticipant(pm, out var team) && team != null && !team.Deleted)
{
team.OnMemberResurrected(pm);
}
}
protected virtual void OnResurrectDeny(Mobile m)
{
if (m != null && !m.Deleted)
{
m.SendMessage("You can not be resurrected at this time.");
}
}
public void OnSpeech(SpeechEventArgs args)
{
if (args.Mobile is PlayerMobile)
{
var pm = (PlayerMobile)args.Mobile;
if (HandleSubCommand(pm, args.Speech))
{
args.Handled = true;
args.Blocked = true;
return;
}
}
if (CheckSpeech(args))
{
OnSpeechAccept(args);
return;
}
args.Handled = true;
args.Blocked = true;
OnSpeechDeny(args);
}
public virtual bool CheckSpeech(SpeechEventArgs e)
{
if (e.Mobile == null || e.Mobile.Deleted)
{
return false;
}
if (!DebugMode && e.Mobile.AccessLevel >= AccessLevel.Counselor)
{
return true;
}
return Options.Rules.AllowSpeech;
}
protected virtual void OnSpeechAccept(SpeechEventArgs args)
{ }
protected virtual void OnSpeechDeny(SpeechEventArgs args)
{
if (args.Mobile != null && !args.Mobile.Deleted)
{
args.Mobile.SendMessage("You can not talk at this time.");
}
}
public virtual void OnSpellCast(Mobile m, ISpell s)
{ }
public virtual void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal)
{ }
public virtual void OnBeneficialAction(Mobile helper, Mobile target)
{ }
public virtual bool OnCombatantChange(Mobile m, Mobile oldMob, Mobile newMob)
{
return m != null && !m.Deleted;
}
public virtual void OnCriminalAction(Mobile m, bool message)
{ }
public virtual void OnDidHarmful(Mobile harmer, Mobile harmed)
{ }
public virtual bool OnDoubleClick(Mobile m, object o)
{
if (o is Item)
{
return OnDoubleClick(m, (Item)o);
}
if (o is Mobile)
{
return OnDoubleClick(m, (Mobile)o);
}
return m != null && !m.Deleted && o != null;
}
public virtual bool OnDoubleClick(Mobile m, Item item)
{
return m != null && !m.Deleted && item != null && !item.Deleted && CanUseItem(m, item, true);
}
public virtual bool OnDoubleClick(Mobile m, Mobile target)
{
if (target is BaseCreature)
{
return OnDoubleClick(m, (BaseCreature)target);
}
return m != null && !m.Deleted && target != null && !target.Deleted && CanUseMobile(m, target, true);
}
public virtual bool OnDoubleClick(Mobile m, BaseCreature target)
{
return m != null && !m.Deleted && target != null && !target.Deleted && CanUseMobile(m, target, true);
}
public virtual bool OnSingleClick(Mobile m, object o)
{
if (o is Item)
{
return OnSingleClick(m, (Item)o);
}
if (o is Mobile)
{
return OnSingleClick(m, (Mobile)o);
}
return m != null && !m.Deleted && o != null;
}
public virtual bool OnSingleClick(Mobile m, Item item)
{
return m != null && !m.Deleted && item != null && !item.Deleted && CanUseItem(m, item, false);
}
public virtual bool OnSingleClick(Mobile m, Mobile target)
{
if (target is BaseCreature)
{
return OnSingleClick(m, (BaseCreature)target);
}
return m != null && !m.Deleted && target != null && !target.Deleted && CanUseMobile(m, target, false);
}
public virtual bool OnSingleClick(Mobile m, BaseCreature target)
{
return m != null && !m.Deleted && target != null && !target.Deleted && CanUseMobile(m, target, false);
}
public virtual void OnGotBeneficialAction(Mobile helper, Mobile target)
{ }
public virtual void OnGotHarmful(Mobile harmer, Mobile harmed)
{ }
public virtual bool OnTarget(Mobile m, Target target, object o)
{
return m != null && !m.Deleted && target != null && o != null;
}
}
}

View File

@@ -0,0 +1,610 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Mobiles;
using Server.Regions;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan LogoutDelay { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan IdleThreshold { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool IdleKick { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool InviteWhileRunning { get; set; }
public virtual Dictionary<PlayerMobile, MapPoint> BounceInfo { get; private set; }
public virtual bool InOtherBattle(PlayerMobile pm)
{
if (pm == null)
{
return false;
}
var battle = AutoPvP.FindBattle(pm);
return battle != null && battle != this && battle.IsParticipant(pm);
}
public bool IsAliveParticipant(PlayerMobile pm)
{
if (pm == null)
{
return false;
}
return IsParticipant(pm, out var team) && !team.IsDead(pm);
}
public bool IsDeadParticipant(PlayerMobile pm)
{
if (pm == null)
{
return false;
}
return IsParticipant(pm, out var team) && team.IsDead(pm);
}
public bool IsParticipant(PlayerMobile pm)
{
if (pm == null)
{
return false;
}
return IsParticipant(pm, out var team);
}
public bool IsParticipant(PlayerMobile pm, out PvPTeam team)
{
if (pm == null)
{
team = null;
return false;
}
team = FindTeam(pm);
return team != null;
}
public virtual TimeSpan GetLogoutDelay(Mobile m)
{
return LogoutDelay;
}
public IEnumerable<PlayerMobile> GetParticipants()
{
return Teams.Where(t => t != null && !t.Deleted).SelectMany(t => t.Where(p => p != null && !p.Deleted));
}
public virtual bool CanSendInvites()
{
return !Hidden && (IsPreparing || (IsRunning && InviteWhileRunning)) && CurrentCapacity < MaxCapacity;
}
public virtual bool CanSendInvite(PlayerMobile pm)
{
return pm != null && !pm.Deleted && pm.Alive && !pm.InRegion<Jail>() && pm.DesignContext == null && IsOnline(pm) &&
!InCombat(pm) && IsQueued(pm) && !IsParticipant(pm) && !InOtherBattle(pm) && !AutoPvP.IsDeserter(pm);
}
public virtual void SendInvites()
{
foreach (var pm in Queue.Keys)
{
var invites = SuperGump.GetInstances<PvPInviteGump>(pm);
if (CanSendInvite(pm))
{
var sendNew = invites.All(invite => !invite.IsOpen || invite.Battle != this);
if (sendNew)
{
OnSendInvite(pm, new PvPInviteGump(pm, this));
}
}
else
{
foreach (var invite in invites.Where(invite => invite.IsOpen && invite.Battle == this))
{
invite.Close();
}
}
}
}
protected virtual void OnSendInvite(PlayerMobile pm, PvPInviteGump invite)
{
if (pm == null || pm.Deleted || !pm.Alive || invite == null || invite.IsDisposed)
{
return;
}
invite.Send();
SendSound(pm, Options.Sounds.InviteSend);
}
public void AcceptInvite(PlayerMobile pm)
{
if (pm == null || pm.Deleted || !pm.Alive)
{
return;
}
if (CanSendInvites() && CanSendInvite(pm))
{
OnInviteAccept(pm);
}
else
{
OnInviteRejected(pm);
}
}
public void DeclineInvite(PlayerMobile pm)
{
if (pm != null && !pm.Deleted)
{
OnInviteDecline(pm);
}
}
protected virtual void OnInviteAccept(PlayerMobile pm)
{
if (pm == null || pm.Deleted || !IsOnline(pm) || IsInternal || Hidden)
{
return;
}
if (!IsQueued(pm))
{
pm.SendMessage("You are not queued for {0}", Name);
return;
}
if (IsParticipant(pm))
{
pm.SendMessage("You are already participating in {0}", Name);
return;
}
if (InOtherBattle(pm))
{
pm.SendMessage("You cannot join {0} while you are in another battle.", Name);
return;
}
if (IsFull)
{
pm.SendMessage("The battle is full, you will be sent an invite if someone leaves.");
return;
}
var team = Queue[pm];
if (team == null || team.Deleted) // Assume AutoAssign is true
{
if (Teams.Count == 1)
{
team = Teams[0];
}
else if (AutoAssign) // Make sure AutoAssign is true
{
team = GetAutoAssignTeam(pm);
}
}
if (team == null || team.Deleted) // Fallback to most empty, or random team
{
team = GetMostEmptyTeam();
if (team == null || team.Deleted)
{
team = GetRandomTeam();
}
}
if (team == null || team.Deleted)
{
pm.SendMessage("The team you've chosen seems to have vanished in the void, sorry about that.");
Queue.Remove(pm);
return;
}
if (team.IsFull)
{
pm.SendMessage("The team you've chosen is full, you will be sent an invite if someone leaves.");
return;
}
Queue.Remove(pm);
RecordBounce(pm);
team.AddMember(pm, true);
SendSound(pm, Options.Sounds.InviteAccept);
}
protected virtual void OnInviteDecline(PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return;
}
pm.SendMessage("You decide not to join {0}", Name);
SendSound(pm, Options.Sounds.InviteCancel);
if (IsQueued(pm))
{
Dequeue(pm);
}
}
protected virtual void OnInviteRejected(PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return;
}
pm.SendMessage("You can not join {0} at this time.", Name);
SendSound(pm, Options.Sounds.InviteCancel);
}
public void RecordBounce(PlayerMobile pm)
{
if (pm == null || pm.Deleted || pm.InRegion<PvPBattleRegion>())
{
return;
}
var bounce = pm.ToMapPoint();
if (bounce != null && !bounce.InternalOrZero)
{
BounceInfo[pm] = bounce;
}
}
public void Quit(Mobile m, bool teleport)
{
var pm = m as PlayerMobile;
if (pm != null)
{
if (IsParticipant(pm, out var team))
{
UpdateStatistics(team, pm, o => ++o.Losses);
if (IsRunning)
{
OnDeserted(team, pm);
}
}
}
Eject(m, teleport);
}
public void Eject(Mobile m, bool teleport)
{
if (m == null || m.Deleted)
{
return;
}
if (m is PlayerMobile)
{
Eject((PlayerMobile)m, teleport);
}
else if (m is BaseCreature)
{
Eject((BaseCreature)m, teleport);
}
}
public void Eject(PlayerMobile pm, bool teleport)
{
if (pm == null || pm.Deleted)
{
return;
}
if (IsParticipant(pm, out var team))
{
if (IsRunning || IsEnded)
{
UpdateStatistics(team, pm, o => ++o.Battles);
}
team.RemoveMember(pm, false);
}
else if (IsSpectator(pm))
{
RemoveSpectator(pm, false);
}
if (teleport)
{
var bounce = BounceInfo.GetValue(pm);
if (bounce != null && !bounce.InternalOrZero)
{
Teleport(pm, bounce, bounce);
BounceInfo.Remove(pm);
}
else
{
Teleport(pm, Options.Locations.Eject, Options.Locations.Eject.Map);
}
}
}
public void Eject(BaseCreature bc, bool teleportOrStable)
{
if (bc == null || bc.Deleted)
{
return;
}
var pet = bc.IsControlled<PlayerMobile>();
if (!teleportOrStable)
{
if (!pet)
{
bc.Delete();
}
return;
}
if (!pet || !bc.Stable())
{
Teleport(bc, Options.Locations.Eject, Options.Locations.Eject);
}
}
protected virtual void OnEjected(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
if (m is PlayerMobile)
{
OnEjected((PlayerMobile)m);
}
else if (m is BaseCreature)
{
OnEjected((BaseCreature)m);
}
}
protected virtual void OnEjected(PlayerMobile pm)
{
if (pm != null && !pm.Deleted)
{
pm.SendMessage("You have been ejected from the battle.");
}
}
protected virtual void OnEjected(BaseCreature bc)
{ }
protected virtual void OnDeserted(PvPTeam team, PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return;
}
pm.SendMessage(0x22, "You have deserted {0}!", Name);
AutoPvP.AddDeserter(pm);
RevokePoints(pm);
UpdateStatistics(team, pm, o => ++o["Deserted"]);
WorldBroadcast("{0} has deserted {1}!", pm.RawName, Name);
}
public virtual void InvalidateStray(Mobile m)
{
if (IsInternal || Hidden || m == null || m.Deleted)
{
return;
}
if (m is PlayerMobile)
{
InvalidateStrayPlayer((PlayerMobile)m);
}
else if (m is BaseCreature)
{
var bc = (BaseCreature)m;
if (bc.IsControlled())
{
InvalidateStrayPet(bc);
}
else
{
InvalidateStraySpawn(bc);
}
}
}
public virtual void InvalidateStrayPlayer(PlayerMobile player)
{
if (IsInternal || Hidden || player == null || player.Deleted)
{
return;
}
if (player.InRegion(SpectateRegion))
{
if (IsParticipant(player))
{
Eject(player, false);
}
if (!IsSpectator(player))
{
AddSpectator(player, false);
}
}
else if (player.InRegion(BattleRegion))
{
if (IsParticipant(player))
{
if (IsSpectator(player))
{
RemoveSpectator(player, false);
}
Queue.Remove(player);
if (DebugMode || player.AccessLevel < AccessLevel.Counselor)
{
if (player.Flying && !Options.Rules.CanFly)
{
player.Flying = false;
}
if (player.Mounted)
{
var canMount = Options.Rules.CanMount;
if (player.Mount is EtherealMount)
{
canMount = Options.Rules.CanMountEthereal;
}
if (!canMount)
{
player.Dismount();
}
}
}
}
else if (!IsSpectator(player))
{
if ((DebugMode || player.AccessLevel < AccessLevel.Counselor) && SpectateAllowed)
{
AddSpectator(player, true);
}
else if (DebugMode || player.AccessLevel < AccessLevel.Counselor)
{
Eject(player, true);
}
}
}
}
public virtual void InvalidateStraySpawn(BaseCreature mob)
{
if (IsInternal || Hidden || mob == null || mob.Deleted || !mob.InRegion(BattleRegion))
{
return;
}
if (!AllowSpawn())
{
Eject(mob, mob.IsControlled<PlayerMobile>());
}
}
public virtual void InvalidateStrayPet(BaseCreature pet)
{
if (IsInternal || Hidden || pet == null || pet.Deleted || !pet.InRegion(BattleRegion))
{
return;
}
if (!Options.Rules.AllowPets)
{
var master = pet.GetMaster<PlayerMobile>();
if (master == null || DebugMode || master.AccessLevel < AccessLevel.Counselor)
{
Eject(pet, master != null);
}
}
}
public virtual void InvalidateGates()
{
InvalidateSpectateGate();
InvalidateTeamGates();
}
public virtual void InvalidateSpectateGate()
{
if (!SpectateAllowed || SpectateRegion == null || IsInternal || Options.Locations.SpectateGate.InternalOrZero)
{
if (Gate != null)
{
Gate.Delete();
Gate = null;
}
return;
}
if (Gate == null || Gate.Deleted)
{
Gate = new PvPSpectatorGate(this);
if (!Options.Locations.SpectateGate.MoveToWorld(Gate))
{
Gate.MoveToWorld(Options.Locations.SpectateGate, Options.Locations.SpectateGate);
}
}
if (Gate.Battle == null)
{
Gate.Battle = this;
}
}
public virtual void InvalidateTeamGates()
{
ForEachTeam(t => t.InvalidateGate());
}
}
}

View File

@@ -0,0 +1,293 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#if ServUO58
#define ServUOX
#endif
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Commands;
using Server.Mobiles;
using Server.Network;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPBattleWarning
{
Starting,
Ending,
WBStarting,
WBEnding
}
public abstract partial class PvPBattle
{
public virtual IEnumerable<PlayerMobile> GetLocalBroadcastList()
{
if (BattleRegion != null)
{
#if ServUOX
foreach (var pm in BattleRegion.AllPlayers.OfType<PlayerMobile>().Where(IsOnline))
#else
foreach (var pm in BattleRegion.GetMobiles().OfType<PlayerMobile>().Where(IsOnline))
#endif
{
yield return pm;
}
}
if (SpectateRegion != null)
{
#if ServUOX
foreach (var pm in SpectateRegion.AllPlayers.OfType<PlayerMobile>().Where(IsOnline))
#else
foreach (var pm in SpectateRegion.GetMobiles().OfType<PlayerMobile>().Where(IsOnline))
#endif
{
yield return pm;
}
}
}
public virtual IEnumerable<PlayerMobile> GetWorldBroadcastList()
{
return NetState.Instances.Where(state => state != null)
.Select(state => state.Mobile as PlayerMobile)
.Where(pm => pm != null && !pm.Deleted)
.Where(pm => IsOnline(pm) && AutoPvP.EnsureProfile(pm).IsSubscribed(this));
}
public virtual void LocalBroadcast(string message, params object[] args)
{
var text = String.Format(message, args);
if (String.IsNullOrWhiteSpace(text))
{
return;
}
if (Options.Broadcasts.Local.Mode == PvPBattleLocalBroadcastMode.Disabled)
{
return;
}
AutoPvP.InvokeBattleLocalBroadcast(this, text);
foreach (var pm in GetLocalBroadcastList())
{
pm.SendMessage(IsParticipant(pm, out var team) ? team.Color : Options.Broadcasts.Local.MessageHue, text);
}
}
public virtual void WorldBroadcast(string message, params object[] args)
{
var text = String.Format(message, args);
if (String.IsNullOrWhiteSpace(text))
{
return;
}
if (Options.Broadcasts.World.Mode == PvPBattleWorldBroadcastMode.Disabled)
{
return;
}
AutoPvP.InvokeBattleWorldBroadcast(this, text);
switch (Options.Broadcasts.World.Mode)
{
case PvPBattleWorldBroadcastMode.Notify:
{
foreach (var pm in GetWorldBroadcastList())
{
pm.SendNotification(text, true, 0.5, 10.0);
}
}
break;
case PvPBattleWorldBroadcastMode.Broadcast:
{
var p = new AsciiMessage(Server.Serial.MinusOne, -1, MessageType.Regular, Options.Broadcasts.World.MessageHue, 3, "System", text);
p.Acquire();
foreach (var pm in GetWorldBroadcastList())
{
pm.Send(p);
}
p.Release();
NetState.FlushAll();
}
break;
case PvPBattleWorldBroadcastMode.TownCrier:
{
foreach (var tc in TownCrier.Instances)
{
tc.PublicOverheadMessage(MessageType.Yell, Options.Broadcasts.World.MessageHue, true, String.Format(message, args));
}
}
break;
}
}
protected virtual void BroadcastStateHandler()
{
if (Hidden)
{
return;
}
var state = State;
var timeLeft = GetStateTimeLeft(DateTime.UtcNow).Add(TimeSpan.FromSeconds(1.0));
if (timeLeft <= TimeSpan.Zero)
{
return;
}
switch (state)
{
case PvPBattleState.Ended:
BroadcastOpenMessage(timeLeft);
break;
case PvPBattleState.Preparing:
BroadcastStartMessage(timeLeft);
break;
case PvPBattleState.Running:
BroadcastEndMessage(timeLeft);
break;
}
}
protected virtual void BroadcastOpenMessage(TimeSpan timeLeft)
{
if (timeLeft.Minutes > 5 || timeLeft.Minutes == 0 || timeLeft.Seconds != 0)
{
return;
}
var msg = String.Format("{0} {1}", timeLeft.Minutes, timeLeft.Minutes != 1 ? "minutes" : "minute");
if (String.IsNullOrWhiteSpace(msg))
{
return;
}
if (Options.Broadcasts.Local.OpenNotify)
{
LocalBroadcast("{0} will open in {1}!", Name, msg);
}
if (Options.Broadcasts.World.OpenNotify)
{
var cmd = String.Empty;
if (QueueAllowed)
{
cmd = AutoPvP.CMOptions.Advanced.Commands.BattlesCommand;
cmd = String.Format("Use {0}{1} to join!", CommandSystem.Prefix, cmd);
}
WorldBroadcast("{0} will open in {1}! {2}", Name, msg, cmd);
}
}
protected virtual void BroadcastStartMessage(TimeSpan timeLeft)
{
if ((timeLeft.Minutes == 0 && timeLeft.Seconds > 10) || timeLeft.Minutes > 5)
{
return;
}
var msg = String.Empty;
if (timeLeft.Minutes > 0)
{
if (timeLeft.Seconds == 0)
{
msg = String.Format("{0} {1}", timeLeft.Minutes, timeLeft.Minutes != 1 ? "minutes" : "minute");
}
}
else if (timeLeft.Seconds > 0)
{
msg = String.Format("{0} {1}", timeLeft.Seconds, timeLeft.Seconds != 1 ? "seconds" : "second");
}
if (String.IsNullOrWhiteSpace(msg))
{
return;
}
if (Options.Broadcasts.Local.StartNotify)
{
LocalBroadcast("{0} will start in {1}!", Name, msg);
}
if (Options.Broadcasts.World.StartNotify && timeLeft.Minutes > 0)
{
var cmd = String.Empty;
if (QueueAllowed)
{
cmd = AutoPvP.CMOptions.Advanced.Commands.BattlesCommand;
cmd = String.Format("Use {0}{1} to join!", CommandSystem.Prefix, cmd);
}
WorldBroadcast("{0} will start in {1}! {2}", Name, msg, cmd);
}
}
protected virtual void BroadcastEndMessage(TimeSpan timeLeft)
{
if ((timeLeft.Minutes == 0 && timeLeft.Seconds > 10) || timeLeft.Minutes > 5)
{
return;
}
var msg = String.Empty;
if (timeLeft.Minutes > 0)
{
if (timeLeft.Seconds == 0)
{
msg = String.Format("{0} {1}", timeLeft.Minutes, timeLeft.Minutes != 1 ? "minutes" : "minute");
}
}
else if (timeLeft.Seconds > 0)
{
msg = String.Format("{0} {1}", timeLeft.Seconds, timeLeft.Seconds != 1 ? "seconds" : "second");
}
if (String.IsNullOrWhiteSpace(msg))
{
return;
}
if (Options.Broadcasts.Local.EndNotify)
{
LocalBroadcast("{0} will end in {1}!", Name, msg);
}
if (Options.Broadcasts.World.EndNotify && timeLeft.Minutes > 0)
{
WorldBroadcast("{0} will end in {1}", Name, msg);
}
}
}
}

View File

@@ -0,0 +1,107 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
[CommandProperty(AutoPvP.Access)]
public virtual int KillPoints { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int PointsBase { get; set; }
public virtual int GetAwardPoints(PvPTeam team, PlayerMobile pm)
{
if (!IsRunning || team == null || team.Deleted || (pm != null && !team.IsMember(pm)))
{
return 0;
}
return PointsBase;
}
public virtual void AwardPoints(PlayerMobile pm)
{
if (pm != null)
{
AwardPoints(pm, GetAwardPoints(FindTeam(pm), pm));
}
}
public virtual void AwardPoints(PlayerMobile pm, int points)
{
if (pm != null && points > 0)
{
if (IsParticipant(pm, out var t))
{
UpdateStatistics(t, pm, o => o.PointsGained += points);
}
}
}
public virtual void RevokePoints(PlayerMobile pm)
{
if (pm != null)
{
RevokePoints(pm, GetAwardPoints(FindTeam(pm), pm));
}
}
public virtual void RevokePoints(PlayerMobile pm, int points)
{
if (pm != null && points > 0)
{
if (IsParticipant(pm, out var t))
{
UpdateStatistics(t, pm, o => o.PointsLost += points);
}
}
}
public virtual void AwardTeamPoints(PvPTeam team)
{
if (team != null)
{
team.ForEachMember(pm => UpdateStatistics(team, pm, o => o.PointsGained += GetAwardPoints(team, pm)));
}
}
public virtual void AwardTeamPoints(PvPTeam team, int points)
{
if (team != null && points > 0)
{
team.ForEachMember(pm => UpdateStatistics(team, pm, o => o.PointsGained += points));
}
}
public virtual void RevokeTeamPoints(PvPTeam team)
{
if (team != null)
{
team.ForEachMember(pm => UpdateStatistics(team, pm, o => o.PointsLost += GetAwardPoints(team, pm)));
}
}
public virtual void RevokeTeamPoints(PvPTeam team, int points)
{
if (team != null)
{
team.ForEachMember(pm => UpdateStatistics(team, pm, o => o.PointsLost += points));
}
}
}
}

View File

@@ -0,0 +1,183 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Engines.PartySystem;
using Server.Mobiles;
using Server.Regions;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public Dictionary<PlayerMobile, PvPTeam> Queue { get; private set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool QueueAllowed { get; set; }
public virtual IEnumerable<PlayerMobile> GetQueued(PvPTeam team)
{
foreach (var kvp in Queue.Where(kvp => kvp.Value == team))
{
yield return kvp.Key;
}
}
public virtual void EnqueueParty(PlayerMobile pm, Party party, PvPTeam team = null)
{
if (pm == null || pm.Deleted || party == null || !party.Active || party.Leader != pm)
{
return;
}
var players = party.Members.Where(pmi => pmi != null && pmi.Mobile != pm)
.Select(pmi => pmi.Mobile as PlayerMobile)
.Where(m => m != null);
foreach (var m in players)
{
Enqueue(m, team, false);
}
}
public virtual void Enqueue(PlayerMobile pm, PvPTeam team = null, bool party = true)
{
if (pm == null || pm.Deleted)
{
return;
}
if (!CanQueue(pm))
{
OnQueueReject(pm);
return;
}
if (team != null && team.Deleted)
{
team = null;
}
if (!IsQueued(pm))
{
Queue.Add(pm, team);
OnQueueJoin(pm, team);
}
else
{
Queue[pm] = team;
OnQueueUpdate(pm, team);
}
if (party)
{
EnqueueParty(pm, Party.Get(pm), team);
}
}
public virtual void Dequeue(PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return;
}
var team = Queue.GetValue(pm);
if (Queue.Remove(pm))
{
OnQueueLeave(pm, team);
}
}
public virtual bool CanQueue(PlayerMobile pm)
{
return !IsInternal && QueueAllowed && IsOnline(pm) && pm.Alive && !InCombat(pm) && !IsQueued(pm) &&
!InOtherBattle(pm) && !AutoPvP.IsDeserter(pm) && !pm.InRegion<Jail>();
}
public virtual bool IsQueued(PlayerMobile pm)
{
return pm != null && Queue.ContainsKey(pm);
}
protected virtual void OnQueueJoin(PlayerMobile pm, PvPTeam team)
{
if (pm == null || pm.Deleted)
{
return;
}
pm.SendMessage(
"You have joined the queue for {0}{1}",
Name,
team != null ? ", your team is " + team.Name : String.Empty);
SendSound(pm, Options.Sounds.QueueJoin);
AutoPvP.InvokeQueueJoin(this, team, pm);
}
protected virtual void OnQueueUpdate(PlayerMobile pm, PvPTeam team)
{
if (pm == null || pm.Deleted)
{
return;
}
pm.SendMessage(
"Your queue status for {0} has changed{1}",
Name,
team != null ? ", your team is " + team.Name : String.Empty);
SendSound(pm, Options.Sounds.QueueJoin);
AutoPvP.InvokeQueueUpdate(this, team, pm);
}
protected virtual void OnQueueLeave(PlayerMobile pm, PvPTeam team)
{
if (pm == null || pm.Deleted || IsParticipant(pm))
{
return;
}
pm.SendMessage("You have left the queue for {0}", Name);
SendSound(pm, Options.Sounds.QueueLeave);
AutoPvP.InvokeQueueLeave(this, team, pm);
}
protected virtual void OnQueueReject(PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return;
}
if (IsQueued(pm))
{
pm.SendMessage("You are already in the queue for {0}", Name);
}
else
{
pm.SendMessage("You can not queue for {0} at this time.", Name);
}
}
}
}

View File

@@ -0,0 +1,578 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
private PvPBattleRegion _BattleRegion;
private PvPSpectateRegion _SpectateRegion;
private bool _FloorItemDelete = true;
private int _LightLevel = 100;
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleRegion BattleRegion
{
get => _BattleRegion;
set
{
if (_BattleRegion == value)
{
return;
}
_BattleRegion = value;
if (!Deserializing)
{
InvalidateBattleRegion();
}
}
}
[CommandProperty(AutoPvP.Access)]
public virtual PvPSpectateRegion SpectateRegion
{
get => _SpectateRegion;
set
{
if (_SpectateRegion == value)
{
return;
}
_SpectateRegion = value;
if (!Deserializing)
{
InvalidateSpectateRegion();
}
}
}
[CommandProperty(AutoPvP.Access)]
public virtual bool FloorItemDelete
{
get => _BattleRegion == null ? _FloorItemDelete : (_FloorItemDelete = _BattleRegion.FloorItemDelete);
set => _FloorItemDelete = _BattleRegion == null ? value : (_BattleRegion.FloorItemDelete = value);
}
[CommandProperty(AutoPvP.Access)]
public virtual int LightLevel { get => _LightLevel; set => _LightLevel = Math.Max(0, Math.Min(100, value)); }
[CommandProperty(AutoPvP.Access)]
public virtual string BattleRegionName => String.Format("{0} ({1})", Name, Serial);
[CommandProperty(AutoPvP.Access)]
public virtual string SpectateRegionName => String.Format("{0} (Safe) ({1})", Name, Serial);
public virtual void InvalidateRegions()
{
if (Deserializing)
{
return;
}
InvalidateBattleRegion();
InvalidateSpectateRegion();
}
public virtual void InvalidateBattleRegion()
{
if (Deserializing)
{
return;
}
if (_BattleRegion != null)
{
if (_BattleRegion.Map == Map &&
_BattleRegion.Area.GetBoundsHashCode() == Options.Locations.BattleBounds.GetBoundsHashCode())
{
return;
}
_BattleRegion.Unregister();
}
if (Options.Locations.BattleFixedPoint == Point3D.Zero)
{
_BattleRegion = null;
return;
}
_BattleRegion = _BattleRegion != null ? _BattleRegion.Clone(this) : RegionExtUtility.Create<PvPBattleRegion>(this);
if (_BattleRegion == null)
{
return;
}
_BattleRegion.GoLocation = Options.Locations.BattleFixedPoint;
_BattleRegion.Register();
}
public virtual void InvalidateSpectateRegion()
{
if (Deserializing)
{
return;
}
if (_SpectateRegion != null)
{
if (_SpectateRegion.Map == Map && _SpectateRegion.Area.GetBoundsHashCode() ==
Options.Locations.SpectateBounds.GetBoundsHashCode())
{
return;
}
_SpectateRegion.Unregister();
}
if (Options.Locations.SpectateFixedPoint == Point3D.Zero)
{
_SpectateRegion = null;
return;
}
_SpectateRegion = _SpectateRegion != null
? _SpectateRegion.Clone(this)
: RegionExtUtility.Create<PvPSpectateRegion>(this);
if (_SpectateRegion == null)
{
return;
}
_SpectateRegion.GoLocation = Options.Locations.SpectateFixedPoint;
_SpectateRegion.Register();
}
public virtual int NotorietyHandler(Mobile source, Mobile target, out bool handled)
{
handled = false;
if (IsInternal || Hidden)
{
return BattleNotoriety.Bubble;
}
if (source == null || source.Deleted || target == null || target.Deleted)
{
return BattleNotoriety.Bubble;
}
handled = true;
if (NotoUtility.Resolve(source, target, out PlayerMobile x, out PlayerMobile y))
{
var noto = NotorietyHandler(x, y, out handled);
if (handled || noto != BattleNotoriety.Bubble)
{
return noto;
}
}
var xrs = source.InRegion(SpectateRegion);
var xrb = source.InRegion(BattleRegion);
var yrs = target.InRegion(SpectateRegion);
var yrb = target.InRegion(BattleRegion);
if (xrs || xrb || yrs || yrb)
{
return Notoriety.Invulnerable;
}
handled = false;
return BattleNotoriety.Bubble;
}
protected virtual int NotorietyHandler(PlayerMobile source, PlayerMobile target, out bool handled)
{
handled = false;
if (IsInternal || Hidden)
{
return BattleNotoriety.Bubble;
}
if (source == null || source.Deleted || target == null || target.Deleted)
{
return BattleNotoriety.Bubble;
}
if (IsParticipant(source, out var teamA) && IsParticipant(target, out var teamB))
{
handled = true;
if (!IsRunning)
{
return Notoriety.Invulnerable;
}
if (teamA == teamB)
{
if (CanDamageOwnTeam(source, target))
{
return Notoriety.Enemy;
}
return Notoriety.Ally;
}
if (CanDamageEnemyTeam(source, target))
{
return Notoriety.Enemy;
}
return Notoriety.Invulnerable;
}
return BattleNotoriety.Bubble;
}
public virtual bool AcceptsSpawnsFrom(Region region)
{
return AllowSpawn() && region != null && (region.IsPartOf(BattleRegion) || region.IsPartOf(SpectateRegion));
}
public virtual void AlterLightLevel(Mobile m, ref int global, ref int personal)
{
personal = personal != LightLevel ? LightLevel : personal;
}
public virtual void OnLocationChanged(Mobile m, Point3D oldLocation)
{
if (m == null || m.Deleted)
{
return;
}
if (m.Region != null && (m.Region.IsPartOf(SpectateRegion) || m.Region.IsPartOf(BattleRegion)))
{
CheckDismount(m);
InvalidateStray(m);
}
var pm = m as PlayerMobile;
if (pm == null)
{
return;
}
if (IsParticipant(pm, out var team) && team != null && !team.Deleted)
{
team.UpdateActivity(pm);
}
}
public virtual bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
return true;
}
public virtual void OnEnter(PvPRegion region, Mobile m)
{
if (region == null || m == null || m.Deleted)
{
return;
}
if (region.IsPartOf(BattleRegion) && m.InRegion(BattleRegion))
{
var pm = m as PlayerMobile;
if (pm != null)
{
pm.SendMessage("You have entered {0}", Name);
}
AutoPvP.InvokeEnterBattle(this, region, m);
}
else if (region.IsPartOf(SpectateRegion) && m.InRegion(SpectateRegion))
{
var pm = m as PlayerMobile;
if (pm != null)
{
pm.SendMessage("You have entered {0} spectator area.", Name);
if (!IsSpectator(pm))
{
AddSpectator(pm, false);
}
}
AutoPvP.InvokeEnterBattle(this, region, m);
}
m.Delta(MobileDelta.Noto);
}
public virtual void OnExit(PvPRegion region, Mobile m)
{
if (region == null || m == null || m.Deleted)
{
return;
}
if (region.IsPartOf(BattleRegion) && !m.InRegion(BattleRegion))
{
var pm = m as PlayerMobile;
if (pm != null)
{
if (IsParticipant(pm))
{
Quit(pm, false);
}
pm.SendMessage("You have left {0}", Name);
}
AutoPvP.InvokeExitBattle(this, region, m);
}
else if (region.IsPartOf(SpectateRegion) && !m.InRegion(SpectateRegion))
{
var pm = m as PlayerMobile;
if (pm != null)
{
pm.SendMessage("You have left {0} spectator area", Name);
if (IsSpectator(pm))
{
RemoveSpectator(pm, false);
}
}
AutoPvP.InvokeExitBattle(this, region, m);
}
m.Delta(MobileDelta.Noto);
}
public bool AllowBeneficial(Mobile m, Mobile target, out bool handled)
{
if (CheckAllowBeneficial(m, target, out handled))
{
if (handled)
{
OnAllowBeneficialAccept(m, target);
}
return true;
}
if (handled)
{
OnAllowBeneficialDeny(m, target);
}
return false;
}
public virtual bool CheckAllowBeneficial(Mobile m, Mobile target, out bool handled)
{
handled = false;
if (m == null || m.Deleted || target == null || target.Deleted)
{
return false;
}
if (Deleted || State == PvPBattleState.Internal || Hidden)
{
return false;
}
handled = true;
if (NotoUtility.Resolve(m, target, out PlayerMobile x, out PlayerMobile y))
{
if (IsParticipant(x, out var teamA) && IsParticipant(y, out var teamB))
{
if (State != PvPBattleState.Running)
{
return true;
}
if (!Options.Rules.AllowBeneficial)
{
return false;
}
if (teamA == teamB)
{
if (!CanHealOwnTeam(x, y))
{
return false;
}
}
else if (!CanHealEnemyTeam(x, y))
{
return false;
}
}
}
var xrs = m.InRegion(SpectateRegion);
var xrb = m.InRegion(BattleRegion);
var yrs = target.InRegion(SpectateRegion);
var yrb = target.InRegion(BattleRegion);
if (xrs || xrb || yrs || yrb)
{
if (xrs && yrs)
{
return true;
}
if (xrb && yrb)
{
return true;
}
return false;
}
handled = false;
return false;
}
protected virtual void OnAllowBeneficialAccept(Mobile m, Mobile target)
{ }
protected virtual void OnAllowBeneficialDeny(Mobile m, Mobile target)
{
if (m != null && !m.Deleted && target != null && !target.Deleted && m != target)
{
m.SendMessage("You can not perform beneficial actions on your target.");
}
}
public bool AllowHarmful(Mobile m, Mobile target, out bool handled)
{
if (CheckAllowHarmful(m, target, out handled))
{
if (handled)
{
OnAllowHarmfulAccept(m, target);
}
return true;
}
if (handled)
{
OnAllowHarmfulDeny(m, target);
}
return false;
}
public virtual bool CheckAllowHarmful(Mobile m, Mobile target, out bool handled)
{
handled = false;
if (m == null || m.Deleted || target == null || target.Deleted)
{
return false;
}
if (Deleted || State == PvPBattleState.Internal || Hidden)
{
return false;
}
handled = true;
if (NotoUtility.Resolve(m, target, out PlayerMobile x, out PlayerMobile y))
{
if (IsParticipant(x, out var teamA) && IsParticipant(y, out var teamB))
{
if (!Options.Rules.AllowHarmful)
{
return false;
}
if (State != PvPBattleState.Running)
{
return false;
}
if (teamA == teamB)
{
if (!CanDamageOwnTeam(x, y))
{
return false;
}
}
else if (!CanDamageEnemyTeam(x, y))
{
return false;
}
}
}
var xrs = m.InRegion(SpectateRegion);
var xrb = m.InRegion(BattleRegion);
var yrs = target.InRegion(SpectateRegion);
var yrb = target.InRegion(BattleRegion);
if (xrs || xrb || yrs || yrb)
{
if (xrs && yrs)
{
return true;
}
if (xrb && yrb)
{
return true;
}
return false;
}
handled = false;
return false;
}
protected virtual void OnAllowHarmfulAccept(Mobile m, Mobile target)
{ }
protected virtual void OnAllowHarmfulDeny(Mobile m, Mobile target)
{
if (m != null && !m.Deleted && target != null && !target.Deleted && m != target)
{
m.SendMessage("You can not perform harmful actions on your target.");
}
}
}
}

View File

@@ -0,0 +1,267 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using VitaNex.Crypto;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public sealed class PvPSerial : CryptoHashCode
{
public static CryptoHashType Algorithm = CryptoHashType.MD5;
[CommandProperty(AutoPvP.Access)]
public override string Value => base.Value.Replace("-", String.Empty);
public PvPSerial()
: this(TimeStamp.UtcNow + "+" + Utility.RandomDouble())
{ }
public PvPSerial(string seed)
: base(Algorithm, seed)
{ }
public PvPSerial(GenericReader reader)
: base(reader)
{ }
}
public abstract partial class PvPBattle
{
[CommandProperty(AutoPvP.Access, true)]
public PvPSerial Serial { get; private set; }
protected bool Deserialized { get; private set; }
protected bool Deserializing { get; private set; }
private PvPBattle(bool deserializing)
{
Deserialized = deserializing;
EnsureConstructDefaults();
}
public PvPBattle(GenericReader reader)
: this(true)
{
Deserializing = true;
Deserialize(reader);
Deserializing = false;
}
public virtual void SerializeRegion(GenericWriter w, PvPRegion r)
{
if (r != null)
{
r.Serialize(w);
}
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(10);
if (version > 5)
{
writer.WriteBlock(
w =>
{
if (version > 6)
{
Serial.Serialize(w);
}
else
{
w.WriteType(Serial, t => Serial.Serialize(w));
}
});
}
switch (version)
{
case 10:
writer.Write(Shortcut);
goto case 9;
case 9:
writer.Write(RewardTeam);
goto case 8;
case 8:
writer.Write(RequireCapacity);
goto case 7;
case 7:
case 6:
case 5:
writer.Write(Hidden);
goto case 4;
case 4:
writer.Write(_FloorItemDelete);
goto case 3;
case 3:
case 2:
writer.Write(Gate);
goto case 1;
case 1:
{
writer.Write(Category);
writer.Write(Ranked);
writer.Write(InviteWhileRunning);
}
goto case 0;
case 0:
{
if (version < 6)
{
writer.WriteBlock(w => w.WriteType(Serial, t => Serial.Serialize(w)));
}
writer.Write(DebugMode);
writer.WriteFlag(_State);
writer.Write(_Name);
writer.Write(Description);
writer.Write(AutoAssign);
writer.Write(UseTeamColors);
writer.Write(false); // IgnoreCapacity
writer.Write(_SubCommandPrefix);
writer.Write(QueueAllowed);
writer.Write(SpectateAllowed);
writer.Write(KillPoints);
writer.Write(PointsBase);
writer.Write(0.0); // PointsRankFactor
writer.Write(IdleKick);
writer.Write(IdleThreshold);
writer.WriteFlag(LastState);
writer.Write(LastStateChange);
writer.Write(_LightLevel);
writer.Write(LogoutDelay);
writer.WriteItemList(Doors, true);
writer.WriteBlock(w => w.WriteType(Options, t => Options.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Schedule, t => Schedule.Serialize(w)));
writer.WriteBlock(w => w.WriteType(BattleRegion, t => SerializeRegion(w, BattleRegion)));
writer.WriteBlock(w => w.WriteType(SpectateRegion, t => SerializeRegion(w, SpectateRegion)));
writer.WriteBlockList(Teams, (w, team) => w.WriteType(team, t => team.Serialize(w)));
}
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var v = reader.GetVersion();
if (v > 5)
{
Serial = reader.ReadBlock(r => v > 6 ? new PvPSerial(r) : r.ReadTypeCreate<PvPSerial>(r)) ?? new PvPSerial();
}
switch (v)
{
case 10:
Shortcut = reader.ReadString();
goto case 9;
case 9:
RewardTeam = reader.ReadBool();
goto case 8;
case 8:
RequireCapacity = reader.ReadBool();
goto case 7;
case 7:
case 6:
case 5:
Hidden = reader.ReadBool();
goto case 4;
case 4:
_FloorItemDelete = reader.ReadBool();
goto case 3;
case 3:
case 2:
{
Gate = reader.ReadItem<PvPSpectatorGate>();
if (Gate != null)
{
Gate.Battle = this;
}
}
goto case 1;
case 1:
{
Category = reader.ReadString();
Ranked = reader.ReadBool();
InviteWhileRunning = reader.ReadBool();
}
goto case 0;
case 0:
{
if (v < 6)
{
Serial = reader.ReadBlock(r => r.ReadTypeCreate<PvPSerial>(r)) ?? new PvPSerial();
}
DebugMode = reader.ReadBool();
_State = reader.ReadFlag<PvPBattleState>();
_Name = reader.ReadString();
Description = reader.ReadString();
AutoAssign = reader.ReadBool();
UseTeamColors = reader.ReadBool();
reader.ReadBool(); // IgnoreCapacity
_SubCommandPrefix = reader.ReadChar();
QueueAllowed = reader.ReadBool();
SpectateAllowed = reader.ReadBool();
KillPoints = v < 3 ? (reader.ReadBool() ? 1 : 0) : reader.ReadInt();
PointsBase = reader.ReadInt();
reader.ReadDouble(); //PointsRankFactor
IdleKick = reader.ReadBool();
IdleThreshold = reader.ReadTimeSpan();
LastState = reader.ReadFlag<PvPBattleState>();
LastStateChange = reader.ReadDateTime();
_LightLevel = reader.ReadInt();
LogoutDelay = reader.ReadTimeSpan();
Doors.AddRange(reader.ReadStrongItemList<BaseDoor>());
Options = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleOptions>(r)) ?? new PvPBattleOptions();
if (Schedule != null && Schedule.Running)
{
Schedule.Stop();
}
Schedule = reader.ReadBlock(r => r.ReadTypeCreate<Schedule>(r)) ?? new Schedule(Name, false);
if (Schedule.Name != Name && Name != null)
{
Schedule.Name = Name;
}
BattleRegion = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleRegion>(this, r));
SpectateRegion = reader.ReadBlock(r => r.ReadTypeCreate<PvPSpectateRegion>(this, r));
Teams = reader.ReadBlockList(r => r.ReadTypeCreate<PvPTeam>(this, r), Teams);
}
break;
}
}
}
}

View File

@@ -0,0 +1,94 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public void SendGlobalSound(int soundID)
{
if (!Options.Sounds.Enabled || soundID <= 0)
{
return;
}
foreach (var m in GetLocalBroadcastList())
{
SendSound(m, soundID);
}
}
public void SendSound(int soundID)
{
if (Options.Sounds.Enabled && soundID > 0)
{
ForEachTeam(t => SendSound(t, soundID));
}
}
public void SendSound(PvPTeam t, int soundID)
{
if (Options.Sounds.Enabled && t != null && !t.Deleted && soundID > 0)
{
t.SendSound(soundID);
}
}
public virtual void SendSound(Mobile m, int soundID)
{
if (Options.Sounds.Enabled && m != null && !m.Deleted && soundID > 0)
{
m.SendSound(soundID);
}
}
public void PlayGlobalSound(int soundID)
{
if (!Options.Sounds.Enabled || soundID <= 0)
{
return;
}
foreach (var m in GetLocalBroadcastList())
{
PlaySound(m, soundID);
}
}
public void PlaySound(int soundID)
{
if (Options.Sounds.Enabled && soundID > 0)
{
ForEachTeam(t => PlaySound(t, soundID));
}
}
public void PlaySound(PvPTeam t, int soundID)
{
if (Options.Sounds.Enabled && t != null && !t.Deleted && soundID > 0)
{
t.PlaySound(soundID);
}
}
public virtual void PlaySound(Mobile m, int soundID)
{
if (Options.Sounds.Enabled && m != null && !m.Deleted && soundID > 0)
{
m.PlaySound(soundID);
}
}
}
}

View File

@@ -0,0 +1,118 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
using Server.Regions;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public List<PlayerMobile> Spectators { get; private set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool SpectateAllowed { get; set; }
public IEnumerable<PlayerMobile> GetSpectators()
{
return Spectators;
}
public void AddSpectator(PlayerMobile pm, bool teleport)
{
if (pm == null || pm.Deleted)
{
return;
}
if (!CanSpectate(pm))
{
OnSpectateReject(pm);
return;
}
Spectators.Add(pm);
if (teleport)
{
RecordBounce(pm);
Teleport(pm, Options.Locations.SpectateJoin, Options.Locations.Map);
}
OnSpectatorAdded(pm);
}
public void RemoveSpectator(PlayerMobile pm, bool teleport)
{
if (!IsSpectator(pm))
{
return;
}
Spectators.Remove(pm);
if (teleport)
{
var bounce = BounceInfo.GetValue(pm);
if (bounce != null && !bounce.InternalOrZero)
{
Teleport(pm, bounce, bounce);
BounceInfo.Remove(pm);
}
else
{
Teleport(pm, Options.Locations.Eject, Options.Locations.Eject);
}
}
OnSpectatorRemoved(pm);
}
public virtual bool CanSpectate(PlayerMobile pm)
{
return SpectateAllowed && State != PvPBattleState.Internal && pm != null && !pm.Deleted && pm.Alive &&
(pm.Region == null || !pm.Region.IsPartOf<Jail>()) && IsOnline(pm) && !InCombat(pm) && !InOtherBattle(pm);
}
public bool IsSpectator(PlayerMobile pm)
{
return Spectators.Contains(pm);
}
protected virtual void OnSpectatorAdded(PlayerMobile pm)
{
if (pm != null && !pm.Deleted)
{
pm.SendMessage("You have been granted a front-row seat.");
}
}
protected virtual void OnSpectatorRemoved(PlayerMobile pm)
{ }
protected virtual void OnSpectateReject(PlayerMobile pm)
{
if (pm != null && !pm.Deleted && IsSpectator(pm))
{
pm.SendMessage("You can not spectate {0} at this time.", Name);
}
}
}
}

View File

@@ -0,0 +1,486 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPBattleState
{
Internal,
Queueing,
Preparing,
Running,
Ended
}
public abstract partial class PvPBattle
{
private bool _StateTransition;
private PvPBattleState _State = PvPBattleState.Internal;
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleState State
{
get => _State;
set
{
if (_State == value)
{
return;
}
var oldState = _State;
_State = value;
if (!Deserializing)
{
OnStateChanged(oldState);
}
}
}
[CommandProperty(AutoPvP.Access, true)]
public virtual PvPBattleState LastState { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public virtual DateTime LastStateChange { get; private set; }
[CommandProperty(AutoPvP.Access)]
public bool IsInternal => State == PvPBattleState.Internal;
[CommandProperty(AutoPvP.Access)]
public bool IsQueueing => State == PvPBattleState.Queueing;
[CommandProperty(AutoPvP.Access)]
public bool IsPreparing => State == PvPBattleState.Preparing;
[CommandProperty(AutoPvP.Access)]
public bool IsRunning => State == PvPBattleState.Running;
[CommandProperty(AutoPvP.Access)]
public bool IsEnded => State == PvPBattleState.Ended;
public void InvalidateState()
{
if (_StateTransition || Deleted || Hidden || IsInternal)
{
return;
}
var state = State;
var reset = false;
switch (state)
{
case PvPBattleState.Queueing:
{
if (CanPrepareBattle(ref reset))
{
state = PvPBattleState.Preparing;
}
}
break;
case PvPBattleState.Preparing:
{
if (CanStartBattle(ref reset))
{
state = PvPBattleState.Running;
}
else if (!reset && GetStateTimeLeft(state) <= TimeSpan.Zero)
{
state = PvPBattleState.Ended;
}
}
break;
case PvPBattleState.Running:
{
if (CanEndBattle(ref reset))
{
state = PvPBattleState.Ended;
}
}
break;
case PvPBattleState.Ended:
{
if (CanOpenBattle(ref reset))
{
state = PvPBattleState.Queueing;
}
}
break;
}
if (reset)
{
Options.Timing.SetTime(State, DateTime.UtcNow);
}
State = state;
}
protected virtual void OnStateChanged(PvPBattleState oldState)
{
_StateTransition = true;
LastState = oldState;
if (IsInternal)
{
Options.Timing.SetAllTimes(DateTime.MinValue);
OnBattleInternalized();
}
else
{
if (LastState == PvPBattleState.Internal)
{
InvalidateRegions();
}
Options.Timing.SetTime(State, DateTime.UtcNow);
switch (State)
{
case PvPBattleState.Queueing:
OnBattleOpened();
break;
case PvPBattleState.Preparing:
OnBattlePreparing();
break;
case PvPBattleState.Running:
OnBattleStarted();
break;
case PvPBattleState.Ended:
OnBattleEnded();
break;
}
}
LastStateChange = DateTime.UtcNow;
_StateTransition = false;
AutoPvP.InvokeBattleStateChanged(this);
PvPBattlesUI.RefreshAll(this);
}
protected bool CanOpenBattle(ref bool timeReset)
{
if (!IsEnded)
{
return false;
}
if (GetStateTimeLeft(PvPBattleState.Ended) > TimeSpan.Zero)
{
return false;
}
return true;
}
protected bool CanPrepareBattle(ref bool timeReset)
{
if (!IsQueueing)
{
return false;
}
if (GetStateTimeLeft(PvPBattleState.Queueing) > TimeSpan.Zero)
{
return false;
}
if (!RequireCapacity || Queue.Count >= MinCapacity)
{
return true;
}
if (Schedule == null || !Schedule.Enabled || Schedule.NextGlobalTick == null)
{
timeReset = true;
}
return false;
}
protected bool CanStartBattle(ref bool timeReset)
{
if (!IsPreparing)
{
return false;
}
if (GetStateTimeLeft(PvPBattleState.Preparing) > TimeSpan.Zero)
{
return false;
}
if (Teams.All(t => t.IsReady()))
{
return true;
}
if (Schedule == null || !Schedule.Enabled || Schedule.NextGlobalTick == null)
{
timeReset = true;
}
return false;
}
protected bool CanEndBattle(ref bool timeReset)
{
if (!IsRunning)
{
return false;
}
if (GetStateTimeLeft(PvPBattleState.Running) <= TimeSpan.Zero)
{
return true;
}
if (!InviteWhileRunning && !HasCapacity())
{
return true;
}
if (Teams.All(t => !t.RespawnOnDeath && !t.IsAlive))
{
return true;
}
if (CheckMissions())
{
return true;
}
return false;
}
protected virtual void OnBattleInternalized()
{
if (LastState == PvPBattleState.Running)
{
OnBattleCancelled();
}
Reset();
foreach (var p in AutoPvP.Profiles.Values.Where(p => p != null && !p.Deleted && p.IsSubscribed(this)))
{
p.Unsubscribe(this);
}
PvPBattlesUI.RefreshAll(this);
}
protected virtual void OnBattleOpened()
{
Hidden = false;
if (Options.Broadcasts.World.OpenNotify)
{
WorldBroadcast("{0} is queueing volunteers!", Name);
}
if (Options.Broadcasts.Local.OpenNotify)
{
LocalBroadcast("{0} is queueing volunteers!", Name);
}
SendGlobalSound(Options.Sounds.BattleOpened);
Reset();
ForEachTeam(t => t.OnBattleOpened());
if (LastState == PvPBattleState.Internal)
{
foreach (var p in AutoPvP.Profiles.Values.Where(p => p != null && !p.Deleted && !p.IsSubscribed(this)))
{
p.Subscribe(this);
}
}
PvPBattlesUI.RefreshAll(this);
}
protected virtual void OnBattlePreparing()
{
Hidden = false;
if (Options.Broadcasts.World.StartNotify)
{
WorldBroadcast("{0} is preparing!", Name);
}
if (Options.Broadcasts.Local.StartNotify)
{
LocalBroadcast("{0} is preparing!", Name);
}
SendGlobalSound(Options.Sounds.BattlePreparing);
ForEachTeam(t => t.OnBattlePreparing());
PvPBattlesUI.RefreshAll(this);
}
protected virtual void OnBattleStarted()
{
Hidden = false;
if (Options.Broadcasts.World.StartNotify)
{
WorldBroadcast("{0} has begun!", Name);
}
if (Options.Broadcasts.Local.StartNotify)
{
LocalBroadcast("{0} has begun!", Name);
}
SendGlobalSound(Options.Sounds.BattleStarted);
OpendDoors(true);
ForEachTeam(t => t.OnBattleStarted());
PvPBattlesUI.RefreshAll(this);
}
protected virtual void OnBattleEnded()
{
if (LastState == PvPBattleState.Preparing)
{
OnBattleCancelled();
}
Hidden = false;
if (Options.Broadcasts.World.EndNotify)
{
WorldBroadcast("{0} has ended!", Name);
}
if (Options.Broadcasts.Local.EndNotify)
{
LocalBroadcast("{0} has ended!", Name);
}
SendGlobalSound(Options.Sounds.BattleEnded);
CloseDoors(true);
ProcessRanks();
ForEachTeam(t => t.OnBattleEnded());
TransferStatistics();
PvPBattlesUI.RefreshAll(this);
}
protected virtual void OnBattleCancelled()
{
Hidden = false;
if (Options.Broadcasts.World.EndNotify)
{
WorldBroadcast("{0} has been cancelled!", Name);
}
if (Options.Broadcasts.Local.EndNotify)
{
LocalBroadcast("{0} has been cancelled!", Name);
}
SendGlobalSound(Options.Sounds.BattleCanceled);
CloseDoors(true);
if (!Deleted && !IsInternal && QueueAllowed)
{
ForEachTeam(t => t.ForEachMember(o => Queue[o] = t));
}
ForEachTeam(t => t.OnBattleCancelled());
}
public TimeSpan GetStateTimeLeft()
{
return GetStateTimeLeft(DateTime.UtcNow);
}
public TimeSpan GetStateTimeLeft(DateTime when)
{
return GetStateTimeLeft(when, State);
}
public TimeSpan GetStateTimeLeft(PvPBattleState state)
{
return GetStateTimeLeft(DateTime.UtcNow, state);
}
public virtual TimeSpan GetStateTimeLeft(DateTime when, PvPBattleState state)
{
var time = 0.0;
switch (state)
{
case PvPBattleState.Queueing:
{
time = (Options.Timing.OpenedWhen.Add(Options.Timing.QueuePeriod) - when).TotalSeconds;
if (Schedule != null && Schedule.Enabled)
{
if (Schedule.CurrentGlobalTick != null)
{
time = (Schedule.CurrentGlobalTick.Value - when).TotalSeconds;
}
else if (Schedule.NextGlobalTick != null)
{
time = (Schedule.NextGlobalTick.Value - when).TotalSeconds;
}
}
}
break;
case PvPBattleState.Preparing:
time = (Options.Timing.PreparedWhen.Add(Options.Timing.PreparePeriod) - when).TotalSeconds;
break;
case PvPBattleState.Running:
time = (Options.Timing.StartedWhen.Add(Options.Timing.RunningPeriod) - when).TotalSeconds;
break;
case PvPBattleState.Ended:
time = (Options.Timing.EndedWhen.Add(Options.Timing.EndedPeriod) - when).TotalSeconds;
break;
}
if (time > 0)
{
return TimeSpan.FromSeconds(time);
}
return TimeSpan.Zero;
}
}
}

View File

@@ -0,0 +1,149 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
[CommandProperty(AutoPvP.Access)]
public virtual bool Ranked { get; set; }
public long GetStatistic(PlayerMobile pm, Func<PvPProfileHistoryEntry, long> fetch)
{
if (pm == null || fetch == null)
{
return 0;
}
return Teams.Aggregate(0L, (v, t) => v + GetStatistic(t, pm, fetch));
}
public long GetStatistic(PvPTeam t, PlayerMobile pm, Func<PvPProfileHistoryEntry, long> fetch)
{
if (t == null || t.Deleted || pm == null || fetch == null)
{
return 0;
}
var s = t.GetStatistics(pm);
if (s != null)
{
return VitaNexCore.TryCatchGet(fetch, s, AutoPvP.CMOptions.ToConsole);
}
return 0;
}
public bool UpdateStatistics(PvPTeam t, PlayerMobile pm, Action<PvPProfileHistoryEntry> update)
{
if (t == null || t.Deleted || pm == null || update == null)
{
return false;
}
var s = t.GetStatistics(pm);
if (s == null)
{
return false;
}
var success = true;
VitaNexCore.TryCatch(
update,
s,
x =>
{
AutoPvP.CMOptions.ToConsole(x);
success = false;
});
if (t.IsMember(pm))
{
t.UpdateActivity(pm);
}
return success;
}
public void ResetStatistics()
{
ForEachTeam(ResetStatistics);
}
public void ResetStatistics(PvPTeam t)
{
if (t != null)
{
t.Statistics.Clear();
}
}
private void TransferStatistics()
{
ForEachTeam(TransferStatistics);
}
private void TransferStatistics(PvPTeam t)
{
if (t != null)
{
t.Statistics.ForEachReverse(o => TransferStatistics(o.Key, o.Value));
}
}
private void TransferStatistics(PlayerMobile pm, PvPProfileHistoryEntry e)
{
var profile = AutoPvP.EnsureProfile(pm);
OnTransferStatistics(profile, e);
OnTransferPoints(profile, e.Points);
}
protected virtual void OnTransferStatistics(PvPProfile profile, PvPProfileHistoryEntry stats)
{
if (Ranked && profile != null && stats != null)
{
stats.AddTo(profile.Statistics, true);
}
}
protected virtual void OnTransferPoints(PvPProfile profile, long points)
{
if (!Ranked || profile == null || points == 0)
{
return;
}
profile.RawPoints += points;
if (IsOnline(profile.Owner))
{
profile.Owner.SendMessage(
"You have {0} {1:#,0} Battle Point{2} from {3}!",
points > 0 ? "gained" : "lost",
points,
points != 1 ? "s" : String.Empty,
Name);
}
}
}
}

View File

@@ -0,0 +1,503 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleCommandState
{
public virtual PvPBattle Battle { get; protected set; }
public virtual PlayerMobile Mobile { get; protected set; }
public virtual string Command { get; protected set; }
public virtual string Speech { get; protected set; }
public virtual string[] Args { get; protected set; }
public PvPBattleCommandState(PvPBattle battle, PlayerMobile from, string command, string[] args)
{
Battle = battle;
Mobile = from;
Command = command;
Args = args;
Speech = String.Join(" ", args);
}
}
public class PvPBattleCommandInfo
{
public virtual string Command { get; protected set; }
public virtual string Usage { get; set; }
public virtual string Description { get; set; }
public virtual AccessLevel Access { get; set; }
public virtual Func<PvPBattleCommandState, bool> Handler { get; set; }
public PvPBattleCommandInfo(
string command,
string desc,
string usage,
AccessLevel access,
Func<PvPBattleCommandState, bool> handler)
{
Command = command;
Description = desc;
Usage = usage;
Access = access;
Handler = handler;
}
}
public abstract partial class PvPBattle
{
private char _SubCommandPrefix = '@';
[CommandProperty(AutoPvP.Access)]
public virtual char SubCommandPrefix
{
get
{
if (!Char.IsSymbol(_SubCommandPrefix))
{
_SubCommandPrefix = '@';
}
return _SubCommandPrefix;
}
set
{
if (!Char.IsSymbol(value))
{
value = '@';
}
_SubCommandPrefix = value;
}
}
public Dictionary<string, PvPBattleCommandInfo> SubCommandHandlers { get; private set; }
protected virtual void RegisterSubCommands()
{
RegisterSubCommand(
"help",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
foreach (var ci in SubCommandHandlers.Keys.Select(cmd => SubCommandHandlers[cmd])
.Where(ci => state.Mobile.AccessLevel >= ci.Access))
{
state.Mobile.SendMessage("{0}{1} {2}", SubCommandPrefix, ci.Command, ci.Usage);
}
return true;
},
"Displays a list of available commands for this battle.",
"[?]",
AccessLevel.Player);
RegisterSubCommandAlias("help", "commands");
RegisterSubCommand(
"battle",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
LocalBroadcast("[{0}]: {1}", state.Mobile.RawName, state.Speech);
return true;
},
"Broadcasts a message to all battle participants and spectators.",
"<message>",
AccessLevel.Player);
RegisterSubCommandAlias("battle", "b");
RegisterSubCommand(
"team",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
if (!IsParticipant(state.Mobile, out var team))
{
state.Mobile.SendMessage("You must be a participant to use that command.");
return true;
}
if (team == null || team.Deleted)
{
state.Mobile.SendMessage("You are not a member of a team.");
return true;
}
team.Broadcast("[{0}]: {1}", state.Mobile.RawName, state.Speech);
return true;
},
"Sends a message to your team.",
"<message>",
AccessLevel.Player);
RegisterSubCommandAlias("team", "t");
RegisterSubCommand(
"join",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
if (IsParticipant(state.Mobile))
{
state.Mobile.SendMessage("You are already participating in this battle.");
return true;
}
if (IsQueued(state.Mobile))
{
state.Mobile.SendMessage("You are already queued for this battle.");
return true;
}
Enqueue(state.Mobile);
return true;
},
"Joins the queue for the battle.",
"",
AccessLevel.Player);
RegisterSubCommandAlias("join", "j");
RegisterSubCommand(
"leave",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
Quit(state.Mobile, true);
return true;
},
"Removes you from the battle.",
"",
AccessLevel.Player);
RegisterSubCommandAlias("leave", "quit");
RegisterSubCommand(
"time",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
var timeLeft = GetStateTimeLeft(DateTime.UtcNow);
if (timeLeft > TimeSpan.Zero)
{
var time = timeLeft.ToSimpleString(@"h\:m\:s");
var nextState = "";
switch (State)
{
case PvPBattleState.Queueing:
nextState = "Preparation";
break;
case PvPBattleState.Preparing:
nextState = "Start";
break;
case PvPBattleState.Running:
nextState = "End";
break;
case PvPBattleState.Ended:
nextState = "Open";
break;
}
state.Mobile.SendMessage("Battle is currently {0}. Time left until {1}: {2}", State.ToString(), nextState, time);
}
else
{
state.Mobile.SendMessage("Time unavailable.");
}
return true;
},
"Displays the amount of time left until the next battle state.",
"",
AccessLevel.Player);
RegisterSubCommand(
"menu",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
new PvPBattleUI(state.Mobile, battle: this).Send();
return true;
},
"Opens the interface for this battle.",
"",
AccessLevel.Player);
RegisterSubCommand(
"config",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
state.Mobile.SendGump(new PropertiesGump(state.Mobile, this));
return true;
},
"Opens the configuration for this battle.");
RegisterSubCommand(
"scores",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
var stats = new StringBuilder();
ForEachTeam(
t =>
{
stats.AppendLine("Team: {0}", t.Name);
stats.AppendLine();
t.GetHtmlStatistics(state.Mobile, stats);
stats.AppendLine();
});
new NoticeDialogGump(state.Mobile)
{
Width = 600,
Height = 400,
Title = "Battle Statistics",
Html = stats.ToString()
}.Send();
return true;
},
"Display the statistics for all teams.");
RegisterSubCommand(
"hidden",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
Hidden = !Hidden;
return true;
},
"Toggle the battle visiblility.");
RegisterSubCommand(
"state",
state =>
{
if (state == null || state.Mobile == null || state.Mobile.Deleted)
{
return false;
}
var oldState = State;
if (!Validate())
{
State = PvPBattleState.Internal;
state.Mobile.SendMessage("This battle has failed validation and has been internalized.");
}
else
{
Hidden = false;
switch (State)
{
case PvPBattleState.Internal:
State = PvPBattleState.Queueing;
break;
case PvPBattleState.Queueing:
State = PvPBattleState.Preparing;
break;
case PvPBattleState.Preparing:
State = PvPBattleState.Running;
break;
case PvPBattleState.Running:
State = PvPBattleState.Ended;
break;
case PvPBattleState.Ended:
State = PvPBattleState.Queueing;
break;
}
}
if (State != oldState)
{
state.Mobile.SendMessage("The state of the battle has been changed to {0}", State.ToString());
return true;
}
return false;
},
"Toggles the state of the current battle.");
}
public void RegisterSubCommand(
string command,
Func<PvPBattleCommandState, bool> handler,
string desc = "",
string usage = "",
AccessLevel access = AutoPvP.Access)
{
if (!String.IsNullOrWhiteSpace(command) && handler != null)
{
RegisterSubCommand(new PvPBattleCommandInfo(command, desc, usage, access, handler));
}
}
public void RegisterSubCommand(PvPBattleCommandInfo info)
{
if (info != null)
{
SubCommandHandlers[info.Command] = info;
}
}
public void RegisterSubCommandAlias(string command, params string[] alias)
{
if (!IsCommand(command))
{
return;
}
var info = SubCommandHandlers[command];
foreach (var cmd in alias)
{
RegisterSubCommand(cmd, info.Handler, info.Description, info.Usage, info.Access);
}
}
public bool HandleSubCommand(PlayerMobile pm, string speech)
{
if (pm == null || pm.Deleted || String.IsNullOrWhiteSpace(speech))
{
return false;
}
speech = speech.Trim();
if (!speech.StartsWith(SubCommandPrefix.ToString(CultureInfo.InvariantCulture)))
{
return false;
}
var command = String.Empty;
var args = new string[0];
speech = speech.TrimStart(SubCommandPrefix);
var split = speech.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (split.Length > 0)
{
command = split[0];
args = new string[split.Length - 1];
for (var i = 0; i < args.Length; i++)
{
args[i] = split[i + 1];
}
}
if (!IsCommand(command))
{
pm.SendMessage("Command not found.");
return true;
}
var info = SubCommandHandlers[command];
if (pm.AccessLevel < info.Access)
{
pm.SendMessage("You do not have access to that command.");
return true;
}
if (args.Length > 0 && (args[0] == "?" || Insensitive.Equals(args[0], "help")))
{
pm.SendMessage("Usage: {0}{1} {2}", SubCommandPrefix, info.Command, info.Usage);
pm.SendMessage(info.Description);
return true;
}
var state = new PvPBattleCommandState(this, pm, command, args);
if (info.Handler.Invoke(state))
{
OnCommand(state);
return true;
}
pm.SendMessage("Usage: {0}{1} {2}", SubCommandPrefix, info.Command, info.Usage);
pm.SendMessage(info.Description);
return true;
}
public bool IsCommand(string command)
{
return !String.IsNullOrWhiteSpace(command) && SubCommandHandlers.ContainsKey(command);
}
protected virtual void OnCommand(PvPBattleCommandState state)
{ }
}
}

View File

@@ -0,0 +1,629 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Mobiles;
using Server.Spells.Fifth;
using VitaNex.Collections;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public List<PvPTeam> Teams { get; private set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool AutoAssign { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool UseTeamColors { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool UseIncognito { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool RequireCapacity { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool RewardTeam { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int MinCapacity => GetMinCapacity();
[CommandProperty(AutoPvP.Access)]
public virtual int MaxCapacity => GetMaxCapacity();
[CommandProperty(AutoPvP.Access)]
public virtual int CurrentCapacity => GetCurrentCapacity();
[CommandProperty(AutoPvP.Access)]
public virtual bool IsFull => (CurrentCapacity >= MaxCapacity);
public int GetMinCapacity()
{
return Teams.Aggregate(0, (v, t) => v + t.MinCapacity);
}
public int GetMaxCapacity()
{
return Teams.Aggregate(0, (v, t) => v + t.MaxCapacity);
}
public int GetCurrentCapacity()
{
return Teams.Aggregate(0, (v, t) => v + t.Count);
}
public bool HasCapacity()
{
return HasCapacity(0);
}
public bool HasCapacity(int min)
{
if (min <= 0)
{
return CurrentCapacity > 1;
}
if (!RequireCapacity)
{
return true;
}
return CurrentCapacity >= min;
}
public virtual bool AddTeam(string name, int capacity, int color)
{
return AddTeam(name, 0, capacity, color);
}
public virtual bool AddTeam(string name, int minCapacity, int capacity, int color)
{
return AddTeam(new PvPTeam(this, name, minCapacity, capacity, color));
}
public virtual bool AddTeam(PvPTeam team)
{
if (!ContainsTeam(team))
{
Teams.Add(team);
OnTeamAdded(team);
return true;
}
return false;
}
public bool RemoveTeam(PvPTeam team)
{
if (Teams.Remove(team))
{
OnTeamRemoved(team);
return true;
}
return false;
}
public bool ContainsTeam(PvPTeam team)
{
return Teams.Contains(team);
}
public void ResetTeam(PvPTeam team)
{
if (team != null && !team.Deleted)
{
team.Reset();
}
}
public void ForEachTeam(Action<PvPTeam> action)
{
Teams.ForEachReverse(
t =>
{
if (t != null && !t.Deleted)
{
action(t);
}
else
{
Teams.Remove(t);
}
});
}
public void ForEachTeam<T>(Action<T> action)
where T : PvPTeam
{
Teams.ForEachReverse(
t =>
{
if (t != null && !t.Deleted)
{
if (t is T)
{
action((T)t);
}
}
else
{
Teams.Remove(t);
}
});
}
public virtual bool CanDamageOwnTeam(PlayerMobile damager, PlayerMobile target)
{
return Options.Rules.CanDamageOwnTeam && State == PvPBattleState.Running;
}
public virtual bool CanDamageEnemyTeam(PlayerMobile damager, PlayerMobile target)
{
return Options.Rules.CanDamageEnemyTeam && State == PvPBattleState.Running;
}
public virtual bool CanHealOwnTeam(PlayerMobile healer, PlayerMobile target)
{
return Options.Rules.CanHealOwnTeam && (State == PvPBattleState.Preparing || State == PvPBattleState.Running);
}
public virtual bool CanHealEnemyTeam(PlayerMobile healer, PlayerMobile target)
{
return Options.Rules.CanHealEnemyTeam && (State == PvPBattleState.Preparing || State == PvPBattleState.Running);
}
public virtual IEnumerable<PvPTeam> GetTeams()
{
return Teams.Where(t => t != null && !t.Deleted);
}
public virtual IOrderedEnumerable<PvPTeam> GetTeamsRanked()
{
return Teams.Where(t => t != null && !t.Deleted).Order();
}
public virtual int CompareTeam(PvPTeam a, PvPTeam b)
{
if (ReferenceEquals(a, b))
{
return 0;
}
var result = 0;
if (a.CompareNull(b, ref result))
{
return result;
}
return a.CompareTo(b);
}
public virtual int CountAliveTeams()
{
return Teams.Count(t => t.Dead.Count < t.Count);
}
public virtual IEnumerable<PvPTeam> GetAliveTeams()
{
return Teams.Where(t => t != null && !t.Deleted && t.Dead.Count < t.Count);
}
public virtual PvPTeam GetMostEmptyTeam()
{
return Teams.Where(t => t != null && !t.Deleted).Lowest(t => t.Count);
}
public virtual PvPTeam GetMostFullTeam()
{
return Teams.Where(t => t != null && !t.Deleted).Lowest(t => t.Count);
}
public virtual PvPTeam GetRandomTeam()
{
return Teams.Where(t => t != null && !t.Deleted).GetRandom();
}
public virtual PvPTeam GetAutoAssignTeam(PlayerMobile pm)
{
if (pm == null || pm.Deleted)
{
return null;
}
if (IsParticipant(pm, out var team) && team != null && !team.Deleted)
{
return team;
}
return Teams.OrderBy(GetAssignPriority).FirstOrDefault();
}
public virtual double GetAssignPriority(PvPTeam team)
{
GetAssignPriority(team, out var weight);
return weight;
}
protected virtual void GetAssignPriority(PvPTeam team, out double weight)
{
if (team == null || team.Deleted)
{
weight = Double.MaxValue;
return;
}
if (team.IsEmpty)
{
weight = Double.MinValue;
return;
}
weight = team.Aggregate(0.0, (v, m) => v + (m.SkillsTotal * m.RawStatTotal));
}
public PvPTeam FindTeam(PlayerMobile pm)
{
return FindTeam<PvPTeam>(pm);
}
public T FindTeam<T>(PlayerMobile pm)
where T : PvPTeam
{
return pm != null ? Teams.OfType<T>().FirstOrDefault(t => t.IsMember(pm)) : null;
}
public virtual void TeamRespawn(PvPTeam team)
{
if (team != null && !team.Deleted)
{
team.ForEachMember(team.Respawn);
}
}
public virtual void TeamEject(PvPTeam team)
{
if (team != null && !team.Deleted)
{
team.ForEachMember(member => team.RemoveMember(member, true));
}
}
public virtual void OnTeamInit(PvPTeam team)
{ }
public virtual void OnTeamSync(PvPTeam team)
{ }
public virtual void OnTeamMicroSync(PvPTeam team)
{ }
public virtual void OnTeamAdded(PvPTeam team)
{ }
public virtual void OnTeamRemoved(PvPTeam team)
{ }
public virtual void OnTeamFrozen(PvPTeam team)
{ }
public virtual void OnTeamUnfrozen(PvPTeam team)
{ }
public virtual void OnTeamMemberFrozen(PvPTeam team, PlayerMobile pm)
{ }
public virtual void OnTeamMemberUnfrozen(PvPTeam team, PlayerMobile pm)
{ }
public virtual void OnTeamMemberDeath(PvPTeam team, PlayerMobile pm)
{
LocalBroadcast("{0} has died.", pm.RawName);
UpdateStatistics(team, pm, s => ++s.Deaths);
var pk = pm.FindMostRecentDamager(false) as PlayerMobile;
if (pk != null && !pk.Deleted)
{
if (IsParticipant(pk, out var pkt))
{
if (KillPoints > 0 && !pk.Account.IsSharedWith(pm.Account))
{
RevokePoints(pm, KillPoints);
}
pm.LastKiller = pk;
UpdateStatistics(pkt, pk, s => ++s.Kills);
if (KillPoints > 0 && !pk.Account.IsSharedWith(pm.Account))
{
AwardPoints(pk, KillPoints);
}
}
}
TeleportToHomeBase(team, pm);
}
public virtual void OnAfterTeamMemberDeath(PvPTeam team, PlayerMobile pm)
{
RefreshStats(pm, true, true);
if (!TryKickOnDeath(team, pm, true) && !TryRespawnOnDeath(team, pm, true))
{
TeleportToHomeBase(team, pm);
team.Respawn(pm, false);
}
}
public virtual void OnTeamMemberResurrected(PvPTeam team, PlayerMobile pm)
{
UpdateStatistics(team, pm, s => ++s.Resurrections);
}
public virtual void OnAfterTeamMemberResurrected(PvPTeam team, PlayerMobile pm)
{
team.Dead.Remove(pm);
}
public virtual void OnTeamMemberAdded(PvPTeam team, PlayerMobile pm)
{
team.Broadcast("{0} has joined the battle.", pm.RawName);
if (UseTeamColors)
{
pm.SolidHueOverride = team.Color;
}
if (UseIncognito)
{
pm.BeginAction(typeof(IncognitoSpell));
pm.NameMod = NameList.RandomName(pm.Female ? "female" : "male");
var race = pm.Race ?? Race.DefaultRace;
pm.BodyMod = race.Body(pm);
pm.HueMod = race.RandomSkinHue();
pm.SetHairMods(race.RandomHair(pm.Female), race.RandomFacialHair(pm.Female));
}
}
public virtual void OnTeamMemberRemoved(PvPTeam team, PlayerMobile pm)
{
team.Broadcast("{0} has left the battle.", pm.RawName);
pm.SolidHueOverride = -1;
pm.EndAction(typeof(IncognitoSpell));
pm.NameMod = null;
pm.BodyMod = 0;
pm.HueMod = -1;
pm.SetHairMods(-1, -1);
}
public virtual bool TryKickOnDeath(PvPTeam team, PlayerMobile pm, bool isLoss)
{
if (team.KickOnDeath)
{
if (isLoss)
{
OnLose(pm);
}
team.RemoveMember(pm, true);
return true;
}
return false;
}
public virtual bool TryRespawnOnDeath(PvPTeam team, PlayerMobile pm, bool isDelayed)
{
if (team.RespawnOnDeath)
{
if (isDelayed && team.RespawnDelay > TimeSpan.Zero)
{
Timer.DelayCall(team.RespawnDelay, team.Respawn, pm);
}
else
{
team.Respawn(pm);
}
return true;
}
return false;
}
protected virtual void ProcessRanks()
{
if (Options.Missions.Enabled)
{
ProcessMissionRanks();
}
else if (RewardTeam)
{
ProcessTeamRanks(1);
}
else
{
ProcessPlayerRanks(1);
}
}
protected virtual void ProcessMissionRanks()
{
var players = ListPool<PlayerMobile>.AcquireObject();
players.AddRange(GetParticipants());
if (CheckMissions(out var team, out var player))
{
if (team != null)
{
WorldBroadcast("{0} has won {1}!", team.Name, Name);
team.ForEachMember(OnWin);
players.RemoveAll(team.IsMember);
}
else if (player != null)
{
WorldBroadcast("{0} has won {1}!", player.Name, Name);
OnWin(player);
players.Remove(player);
}
}
foreach (var p in players)
{
OnLose(p);
}
ObjectPool.Free(ref players);
}
protected virtual void ProcessTeamRanks(int limit)
{
if (limit <= 0)
{
return;
}
var teams = GetTeams().Where(t => !t.IsEmpty).ToLookup(GetScore, o => o);
if (teams.Count <= 0)
{
return;
}
bool win;
foreach (var o in teams.OrderByDescending(o => o.Key))
{
win = limit > 0 && o.Key > 0 && o.Any() && --limit >= 0;
foreach (var team in o)
{
if (win)
{
WorldBroadcast("{0} has won {1}!", team.Name, Name);
team.ForEachMember(OnWin);
}
else
{
team.ForEachMember(OnLose);
}
}
}
}
protected virtual void ProcessPlayerRanks(int limit)
{
if (limit <= 0)
{
return;
}
var players = GetParticipants().ToLookup(GetScore, o => o);
if (players.Count <= 0)
{
return;
}
bool win;
foreach (var o in players.OrderByDescending(o => o.Key))
{
win = limit > 0 && o.Key > 0 && o.Any() && --limit >= 0;
foreach (var player in o)
{
if (win)
{
WorldBroadcast("{0} has won {1}!", player.Name, Name);
OnWin(player);
}
else
{
OnLose(player);
}
}
}
}
protected double GetScore(PvPTeam team)
{
if (team != null)
{
return team.GetScore();
}
return 0;
}
protected double GetMissionsScore(PvPTeam team)
{
if (team != null)
{
return team.GetMissionsScore();
}
return 0;
}
protected double GetScore(PlayerMobile pm)
{
if (Options.Missions.Enabled)
{
return GetMissionsScore(pm);
}
return GetStatistic(pm, e => e.Points);
}
public double GetMissionsScore(PlayerMobile pm)
{
if (Options.Missions.Enabled)
{
return Options.Missions.ComputeScore(this, pm);
}
return 0;
}
}
}

View File

@@ -0,0 +1,228 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
public bool Validate(Mobile viewer = null)
{
return Validate(viewer, new List<string>());
}
public virtual bool Validate(Mobile viewer, List<string> errors, bool pop = true)
{
if (Deleted)
{
errors.Add("This battle has been deleted.");
return false;
}
if (String.IsNullOrWhiteSpace(Name))
{
errors.Add("Select a valid Name.");
errors.Add("[Options] -> [Edit Options]");
if (pop)
{
return false;
}
}
if (String.IsNullOrWhiteSpace(Description))
{
errors.Add("Select a valid Description.");
errors.Add("[Options] -> [Edit Options]");
if (pop)
{
return false;
}
}
if (SpectateAllowed)
{
if (SpectateRegion == null)
{
errors.Add("Select a valid Spectate Region.");
errors.Add("[Options] -> [Edit Spectage Region]");
if (pop)
{
return false;
}
}
else if (Options.Locations.SpectateBounds.Count == 0)
{
errors.Add("The Spectate Region has no zones.");
errors.Add("[Options] -> [Edit Spectage Region]");
if (pop)
{
return false;
}
}
}
if (BattleRegion == null)
{
errors.Add("Select a valid Battle Region.");
errors.Add("[Options] -> [Edit Battle Region]");
if (pop)
{
return false;
}
}
else if (Options.Locations.BattleBounds.Count == 0)
{
errors.Add("The Battle Region has no zones.");
errors.Add("[Options] -> [Edit Battle Region]");
if (pop)
{
return false;
}
}
if (Options.Locations.Map == Map.Internal)
{
errors.Add("The Battle Map must not be Internal.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
if (Options.Locations.Eject.Internal)
{
errors.Add("The Eject Map must not be Internal.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
if (Options.Locations.Eject == Point3D.Zero)
{
errors.Add("Select a valid Eject Location.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
else if (BattleRegion != null &&
BattleRegion.Contains(Options.Locations.Eject.Location, Options.Locations.Eject.Map))
{
errors.Add("Eject Location must be outside the Battle Region.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
if (SpectateAllowed)
{
if (Options.Locations.SpectateJoin == Point3D.Zero)
{
errors.Add("Select a valid Spectator Join location.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
else if (SpectateRegion != null && !SpectateRegion.Contains(Options.Locations.SpectateJoin))
{
errors.Add("Spectate Join Location must be within the Spectate Region.");
errors.Add("[Options] -> [Edit Advanced Options] -> [Locations]");
if (pop)
{
return false;
}
}
}
if (Schedule == null)
{
errors.Add("No Schedule has been set for this battle.");
errors.Add("[Options] -> [View Schedule]");
if (pop)
{
return false;
}
}
else if (Schedule.Enabled && Schedule.NextGlobalTick == null)
{
errors.Add("The Schedule has no more future dates.");
errors.Add("[Options] -> [View Schedule]");
if (pop)
{
return false;
}
}
if (IdleKick && IdleThreshold.TotalSeconds < 10.0)
{
errors.Add("The Idle Threshold must be greater than, or equal to 10 seconds.");
errors.Add("[Options] -> [Edit Options]");
if (pop)
{
return false;
}
}
if (Teams.Count == 0)
{
errors.Add("There are no teams available for this Battle.");
errors.Add("[Options] -> [View Teams]");
if (pop)
{
return false;
}
}
else if (Teams.Any(t => !t.Validate(viewer)))
{
errors.Add("One or more teams did not pass validation.");
errors.Add("[Options] -> [View Teams]");
if (pop)
{
return false;
}
}
return errors.Count == 0;
}
}
}

View File

@@ -0,0 +1,190 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#if ServUO58
#define ServUOX
#endif
#region References
using System;
using System.Linq;
using System.Threading.Tasks;
using Server;
using Server.Movement;
using VitaNex.FX;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public abstract partial class PvPBattle
{
private static readonly PvPBattleWeatherDirection[] _WeatherDirections = ((PvPBattleWeatherDirection)0)
.GetValues<PvPBattleWeatherDirection>()
.Not(d => d == PvPBattleWeatherDirection.None || d == PvPBattleWeatherDirection.Random)
.ToArray();
public virtual bool CanUseWeather()
{
if (Options.Locations.BattleBounds == null || Options.Locations.BattleBounds.Count == 0 ||
Options.Locations.Map == Map.Internal)
{
return false;
}
if (Options.Weather.Density <= 0 || Options.Weather.EffectID <= 0 || Options.Weather.EffectSpeed <= 0)
{
return false;
}
if (Options.Weather.Force)
{
return true;
}
if (!Options.Weather.Enabled || State == PvPBattleState.Internal)
{
return false;
}
#if ServUOX
if (BattleRegion != null && BattleRegion.MobileCount == 0)
#else
if (BattleRegion != null && BattleRegion.GetMobileCount() == 0)
#endif
{
return false;
}
if (!Options.SuddenDeath.Enabled || !Options.SuddenDeath.Active)
{
return false;
}
if (DateTime.UtcNow - Options.SuddenDeath.StartedWhen < Options.SuddenDeath.Delay)
{
return false;
}
return true;
}
public virtual Point3D GetWeatherStartPoint(Point3D loc, PvPBattleWeatherDirection direction)
{
if (!Options.Weather.Enabled || Options.Locations.Map == null || Options.Locations.Map == Map.Internal ||
loc == Point3D.Zero)
{
return loc;
}
switch (direction)
{
case PvPBattleWeatherDirection.None:
return loc.Clone3D(0, 0, 80);
case PvPBattleWeatherDirection.Random:
direction = _WeatherDirections.GetRandom(PvPBattleWeatherDirection.None);
break;
}
int x = 0, y = 0;
Movement.Offset((Direction)direction, ref x, ref y);
var rand = Utility.RandomMinMax(4, 8);
return loc.Clone3D(x * rand, y * rand, 80);
}
protected virtual void WeatherCycle()
{
if (!CanUseWeather())
{
return;
}
Point3D start, end;
Parallel.ForEach(
Options.Locations.BattleBounds,
b =>
{
end = b.Start.Clone2D(Utility.Random(b.Width), Utility.Random(b.Height)).GetWorldTop(Options.Locations.Map);
start = GetWeatherStartPoint(end, Options.Weather.Direction);
new MovingEffectInfo(
start,
end,
Options.Locations.Map,
Options.Weather.EffectID,
Options.Weather.EffectHue,
Options.Weather.EffectSpeed,
Options.Weather.EffectRender,
TimeSpan.FromMilliseconds(Utility.Random(500))).MovingImpact(WeatherImpactHandler);
});
}
protected virtual void WeatherImpactHandler(MovingEffectInfo info)
{
if (info == null || Deleted || !Options.Weather.Impacts || Options.Weather.ImpactEffectID <= 0 ||
Options.Weather.ImpactEffectSpeed <= 0 || Options.Weather.ImpactEffectDuration <= 0)
{
return;
}
OnWeatherImpact(info);
if (Options.Weather.ImpactEffectID <= 0)
{
return;
}
var effect = new EffectInfo(
info.Target,
info.Map,
Options.Weather.ImpactEffectID,
Options.Weather.ImpactEffectHue,
Options.Weather.ImpactEffectSpeed,
Options.Weather.ImpactEffectDuration,
Options.Weather.ImpactEffectRender);
effect.Send();
OnWeatherImpact(effect);
}
protected virtual void OnWeatherImpact(MovingEffectInfo info)
{ }
protected virtual void OnWeatherImpact(EffectInfo info)
{
if (info == null || Deleted || !Options.Weather.Impacts)
{
return;
}
if (Options.Weather.ImpactEffectSound > 0)
{
Effects.PlaySound(info.Source, info.Map, Options.Weather.ImpactEffectSound);
}
if (!Options.SuddenDeath.Enabled || !Options.SuddenDeath.Active || !Options.SuddenDeath.Damages)
{
return;
}
foreach (var pm in info.Source.GetPlayersInRange(info.Map, Options.SuddenDeath.DamageRange))
{
Options.SuddenDeath.Damage(pm);
}
}
}
}

View File

@@ -0,0 +1,412 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Server;
using Server.Mobiles;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPProfile : IEnumerable<PvPProfileHistoryEntry>
{
[CommandProperty(AutoPvP.Access)]
public bool Deleted { get; private set; }
[CommandProperty(AutoPvP.Access)]
public PlayerMobile Owner { get; private set; }
private long _Points;
[CommandProperty(AutoPvP.Access)]
public long RawPoints { get => _Points; set => _Points = Math.Max(0, value); }
[CommandProperty(AutoPvP.Access)]
public long Points
{
get => RawPoints;
set
{
var oldVal = RawPoints;
RawPoints = value;
if (oldVal != RawPoints)
{
OnPointsChanged(oldVal);
}
}
}
[CommandProperty(AutoPvP.Access)]
public List<PvPBattle> Subscriptions { get; private set; }
[CommandProperty(AutoPvP.Access)]
public long TotalDamageTaken => GetTotalDamageTaken();
[CommandProperty(AutoPvP.Access)]
public long TotalDamageDone => GetTotalDamageDone();
[CommandProperty(AutoPvP.Access)]
public long TotalHealingTaken => GetTotalHealingTaken();
[CommandProperty(AutoPvP.Access)]
public long TotalHealingDone => GetTotalHealingDone();
[CommandProperty(AutoPvP.Access)]
public long TotalDeaths => GetTotalDeaths();
[CommandProperty(AutoPvP.Access)]
public long TotalResurrections => GetTotalResurrections();
[CommandProperty(AutoPvP.Access)]
public long TotalKills => GetTotalKills();
[CommandProperty(AutoPvP.Access)]
public long TotalPointsGained => GetTotalPointsGained();
[CommandProperty(AutoPvP.Access)]
public long TotalPointsLost => GetTotalPointsLost();
[CommandProperty(AutoPvP.Access)]
public long TotalPoints => TotalPointsGained - TotalPointsLost;
[CommandProperty(AutoPvP.Access)]
public long TotalWins => GetTotalWins();
[CommandProperty(AutoPvP.Access)]
public long TotalLosses => GetTotalLosses();
[CommandProperty(AutoPvP.Access)]
public long TotalBattles => GetTotalBattles();
[CommandProperty(AutoPvP.Access)]
public virtual PvPProfileHistory History { get; set; }
[CommandProperty(AutoPvP.Access)]
public PvPProfileHistoryEntry Statistics => History.EnsureEntry();
public PvPProfile(PlayerMobile owner)
{
Owner = owner;
History = new PvPProfileHistory(this);
Subscriptions = new List<PvPBattle>();
SubscribeAllBattles();
}
public PvPProfile(GenericReader reader)
{
Deserialize(reader);
}
public void SubscribeAllBattles()
{
foreach (var battle in AutoPvP.GetBattles())
{
Subscribe(battle);
}
}
public bool IsSubscribed(PvPBattle battle)
{
return battle != null && !battle.Deleted && Subscriptions.Contains(battle);
}
public void Subscribe(PvPBattle battle)
{
if (battle != null && !battle.Deleted && !battle.IsInternal)
{
Subscriptions.Update(battle);
}
}
public void Unsubscribe(PvPBattle battle)
{
if (battle != null && !battle.Deleted)
{
Subscriptions.Remove(battle);
}
}
protected virtual void OnPointsChanged(long oldVal)
{
if (_Points > oldVal)
{
OnPointsGained(_Points - oldVal);
}
else if (_Points < oldVal)
{
OnPointsLost(oldVal - _Points);
}
}
protected virtual void OnPointsGained(long value)
{
Statistics.PointsGained += value;
Owner.SendMessage("You have gained {0:#,0} Battle Point{1}!", value, value != 1 ? "s" : String.Empty);
}
protected virtual void OnPointsLost(long value)
{
Statistics.PointsLost += value;
Owner.SendMessage("You have lost {0:#,0} Battle Point{1}!", value, value != 1 ? "s" : String.Empty);
}
public long GetTotalDamageTaken()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.DamageTaken);
}
public long GetTotalDamageDone()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.DamageDone);
}
public long GetTotalHealingTaken()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.HealingTaken);
}
public long GetTotalHealingDone()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.HealingDone);
}
public long GetTotalResurrections()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Resurrections);
}
public long GetTotalDeaths()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Deaths);
}
public long GetTotalKills()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Kills);
}
public long GetTotalPointsGained()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.PointsGained);
}
public long GetTotalPointsLost()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.PointsLost);
}
public long GetTotalWins()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Wins);
}
public long GetTotalLosses()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Losses);
}
public long GetTotalBattles()
{
return History.Values.Aggregate(0L, (c, entry) => c + entry.Battles);
}
public IEnumerable<KeyValuePair<string, long>> GetMiscStatisticTotals()
{
return History.Values.SelectMany(e => e.MiscStats)
.ToLookup(o => o.Key, o => o.Value)
.Select(o => new KeyValuePair<string, long>(o.Key, o.Aggregate(0L, (c, v) => c + v)));
}
public void Remove()
{
if (AutoPvP.RemoveProfile(this))
{
OnRemoved();
}
}
public void Delete()
{
if (Deleted)
{
return;
}
Deleted = true;
Remove();
History = null;
OnDeleted();
}
protected virtual void OnDeleted()
{ }
protected virtual void OnRemoved()
{ }
public virtual void Init()
{ }
public string ToHtmlString(Mobile viewer = null, bool big = true)
{
var html = new StringBuilder();
if (big)
{
html.Append("<BIG>");
}
GetHtmlString(viewer, html);
if (big)
{
html.Append("</BIG>");
}
return html.ToString();
}
public virtual void GetHtmlString(Mobile viewer, StringBuilder html)
{
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
if (Deleted)
{
html.Append("<B>This profile has been deleted.</B>");
return;
}
html.AppendLine("<B>PvP Profile for {0}</B>", Owner.RawName);
html.AppendLine();
html.Append("".WrapUOHtmlColor(Color.YellowGreen, false));
html.AppendLine("<B>Statistics</B>");
html.AppendLine();
html.AppendLine("* Overall Points: {0}", _Points.ToString("#,0"));
html.AppendLine();
Statistics.GetHtmlString(viewer, html);
html.Append("".WrapUOHtmlColor(Color.Cyan, false));
html.AppendLine("<B>Statisctics For All Seasons:</B>");
html.AppendLine();
html.AppendLine("<B>Main Statistic Totals</B>");
html.AppendLine();
html.AppendLine("* Battles Attended: {0}", TotalBattles.ToString("#,0"));
html.AppendLine("* Battles Won: {0}", TotalWins.ToString("#,0"));
html.AppendLine("* Battles Lost: {0}", TotalLosses.ToString("#,0"));
html.AppendLine("* Points Gained: {0}", TotalPointsGained.ToString("#,0"));
html.AppendLine("* Points Lost: {0}", TotalPointsLost.ToString("#,0"));
html.AppendLine("* Kills: {0}", TotalKills.ToString("#,0"));
html.AppendLine("* Deaths: {0}", TotalDeaths.ToString("#,0"));
html.AppendLine("* Resurrections: {0}", TotalResurrections.ToString("#,0"));
html.AppendLine("* Damage Taken: {0}", TotalDamageTaken.ToString("#,0"));
html.AppendLine("* Damage Done: {0}", TotalDamageDone.ToString("#,0"));
html.AppendLine("* Healing Taken: {0}", TotalHealingTaken.ToString("#,0"));
html.AppendLine("* Healing Done: {0}", TotalHealingDone.ToString("#,0"));
html.AppendLine();
html.Append("".WrapUOHtmlColor(Color.GreenYellow, false));
html.AppendLine("<B>Misc Statistic Totals</B>");
html.AppendLine();
foreach (var kvp in GetMiscStatisticTotals())
{
html.AppendLine("* {0}: {1}", kvp.Key, kvp.Value.ToString("#,0"));
}
html.AppendLine();
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
}
public IEnumerator<PvPProfileHistoryEntry> GetEnumerator()
{
return History.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
writer.Write(Deleted);
writer.Write(Owner);
switch (version)
{
case 0:
{
writer.Write(_Points);
writer.WriteBlock(w => w.WriteType(History, t => History.Serialize(w)));
writer.WriteBlockList(Subscriptions, (w, b) => w.WriteType(b.Serial, t => b.Serial.Serialize(w)));
}
break;
}
}
public void Deserialize(GenericReader reader)
{
var version = reader.ReadInt();
Deleted = reader.ReadBool();
Owner = reader.ReadMobile<PlayerMobile>();
switch (version)
{
case 0:
{
_Points = reader.ReadLong();
History = reader.ReadBlock(r => r.ReadTypeCreate<PvPProfileHistory>(this, r)) ?? new PvPProfileHistory(this);
Subscriptions = reader.ReadBlockList(
r =>
{
var serial = r.ReadTypeCreate<PvPSerial>(r) ?? new PvPSerial(r);
return AutoPvP.FindBattleByID(serial);
},
Subscriptions);
}
break;
}
}
}
}

View File

@@ -0,0 +1,119 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPProfileHistory
{
public PvPProfile Profile { get; private set; }
public Dictionary<int, PvPProfileHistoryEntry> Entries { get; private set; }
public Dictionary<int, PvPProfileHistoryEntry>.KeyCollection Keys => Entries.Keys;
public Dictionary<int, PvPProfileHistoryEntry>.ValueCollection Values => Entries.Values;
private PvPProfileHistory(PvPProfile owner)
{
Profile = owner;
}
public PvPProfileHistory(PvPProfile owner, params PvPProfileHistoryEntry[] entries)
: this(owner)
{
if (entries == null)
{
Entries = new Dictionary<int, PvPProfileHistoryEntry>();
}
else
{
Entries = new Dictionary<int, PvPProfileHistoryEntry>(entries.Length);
foreach (var entry in entries)
{
var season = AutoPvP.EnsureSeason(entry.Season);
if (season != null)
{
Entries[season.Number] = entry;
}
}
}
}
public PvPProfileHistory(PvPProfile owner, IDictionary<int, PvPProfileHistoryEntry> dictionary)
: this(owner)
{
Entries = new Dictionary<int, PvPProfileHistoryEntry>(dictionary);
}
public PvPProfileHistory(PvPProfile owner, GenericReader reader)
: this(owner)
{
Deserialize(reader);
}
public virtual PvPProfileHistoryEntry EnsureEntry(bool replace = false)
{
return EnsureEntry(AutoPvP.CurrentSeason, replace);
}
public virtual PvPProfileHistoryEntry EnsureEntry(PvPSeason season, bool replace = false)
{
if (!Entries.TryGetValue(season.Number, out var entry) || entry == null || replace)
{
Entries[season.Number] = entry = new PvPProfileHistoryEntry(season.Number);
}
return entry;
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlockDictionary(Entries, (w, k, e) => w.WriteType(e, t => e.Serialize(w)));
}
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Entries = reader.ReadBlockDictionary(
r =>
{
var e = r.ReadTypeCreate<PvPProfileHistoryEntry>(r);
return new KeyValuePair<int, PvPProfileHistoryEntry>(e.Season, e);
},
Entries);
}
break;
}
}
}
}

View File

@@ -0,0 +1,404 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using Server;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPProfileHistoryEntry : PropertyObject, IEquatable<PvPProfileHistoryEntry>
{
[CommandProperty(AutoPvP.Access)]
public PvPSerial UID { get; private set; }
[CommandProperty(AutoPvP.Access, true)]
public int Season { get; private set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Battles { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Wins { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Losses { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long PointsGained { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long PointsLost { get; set; }
[CommandProperty(AutoPvP.Access)]
public long Points => PointsGained - PointsLost;
[CommandProperty(AutoPvP.Access)]
public virtual long DamageTaken { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long DamageDone { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long HealingTaken { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long HealingDone { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Kills { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Deaths { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual long Resurrections { get; set; }
public virtual Dictionary<string, long> MiscStats { get; protected set; }
public virtual long this[string stat]
{
get => MiscStats.GetValue(stat);
set
{
if (String.IsNullOrWhiteSpace(stat))
{
return;
}
if (MiscStats.ContainsKey(stat))
{
if (value < 0)
{
MiscStats.Remove(stat);
}
else
{
MiscStats[stat] = value;
}
}
else if (value >= 0)
{
MiscStats[stat] = value;
}
}
}
public PvPProfileHistoryEntry(int season)
{
Season = season;
UID = new PvPSerial(Season + "~" + TimeStamp.UtcNow + "~" + Utility.RandomDouble());
MiscStats = new Dictionary<string, long>();
}
public PvPProfileHistoryEntry(GenericReader reader)
: base(reader)
{ }
public virtual void SetDefaults()
{
Battles = 0;
Wins = 0;
Losses = 0;
PointsGained = 0;
PointsLost = 0;
DamageTaken = 0;
DamageDone = 0;
HealingTaken = 0;
HealingDone = 0;
Kills = 0;
Deaths = 0;
Resurrections = 0;
MiscStats.Clear();
}
public override void Clear()
{
SetDefaults();
}
public override void Reset()
{
SetDefaults();
}
public virtual long GetMiscStat(string stat)
{
return this[stat];
}
public virtual void SetMiscStat(string stat, long value)
{
this[stat] = value;
}
public void MergeFrom(PvPProfileHistoryEntry e, bool points)
{
if (e != null)
{
e.MergeTo(this, points);
}
}
public void MergeTo(PvPProfileHistoryEntry e, bool points)
{
if (e == null)
{
return;
}
AddTo(e, points);
Battles = 0;
Wins = 0;
Losses = 0;
if (points)
{
PointsGained = 0;
PointsLost = 0;
}
DamageTaken = 0;
DamageDone = 0;
HealingTaken = 0;
HealingDone = 0;
Kills = 0;
Deaths = 0;
Resurrections = 0;
MiscStats.Clear();
}
public void TakeFrom(PvPProfileHistoryEntry e, bool points)
{
if (e != null)
{
e.AddTo(this, points);
}
}
public void AddTo(PvPProfileHistoryEntry e, bool points)
{
if (e == null)
{
return;
}
e.Battles += Battles;
e.Wins += Wins;
e.Losses += Losses;
if (points)
{
e.PointsGained += PointsGained;
e.PointsLost += PointsLost;
}
e.DamageTaken += DamageTaken;
e.DamageDone += DamageDone;
e.HealingTaken += HealingTaken;
e.HealingDone += HealingDone;
e.Kills += Kills;
e.Deaths += Deaths;
e.Resurrections += Resurrections;
foreach (var o in MiscStats)
{
e[o.Key] += o.Value;
}
}
public string ToHtmlString(bool big)
{
return ToHtmlString(null, big);
}
public string ToHtmlString(Mobile viewer, bool big)
{
var sb = new StringBuilder();
if (big)
{
sb.Append("<BIG>");
}
GetHtmlString(viewer, sb);
if (big)
{
sb.Append("</BIG>");
}
return sb.ToString();
}
public virtual void GetHtmlString(Mobile viewer, StringBuilder html)
{
html.Append(String.Empty.WrapUOHtmlColor(Color.Cyan, false));
html.AppendLine("Statistics For Season: {0:#,0}".WrapUOHtmlBold(), Season);
html.AppendLine();
html.AppendLine("Statistics:".WrapUOHtmlBold());
html.AppendLine();
html.AppendLine("Battles Attended: {0:#,0}", Battles);
html.AppendLine("Battles Won: {0:#,0}", Wins);
html.AppendLine("Battles Lost: {0:#,0}", Losses);
html.AppendLine();
html.AppendLine("Points Total: {0:#,0}", Points);
html.AppendLine("Points Gained: {0:#,0}", PointsGained);
html.AppendLine("Points Lost: {0:#,0}", PointsLost);
html.AppendLine();
html.AppendLine("Kills: {0:#,0}", Kills);
html.AppendLine("Deaths: {0:#,0}", Deaths);
html.AppendLine("Resurrections: {0:#,0}", Resurrections);
html.AppendLine("Damage Taken: {0:#,0}", DamageTaken);
html.AppendLine("Damage Given: {0:#,0}", DamageDone);
html.AppendLine("Healing Taken: {0:#,0}", HealingTaken);
html.AppendLine("Healing Given: {0:#,0}", HealingDone);
html.AppendLine();
html.Append(String.Empty.WrapUOHtmlColor(Color.GreenYellow, false));
html.AppendLine("Misc Statistics:");
foreach (var kvp in MiscStats)
{
html.AppendLine("{0}: {1:#,0}", kvp.Key, kvp.Value);
}
html.AppendLine();
html.Append(String.Empty.WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
}
public override sealed int GetHashCode()
{
return UID.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is PvPProfileHistoryEntry && Equals((PvPProfileHistoryEntry)obj);
}
public virtual bool Equals(PvPProfileHistoryEntry other)
{
return !ReferenceEquals(other, null) && UID == other.UID;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
UID.Serialize(writer);
switch (version)
{
case 1:
case 0:
{
writer.Write(Season);
writer.Write(DamageTaken);
writer.Write(DamageDone);
writer.Write(HealingTaken);
writer.Write(HealingDone);
writer.Write(Kills);
writer.Write(Deaths);
writer.Write(Resurrections);
writer.Write(PointsGained);
writer.Write(PointsLost);
writer.Write(Wins);
writer.Write(Losses);
writer.Write(Battles);
writer.WriteBlockDictionary(
MiscStats,
(w, k, v) =>
{
w.Write(k);
w.Write(v);
});
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
UID = version > 0 ? new PvPSerial(reader) : new PvPSerial(TimeStamp.UtcNow + "~" + Utility.RandomDouble());
switch (version)
{
case 1:
case 0:
{
Season = reader.ReadInt();
DamageTaken = reader.ReadLong();
DamageDone = reader.ReadLong();
HealingTaken = reader.ReadLong();
HealingDone = reader.ReadLong();
Kills = reader.ReadLong();
Deaths = reader.ReadLong();
Resurrections = reader.ReadLong();
PointsGained = reader.ReadLong();
PointsLost = reader.ReadLong();
Wins = reader.ReadLong();
Losses = reader.ReadLong();
Battles = reader.ReadLong();
MiscStats = reader.ReadBlockDictionary(
r =>
{
var k = r.ReadString();
var v = r.ReadLong();
return new KeyValuePair<string, long>(k, v);
},
MiscStats);
}
break;
}
}
public static bool operator ==(PvPProfileHistoryEntry left, PvPProfileHistoryEntry right)
{
return ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.Equals(right);
}
public static bool operator !=(PvPProfileHistoryEntry left, PvPProfileHistoryEntry right)
{
return ReferenceEquals(left, null) ? !ReferenceEquals(right, null) : !left.Equals(right);
}
}
}

View File

@@ -0,0 +1,21 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPProfileRankOrder
{
None,
Points,
Wins,
Kills
}
}

View File

@@ -0,0 +1,604 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Regions;
using Server.Targeting;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public abstract class PvPRegion : BaseRegion
{
[CommandProperty(AutoPvP.Access)]
public PvPBattle Battle { get; set; }
public PvPRegion(PvPBattle battle, string name, params Rectangle3D[] bounds)
: base(name, battle.Options.Locations.Map, battle.Options.Locations.BattlePriority, bounds.Ensure().ZFix().ToArray())
{
Battle = battle;
}
public PvPRegion(PvPBattle battle, string name, GenericReader reader)
: this(battle, name)
{
Deserialize(reader);
}
public void MicroSync()
{
if (Battle != null)
{
OnMicroSync();
}
}
public virtual void OnMicroSync()
{ }
public override bool AllowBeneficial(Mobile from, Mobile target)
{
if (Battle != null)
{
if (NotoUtility.Resolve(from, target, out PlayerMobile x, out PlayerMobile y))
{
var result = Battle.AllowBeneficial(x, y, out var handled);
if (handled)
{
return result;
}
}
}
return base.AllowBeneficial(from, target);
}
public override bool AllowHarmful(Mobile from, IDamageable target)
{
if (target is Mobile mt)
{
return AllowHarmful(from, mt);
}
return base.AllowHarmful(from, target);
}
public virtual bool AllowHarmful(Mobile from, Mobile target)
{
if (Battle != null)
{
if (NotoUtility.Resolve(from, target, out PlayerMobile x, out PlayerMobile y))
{
var result = Battle.AllowHarmful(x, y, out var handled);
if (handled)
{
return result;
}
}
}
return base.AllowHarmful(from, target);
}
public override bool AllowHousing(Mobile from, Point3D p)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.AllowHousing(from, p))
{
return false;
}
return base.AllowHousing(from, p);
}
public override bool AllowSpawn()
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.AllowSpawn())
{
return false;
}
return base.AllowSpawn();
}
public override bool CanUseStuckMenu(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.CanUseStuckMenu(m))
{
return false;
}
return base.CanUseStuckMenu(m);
}
public override void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnAggressed(aggressor, aggressed, criminal);
}
base.OnAggressed(aggressor, aggressed, criminal);
}
public override bool AcceptsSpawnsFrom(Region region)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.AcceptsSpawnsFrom(region))
{
return false;
}
return base.AcceptsSpawnsFrom(region);
}
public override void AlterLightLevel(Mobile m, ref int global, ref int personal)
{
base.AlterLightLevel(m, ref global, ref personal);
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.AlterLightLevel(m, ref global, ref personal);
}
}
public override bool CheckAccessibility(Item item, Mobile from)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.CheckAccessibility(item, from))
{
return false;
}
return base.CheckAccessibility(item, from);
}
public override TimeSpan GetLogoutDelay(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
return Battle.GetLogoutDelay(m);
}
return base.GetLogoutDelay(m);
}
public override bool OnDecay(Item item)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnDecay(item))
{
return false;
}
return base.OnDecay(item);
}
public override bool OnBeginSpellCast(Mobile m, ISpell s)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnBeginSpellCast(m, s))
{
return false;
}
return base.OnBeginSpellCast(m, s);
}
public override void OnBeneficialAction(Mobile helper, Mobile target)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnBeneficialAction(helper, target);
}
base.OnBeneficialAction(helper, target);
}
public override bool OnCombatantChange(Mobile m, IDamageable oldC, IDamageable newC)
{
if (oldC is Mobile || newC is Mobile)
{
return OnCombatantChange(m, oldC as Mobile, newC as Mobile);
}
return base.OnCombatantChange(m, oldC, newC);
}
public virtual bool OnCombatantChange(Mobile m, Mobile oldMob, Mobile newMob)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnCombatantChange(m, oldMob, newMob))
{
return false;
}
return base.OnCombatantChange(m, oldMob, newMob);
}
public override void OnCriminalAction(Mobile m, bool message)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnCriminalAction(m, message);
}
base.OnCriminalAction(m, message);
}
public override bool OnDamage(Mobile m, ref int damage)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
if (!Battle.CheckDamage(m, ref damage))
{
return false;
}
Timer.DelayCall(d => OnDamage(m, m.GetLastDamager(true), d), damage);
return true;
}
return base.OnDamage(m, ref damage);
}
protected void OnDamage(Mobile m, IEntity damager, int damage)
{
OnDamage(m, damager as Mobile, damage);
}
protected virtual void OnDamage(Mobile m, Mobile damager, int damage)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnDamage(damager, m, damage);
}
}
public override bool OnBeforeDeath(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnBeforeDeath(m))
{
return false;
}
return base.OnBeforeDeath(m);
}
public override void OnDeath(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnDeath(m);
}
base.OnDeath(m);
}
public override void OnDidHarmful(Mobile harmer, IDamageable harmed)
{
if (harmed is Mobile mh)
{
OnDidHarmful(harmer, mh);
}
else
{
base.OnDidHarmful(harmer, harmed);
}
}
public virtual void OnDidHarmful(Mobile harmer, Mobile harmed)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnDidHarmful(harmer, harmed);
}
base.OnDidHarmful(harmer, harmed);
}
public override bool OnSingleClick(Mobile m, object o)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnSingleClick(m, o))
{
return false;
}
return base.OnSingleClick(m, o);
}
public override bool OnDoubleClick(Mobile m, object o)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnDoubleClick(m, o))
{
return false;
}
return base.OnDoubleClick(m, o);
}
public override void OnEnter(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnEnter(this, m);
}
base.OnEnter(m);
}
public override void OnExit(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnExit(this, m);
}
base.OnExit(m);
}
public override void OnGotBeneficialAction(Mobile helper, Mobile target)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnGotBeneficialAction(helper, target);
}
base.OnGotBeneficialAction(helper, target);
}
public override void OnGotHarmful(Mobile harmer, IDamageable harmed)
{
if (harmed is Mobile mh)
{
OnGotHarmful(harmer, mh);
}
else
{
base.OnGotHarmful(harmer, harmed);
}
}
public virtual void OnGotHarmful(Mobile harmer, Mobile harmed)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnGotHarmful(harmer, harmed);
}
base.OnGotHarmful(harmer, harmed);
}
public override bool OnHeal(Mobile m, ref int heal)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
if (!Battle.CheckHeal(m, ref heal))
{
return false;
}
Timer.DelayCall(h => OnHeal(m, m.GetLastHealer(true), h), heal);
return true;
}
return base.OnHeal(m, ref heal);
}
protected void OnHeal(Mobile m, IEntity healer, int heal)
{
OnHeal(m, healer as Mobile, heal);
}
protected virtual void OnHeal(Mobile m, Mobile healer, int heal)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnHeal(healer, m, heal);
}
}
public override void OnLocationChanged(Mobile m, Point3D oldLocation)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnLocationChanged(m, oldLocation);
}
base.OnLocationChanged(m, oldLocation);
}
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnMoveInto(m, d, newLocation, oldLocation))
{
return false;
}
return base.OnMoveInto(m, d, newLocation, oldLocation);
}
public override bool OnResurrect(Mobile m)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnResurrect(m))
{
return false;
}
return base.OnResurrect(m);
}
public override bool OnSkillUse(Mobile m, int skill)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnSkillUse(m, skill))
{
return false;
}
return base.OnSkillUse(m, skill);
}
public override void OnSpeech(SpeechEventArgs args)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnSpeech(args);
}
base.OnSpeech(args);
}
public override void OnSpellCast(Mobile m, ISpell s)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.OnSpellCast(m, s);
}
base.OnSpellCast(m, s);
}
public override bool OnTarget(Mobile m, Target t, object o)
{
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden && !Battle.OnTarget(m, t, o))
{
return false;
}
return base.OnTarget(m, t, o);
}
public override void SpellDamageScalar(Mobile caster, Mobile target, ref double damage)
{
base.SpellDamageScalar(caster, target, ref damage);
if (Battle != null && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
Battle.SpellDamageScalar(caster, target, ref damage);
}
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
break;
}
}
}
public class PvPBattleRegion : PvPRegion
{
[CommandProperty(AutoPvP.Access)]
public bool FloorItemDelete { get; set; }
public PvPBattleRegion(PvPBattle battle)
: base(battle, battle.BattleRegionName, battle.Options.Locations.BattleBounds.ToArray())
{ }
public PvPBattleRegion(PvPBattle battle, GenericReader reader)
: base(battle, battle.BattleRegionName, reader)
{ }
public override void OnMicroSync()
{
base.OnMicroSync();
if (FloorItemDelete && Battle.State != PvPBattleState.Internal && !Battle.Hidden)
{
var delete = Area.SelectMany(r => r.FindEntities<Item>(Map))
.Not(i => i == null || i.Deleted || i is Static || i is LOSBlocker || i is Blocker)
.Where(i => i.Movable && i.Visible && i.Decays);
foreach (var i in delete)
{
i.Delete();
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.Write(FloorItemDelete);
goto case 0;
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
FloorItemDelete = reader.ReadBool();
goto case 0;
case 0:
break;
}
}
}
public class PvPSpectateRegion : PvPRegion
{
public PvPSpectateRegion(PvPBattle battle)
: base(battle, battle.SpectateRegionName, battle.Options.Locations.SpectateBounds.ToArray())
{ }
public PvPSpectateRegion(PvPBattle battle, GenericReader reader)
: base(battle, battle.SpectateRegionName, reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,91 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public sealed class PvPScenario
{
private readonly Type _TypeOf;
private string _Info;
private string _Name;
public PvPScenario(PvPBattle battle)
{
_TypeOf = battle.GetType();
_Name = battle.Name;
_Info = battle.ToHtmlString(preview: true).Replace("(Internal)", String.Empty);
}
public Type TypeOf => _TypeOf;
public string Name
{
get => _Name;
set
{
if (!String.IsNullOrEmpty(value))
{
_Name = value;
}
}
}
public string Info
{
get => _Info;
set
{
if (!String.IsNullOrEmpty(value))
{
_Info = value;
}
}
}
public PvPBattle CreateBattle()
{
var battle = Activator.CreateInstance(_TypeOf) as PvPBattle;
foreach (var profile in AutoPvP.Profiles.Values)
{
if (!profile.IsSubscribed(battle))
{
profile.Subscribe(battle);
}
}
return battle;
}
public override string ToString()
{
return String.Format("{0}: {1}", _Name, _TypeOf);
}
public string ToHtmlString(Mobile viewer = null, bool big = true)
{
return big ? String.Format("<big>{0}</big>", _Info) : _Info;
}
public static implicit operator PvPScenario(PvPBattle battle)
{
return new PvPScenario(battle);
}
}
}

View File

@@ -0,0 +1,260 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPSeason : IComparable<PvPSeason>, IEquatable<PvPSeason>
{
public PvPSeason(int number)
{
Number = number;
Winners = new Dictionary<PlayerMobile, List<Item>>();
Losers = new Dictionary<PlayerMobile, List<Item>>();
}
public PvPSeason(GenericReader reader)
{
Deserialize(reader);
}
public int Number { get; private set; }
public DateTime? Started { get; private set; }
public DateTime? Ended { get; private set; }
public Dictionary<PlayerMobile, List<Item>> Winners { get; private set; }
public Dictionary<PlayerMobile, List<Item>> Losers { get; private set; }
public bool Active => (this == AutoPvP.CurrentSeason);
public virtual int CompareTo(PvPSeason a)
{
if (a == null)
{
return -1;
}
if (Number > a.Number)
{
return 1;
}
if (Number < a.Number)
{
return -1;
}
return 0;
}
public virtual bool Equals(PvPSeason a)
{
return a != null && (ReferenceEquals(this, a) || Number == a.Number);
}
public override int GetHashCode()
{
return Number;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public virtual void Start()
{
Started = DateTime.UtcNow;
}
public virtual void End()
{
Ended = DateTime.UtcNow;
}
public virtual void Sync()
{
if (Active && Started == null)
{
Start();
}
else if (!Active && Ended == null)
{
if (Started == null)
{
Start();
}
End();
AutoPvP.SeasonChanged(this);
}
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(1);
switch (version)
{
case 1:
{
writer.WriteBlockDictionary(
Winners,
(w, k, v) =>
{
w.Write(k);
w.WriteItemList(v, true);
});
writer.WriteBlockDictionary(
Losers,
(w, k, v) =>
{
w.Write(k);
w.WriteItemList(v, true);
});
}
goto case 0;
case 0:
{
writer.Write(Number);
if (version < 1)
{
writer.WriteMobileList(Winners.Keys.ToList(), true);
writer.WriteMobileList(Losers.Keys.ToList(), true);
}
if (Started != null)
{
writer.Write(true);
writer.Write(Started.Value);
}
else
{
writer.Write(false);
}
if (Ended != null)
{
writer.Write(true);
writer.Write(Ended.Value);
}
else
{
writer.Write(false);
}
}
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 1:
{
Winners = reader.ReadBlockDictionary(
r =>
{
var k = r.ReadMobile<PlayerMobile>();
var v = r.ReadStrongItemList();
return new KeyValuePair<PlayerMobile, List<Item>>(k, v);
});
Losers = reader.ReadBlockDictionary(
r =>
{
var k = r.ReadMobile<PlayerMobile>();
var v = r.ReadStrongItemList();
return new KeyValuePair<PlayerMobile, List<Item>>(k, v);
});
}
goto case 0;
case 0:
{
Number = reader.ReadInt();
if (version < 1)
{
var winners = reader.ReadStrongMobileList<PlayerMobile>();
Winners = new Dictionary<PlayerMobile, List<Item>>(winners.Count);
winners.ForEach(m => Winners.Add(m, new List<Item>()));
var losers = reader.ReadStrongMobileList<PlayerMobile>();
Losers = new Dictionary<PlayerMobile, List<Item>>(losers.Count);
losers.ForEach(m => Losers.Add(m, new List<Item>()));
}
if (reader.ReadBool())
{
Started = reader.ReadDateTime();
}
if (reader.ReadBool())
{
Ended = reader.ReadDateTime();
}
}
break;
}
}
public override string ToString()
{
return String.Format("Season: {0}", Number);
}
public string ToHtmlString(Mobile viewer = null, bool big = true)
{
var sb = new StringBuilder();
sb.AppendLine(ToString());
sb.AppendLine();
if (Started != null)
{
sb.AppendLine("Started: {0}", Started);
}
if (Ended != null)
{
sb.AppendLine("Ended: {0}", Ended);
}
if (Winners.Count > 0)
{
sb.AppendLine("Winners");
sb.AppendLine();
Winners.Keys.For(
(i, p) => sb.AppendLine("{0}: {1}", (Numeral)(i + 1), p.Name.WrapUOHtmlColor(viewer.GetNotorietyColor(p))));
}
sb.AppendLine();
return big ? String.Format("<big>{0}</big>", sb) : sb.ToString();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleBroadcasts : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleLocalBroadcasts Local { get; protected set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleWorldBroadcasts World { get; protected set; }
public PvPBattleBroadcasts()
{
Local = new PvPBattleLocalBroadcasts();
World = new PvPBattleWorldBroadcasts();
}
public PvPBattleBroadcasts(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Broadcasts";
}
public override void Clear()
{
Local.Clear();
World.Clear();
}
public override void Reset()
{
Local.Reset();
World.Reset();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlock(w => w.WriteType(Local, t => Local.Serialize(w)));
writer.WriteBlock(w => w.WriteType(World, t => World.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlock(r => Local = r.ReadTypeCreate<PvPBattleLocalBroadcasts>(r) ?? new PvPBattleLocalBroadcasts());
reader.ReadBlock(r => World = r.ReadTypeCreate<PvPBattleWorldBroadcasts>(r) ?? new PvPBattleWorldBroadcasts());
}
break;
}
}
}
}

View File

@@ -0,0 +1,118 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPBattleLocalBroadcastMode
{
Disabled,
Broadcast
}
[PropertyObject]
public class PvPBattleLocalBroadcasts : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public PvPBattleLocalBroadcastMode Mode { get; set; }
[Hue, CommandProperty(AutoPvP.Access)]
public int MessageHue { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool OpenNotify { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool StartNotify { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool EndNotify { get; set; }
public PvPBattleLocalBroadcasts()
{
OpenNotify = true;
StartNotify = true;
EndNotify = true;
MessageHue = 85;
Mode = PvPBattleLocalBroadcastMode.Disabled;
}
public PvPBattleLocalBroadcasts(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Local Broadcasts";
}
public override void Clear()
{
OpenNotify = false;
StartNotify = false;
EndNotify = false;
MessageHue = 0;
Mode = PvPBattleLocalBroadcastMode.Disabled;
}
public override void Reset()
{
OpenNotify = true;
StartNotify = true;
EndNotify = true;
MessageHue = 85;
Mode = PvPBattleLocalBroadcastMode.Disabled;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteFlag(Mode);
writer.Write(MessageHue);
writer.Write(OpenNotify);
writer.Write(StartNotify);
writer.Write(EndNotify);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Mode = reader.ReadFlag<PvPBattleLocalBroadcastMode>();
MessageHue = reader.ReadInt();
OpenNotify = reader.ReadBool();
StartNotify = reader.ReadBool();
EndNotify = reader.ReadBool();
}
break;
}
}
}
}

View File

@@ -0,0 +1,120 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPBattleWorldBroadcastMode
{
Disabled,
Broadcast,
TownCrier,
Notify
}
[PropertyObject]
public class PvPBattleWorldBroadcasts : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public PvPBattleWorldBroadcastMode Mode { get; set; }
[Hue, CommandProperty(AutoPvP.Access)]
public int MessageHue { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool OpenNotify { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool StartNotify { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool EndNotify { get; set; }
public PvPBattleWorldBroadcasts()
{
OpenNotify = true;
StartNotify = true;
EndNotify = true;
MessageHue = 85;
Mode = PvPBattleWorldBroadcastMode.Broadcast;
}
public PvPBattleWorldBroadcasts(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "World Broadcasts";
}
public override void Clear()
{
OpenNotify = false;
StartNotify = false;
EndNotify = false;
MessageHue = 0;
Mode = PvPBattleWorldBroadcastMode.Disabled;
}
public override void Reset()
{
OpenNotify = true;
StartNotify = true;
EndNotify = true;
MessageHue = 85;
Mode = PvPBattleWorldBroadcastMode.Broadcast;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteFlag(Mode);
writer.Write(MessageHue);
writer.Write(OpenNotify);
writer.Write(StartNotify);
writer.Write(EndNotify);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Mode = reader.ReadFlag<PvPBattleWorldBroadcastMode>();
MessageHue = reader.ReadInt();
OpenNotify = reader.ReadBool();
StartNotify = reader.ReadBool();
EndNotify = reader.ReadBool();
}
break;
}
}
}
}

View File

@@ -0,0 +1,165 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleLocations : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual int BattlePriority { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual Map Map { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual Point3D SpectateJoin { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual MapPoint Eject { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual MapPoint SpectateGate { get; set; }
public virtual List<Rectangle3D> BattleBounds { get; set; }
public virtual List<Rectangle3D> SpectateBounds { get; set; }
public Point3D BattleFixedPoint => GetBattleFixedPoint();
public Point3D SpectateFixedPoint => GetSpectateFixedPoint();
public PvPBattleLocations()
{
BattlePriority = Region.DefaultPriority;
Map = Map.Internal;
Eject = MapPoint.Empty;
SpectateGate = MapPoint.Empty;
SpectateJoin = Point3D.Zero;
BattleBounds = new List<Rectangle3D>();
SpectateBounds = new List<Rectangle3D>();
}
public PvPBattleLocations(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Locations";
}
public override void Clear()
{
Map = Map.Internal;
BattlePriority = Region.DefaultPriority;
BattleBounds.Free(true);
SpectateBounds.Free(true);
SpectateJoin = Point3D.Zero;
Eject = MapPoint.Empty;
}
public override void Reset()
{
Map = Map.Internal;
BattlePriority = Region.DefaultPriority;
BattleBounds.Free(true);
SpectateBounds.Free(true);
SpectateJoin = Point3D.Zero;
Eject = MapPoint.Empty;
}
public Point3D GetBattleFixedPoint()
{
if (BattleBounds == null || BattleBounds.Count == 0)
{
return Point3D.Zero;
}
var p = BattleBounds[0].Start;
return p.ToPoint3D(Map.GetAverageZ(p.X, p.Y));
}
public Point3D GetSpectateFixedPoint()
{
if (SpectateBounds == null || SpectateBounds.Count == 0)
{
return Point3D.Zero;
}
var p = SpectateBounds[0].Start;
return p.ToPoint3D(Map.GetAverageZ(p.X, p.Y));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
SpectateGate.Serialize(writer);
goto case 0;
case 0:
{
writer.Write(Map);
writer.Write(BattlePriority);
Eject.Serialize(writer);
writer.Write(SpectateJoin);
writer.WriteBlockList(BattleBounds, (w, b) => w.Write(b));
writer.WriteBlockList(SpectateBounds, (w, b) => w.Write(b));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
SpectateGate = new MapPoint(reader);
goto case 0;
case 0:
{
Map = reader.ReadMap();
BattlePriority = reader.ReadInt();
Eject = new MapPoint(reader);
SpectateJoin = reader.ReadPoint3D();
BattleBounds = reader.ReadBlockList(r => r.ReadRect3D());
SpectateBounds = reader.ReadBlockList(r => r.ReadRect3D());
}
break;
}
}
}
}

View File

@@ -0,0 +1,183 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using System.Text;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleMissions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public bool Enabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleObjectives Team { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleObjectives Player { get; set; }
public PvPBattleMissions()
{
Enabled = false;
Team = new PvPBattleObjectives();
Player = new PvPBattleObjectives();
}
public PvPBattleMissions(GenericReader reader)
: base(reader)
{ }
public virtual double ComputeScore(PvPTeam team)
{
if (!Enabled || Team.IsEmpty)
{
return 0;
}
return Team.ComputeScore(team);
}
public virtual double ComputeScore(PvPBattle battle, PlayerMobile player)
{
if (!Enabled || Player.IsEmpty)
{
return 0;
}
return Player.ComputeScore(battle, player);
}
public virtual bool Completed(PvPTeam team)
{
if (!Enabled || Team.IsEmpty)
{
return false;
}
return Team.Completed(team);
}
public virtual bool Completed(PvPBattle battle, PlayerMobile player)
{
if (!Enabled || Player.IsEmpty)
{
return false;
}
return Player.Completed(battle, player);
}
public virtual string GetStatus(PvPTeam team)
{
if (!Enabled || Team.IsEmpty)
{
return String.Empty;
}
return Team.GetStatus(team);
}
public virtual string GetStatus(PvPBattle battle, PlayerMobile player)
{
if (!Enabled || Player.IsEmpty)
{
return String.Empty;
}
return Player.GetStatus(battle, player);
}
public virtual void GetHtmlString(StringBuilder html)
{
if (!Enabled)
{
return;
}
var idx = html.Length;
var len = html.Length;
if (!Team.IsEmpty)
{
Team.GetHtmlString(html);
if (len < html.Length)
{
html.Insert(len, "Team Objectives\n".WrapUOHtmlColor(Color.LawnGreen, false));
}
}
len = html.Length;
if (!Player.IsEmpty)
{
Player.GetHtmlString(html);
if (len < html.Length)
{
html.Insert(len, "Player Objectives\n".WrapUOHtmlColor(Color.LawnGreen, false));
}
}
if (idx < html.Length)
{
html.Insert(idx, "Missions\n".WrapUOHtmlBig().WrapUOHtmlColor(Color.PaleGoldenrod, false));
html.Append(String.Empty.WrapUOHtmlColor(Color.White, false));
}
}
public virtual string ToHtmlString()
{
var html = new StringBuilder();
GetHtmlString(html);
return html.ToString();
}
public override string ToString()
{
return "Battle Missions";
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Enabled);
writer.WriteBlock(w => w.WriteType(Team, (w1, t) => Team.Serialize(w1)));
writer.WriteBlock(w => w.WriteType(Player, (w1, t) => Player.Serialize(w1)));
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Enabled = reader.ReadBool();
Team = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleObjectives>(r)) ?? new PvPBattleObjectives();
Player = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleObjectives>(r)) ?? new PvPBattleObjectives();
}
}
}

View File

@@ -0,0 +1,643 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using System.Text;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleObjectives : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public bool AllRequired { get; set; }
[CommandProperty(AutoPvP.Access)]
public long PointsTotal { get; set; }
[CommandProperty(AutoPvP.Access)]
public long PointsGained { get; set; }
[CommandProperty(AutoPvP.Access)]
public long PointsLost { get; set; }
[CommandProperty(AutoPvP.Access)]
public long Kills { get; set; }
[CommandProperty(AutoPvP.Access)]
public long Deaths { get; set; }
[CommandProperty(AutoPvP.Access)]
public long Resurrections { get; set; }
[CommandProperty(AutoPvP.Access)]
public long DamageTaken { get; set; }
[CommandProperty(AutoPvP.Access)]
public long DamageDone { get; set; }
[CommandProperty(AutoPvP.Access)]
public long HealingTaken { get; set; }
[CommandProperty(AutoPvP.Access)]
public long HealingDone { get; set; }
public virtual bool IsEmpty => PointsTotal + PointsGained + PointsLost
+ Kills + Deaths + Resurrections
+ DamageTaken + DamageDone
+ HealingTaken + HealingDone
<= 0;
public PvPBattleObjectives()
{
SetDefaults();
}
public PvPBattleObjectives(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
base.Clear();
SetDefaults();
}
public override void Reset()
{
base.Reset();
SetDefaults();
}
public virtual void SetDefaults()
{
AllRequired = false;
PointsTotal = 0;
PointsGained = 0;
PointsLost = 0;
Kills = 0;
Deaths = 0;
Resurrections = 0;
DamageTaken = 0;
DamageDone = 0;
HealingTaken = 0;
HealingDone = 0;
}
public double ComputeScorePotential(PvPTeam t)
{
double min = 0, max = 0, total = 0;
ComputeScore(t, ref min, ref max, ref total);
return total;
}
public double ComputeScore(PvPTeam t)
{
double min = 0, max = 0, total = 0;
return ComputeScore(t, ref min, ref max, ref total);
}
public virtual double ComputeScore(PvPTeam t, ref double min, ref double max, ref double total)
{
if (t == null || t.Deleted)
{
return 0;
}
double val, score = 0.0;
if (PointsTotal > 0)
{
score += val = Math.Min(1.0, t.GetTotalPoints() / (double)PointsTotal);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (PointsGained > 0)
{
score += val = Math.Min(1.0, t.GetTotalPointsGained() / (double)PointsGained);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (PointsLost > 0)
{
score += val = Math.Min(1.0, t.GetTotalPointsLost() / (double)PointsLost);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Kills > 0)
{
score += val = Math.Min(1.0, t.GetTotalKills() / (double)Kills);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Deaths > 0)
{
score += val = Math.Min(1.0, t.GetTotalDeaths() / (double)Deaths);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Resurrections > 0)
{
score += val = Math.Min(1.0, t.GetTotalResurrections() / (double)Resurrections);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (DamageTaken > 0)
{
score += val = Math.Min(1.0, t.GetTotalDamageTaken() / (double)DamageTaken);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (DamageDone > 0)
{
score += val = Math.Min(1.0, t.GetTotalDamageDone() / (double)DamageDone);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (HealingTaken > 0)
{
score += val = Math.Min(1.0, t.GetTotalHealingTaken() / (double)HealingTaken);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (HealingDone > 0)
{
score += val = Math.Min(1.0, t.GetTotalHealingDone() / (double)HealingDone);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
return score;
}
public double ComputeScorePotential(PvPBattle b, PlayerMobile p)
{
double min = 0, max = 0, total = 0;
ComputeScore(b, p, ref min, ref max, ref total);
return total;
}
public double ComputeScore(PvPBattle b, PlayerMobile p)
{
double min = 0, max = 0, total = 0;
return ComputeScore(b, p, ref min, ref max, ref total);
}
public virtual double ComputeScore(PvPBattle b, PlayerMobile p, ref double min, ref double max, ref double total)
{
if (b == null || b.Deleted)
{
return 0;
}
if (p == null || p.Deleted)
{
return 0;
}
double val, score = 0.0;
if (PointsTotal > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.Points) / (double)PointsTotal);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (PointsGained > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.PointsGained) / (double)PointsGained);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (PointsLost > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.PointsLost) / (double)PointsLost);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Kills > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.Kills) / (double)Kills);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Deaths > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.Deaths) / (double)Deaths);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (Resurrections > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.Resurrections) / (double)Resurrections);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (DamageTaken > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.DamageTaken) / (double)DamageTaken);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (DamageDone > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.DamageDone) / (double)DamageDone);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (HealingTaken > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.HealingTaken) / (double)HealingTaken);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
if (HealingDone > 0)
{
score += val = Math.Min(1.0, b.GetStatistic(p, o => o.HealingDone) / (double)HealingDone);
min = Math.Min(min, val);
max = Math.Max(max, val);
++total;
}
return score;
}
public virtual bool Completed(PvPTeam t)
{
double min = 0, max = 0, total = 0;
var score = ComputeScore(t, ref min, ref max, ref total);
if (score <= 0 || max <= 0)
{
return false;
}
if (AllRequired)
{
return score >= total;
}
return max >= 1.0;
}
public virtual bool Completed(PvPBattle b, PlayerMobile p)
{
double min = 0, max = 0, total = 0;
var score = ComputeScore(b, p, ref min, ref max, ref total);
if (score <= 0 || total <= 0)
{
return false;
}
if (AllRequired)
{
return score >= total;
}
return max >= 1.0;
}
public virtual string GetStatus(PvPTeam t)
{
if (t == null || t.Deleted)
{
return String.Empty;
}
var lines = new StringBuilder();
if (PointsTotal > 0)
{
lines.AppendLine("Points Total: {0:#,0} / {1:#,0}", t.GetTotalPoints(), PointsTotal);
}
if (PointsGained > 0)
{
lines.AppendLine("Points Gained: {0:#,0} / {1:#,0}", t.GetTotalPointsGained(), PointsGained);
}
if (PointsLost > 0)
{
lines.AppendLine("Points Lost: {0:#,0} / {1:#,0}", t.GetTotalPointsLost(), PointsLost);
}
if (Kills > 0)
{
lines.AppendLine("Kills: {0:#,0} / {1:#,0}", t.GetTotalKills(), Kills);
}
if (Deaths > 0)
{
lines.AppendLine("Deaths: {0:#,0} / {1:#,0}", t.GetTotalDeaths(), Deaths);
}
if (Resurrections > 0)
{
lines.AppendLine("Resurrections: {0:#,0} / {1:#,0}", t.GetTotalResurrections(), Resurrections);
}
if (DamageTaken > 0)
{
lines.AppendLine("Damage Taken: {0:#,0} / {1:#,0}", t.GetTotalDamageTaken(), DamageTaken);
}
if (DamageDone > 0)
{
lines.AppendLine("Damage Done: {0:#,0} / {1:#,0}", t.GetTotalDamageDone(), DamageDone);
}
if (HealingTaken > 0)
{
lines.AppendLine("Healing Taken: {0:#,0} / {1:#,0}", t.GetTotalHealingTaken(), HealingTaken);
}
if (HealingDone > 0)
{
lines.AppendLine("Healing Done: {0:#,0} / {1:#,0}", t.GetTotalHealingDone(), HealingDone);
}
return lines.ToString();
}
public virtual string GetStatus(PvPBattle b, PlayerMobile p)
{
if (b == null || b.Deleted)
{
return String.Empty;
}
if (p == null || p.Deleted)
{
return String.Empty;
}
var lines = new StringBuilder();
if (PointsTotal > 0)
{
lines.AppendLine("Points Total: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.Points), PointsTotal);
}
if (PointsGained > 0)
{
lines.AppendLine("Points Gained: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.PointsGained), PointsGained);
}
if (PointsLost > 0)
{
lines.AppendLine("Points Lost: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.PointsLost), PointsLost);
}
if (Kills > 0)
{
lines.AppendLine("Kills: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.Kills), Kills);
}
if (Deaths > 0)
{
lines.AppendLine("Deaths: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.Deaths), Deaths);
}
if (Resurrections > 0)
{
lines.AppendLine("Resurrections: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.Resurrections), Resurrections);
}
if (DamageTaken > 0)
{
lines.AppendLine("Damage Taken: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.DamageTaken), DamageTaken);
}
if (DamageDone > 0)
{
lines.AppendLine("Damage Done: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.DamageDone), DamageDone);
}
if (HealingTaken > 0)
{
lines.AppendLine("Healing Taken: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.HealingTaken), HealingTaken);
}
if (HealingDone > 0)
{
lines.AppendLine("Healing Done: {0:#,0} / {1:#,0}", b.GetStatistic(p, o => o.HealingDone), HealingDone);
}
return lines.ToString();
}
public virtual void GetHtmlString(StringBuilder html)
{
var len = html.Length;
if (PointsTotal > 0)
{
html.AppendLine("Points Total: {0:#,0}", PointsTotal);
}
if (PointsGained > 0)
{
html.AppendLine("Points Gained: {0:#,0}", PointsGained);
}
if (PointsLost > 0)
{
html.AppendLine("Points Lost: {0:#,0}", PointsLost);
}
if (Kills > 0)
{
html.AppendLine("Kills: {0:#,0}", Kills);
}
if (Deaths > 0)
{
html.AppendLine("Deaths: {0:#,0}", Deaths);
}
if (Resurrections > 0)
{
html.AppendLine("Resurrections: {0:#,0}", Resurrections);
}
if (DamageTaken > 0)
{
html.AppendLine("Damage Taken: {0:#,0}", DamageTaken);
}
if (DamageDone > 0)
{
html.AppendLine("Damage Done: {0:#,0}", DamageDone);
}
if (HealingTaken > 0)
{
html.AppendLine("Healing Taken: {0:#,0}", HealingTaken);
}
if (HealingDone > 0)
{
html.AppendLine("Healing Done: {0:#,0}", HealingDone);
}
if (len < html.Length)
{
html.Insert(len, AllRequired ? "(Complete All)\n" : "(Complete Any)\n");
html.Insert(len, String.Empty.WrapUOHtmlColor(Color.PaleGoldenrod, false));
html.Append(String.Empty.WrapUOHtmlColor(Color.White, false));
}
}
public virtual string ToHtmlString()
{
var html = new StringBuilder();
GetHtmlString(html);
return html.ToString();
}
public override string ToString()
{
return "Mission Objectives";
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(PointsTotal);
writer.Write(PointsGained);
writer.Write(PointsLost);
writer.Write(Kills);
writer.Write(Deaths);
writer.Write(Resurrections);
writer.Write(DamageTaken);
writer.Write(DamageDone);
writer.Write(HealingTaken);
writer.Write(HealingDone);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
PointsTotal = reader.ReadLong();
PointsGained = reader.ReadLong();
PointsLost = reader.ReadLong();
Kills = reader.ReadLong();
Deaths = reader.ReadLong();
Resurrections = reader.ReadLong();
DamageTaken = reader.ReadLong();
DamageDone = reader.ReadLong();
HealingTaken = reader.ReadLong();
HealingDone = reader.ReadLong();
}
}
}

View File

@@ -0,0 +1,160 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleOptions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleBroadcasts Broadcasts { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleLocations Locations { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleRestrictions Restrictions { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPRewards Rewards { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleRules Rules { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleSounds Sounds { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleSuddenDeath SuddenDeath { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleTiming Timing { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleWeather Weather { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleMissions Missions { get; set; }
public PvPBattleOptions()
{
Broadcasts = new PvPBattleBroadcasts();
Locations = new PvPBattleLocations();
Restrictions = new PvPBattleRestrictions();
Rewards = new PvPRewards();
Rules = new PvPBattleRules();
Sounds = new PvPBattleSounds();
SuddenDeath = new PvPBattleSuddenDeath();
Timing = new PvPBattleTiming();
Weather = new PvPBattleWeather();
Missions = new PvPBattleMissions();
}
public PvPBattleOptions(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
Broadcasts.Clear();
Locations.Clear();
Restrictions.Clear();
Rewards.Clear();
Rules.Clear();
Sounds.Clear();
SuddenDeath.Clear();
Timing.Clear();
Weather.Clear();
Missions.Clear();
}
public override void Reset()
{
Broadcasts.Reset();
Locations.Reset();
Restrictions.Reset();
Rewards.Reset();
Rules.Reset();
Sounds.Reset();
SuddenDeath.Reset();
Timing.Reset();
Weather.Reset();
Missions.Reset();
}
public override string ToString()
{
return "Advanced Options";
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.WriteBlock(w => w.WriteType(Missions, t => Missions.Serialize(w)));
goto case 0;
case 0:
{
writer.WriteBlock(w => w.WriteType(Broadcasts, t => Broadcasts.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Locations, t => Locations.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Restrictions, t => Restrictions.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Rewards, t => Rewards.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Rules, t => Rules.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Sounds, t => Sounds.Serialize(w)));
writer.WriteBlock(w => w.WriteType(SuddenDeath, t => SuddenDeath.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Timing, t => Timing.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Weather, t => Weather.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
Missions = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleMissions>(r)) ?? new PvPBattleMissions();
goto case 0;
case 0:
{
Broadcasts = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleBroadcasts>(r)) ?? new PvPBattleBroadcasts();
Locations = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleLocations>(r)) ?? new PvPBattleLocations();
Restrictions = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleRestrictions>(r)) ?? new PvPBattleRestrictions();
Rewards = reader.ReadBlock(r => r.ReadTypeCreate<PvPRewards>(r)) ?? new PvPRewards();
Rules = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleRules>(r)) ?? new PvPBattleRules();
Sounds = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleSounds>(r)) ?? new PvPBattleSounds();
SuddenDeath = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleSuddenDeath>(r)) ?? new PvPBattleSuddenDeath();
Timing = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleTiming>(r)) ?? new PvPBattleTiming();
Weather = reader.ReadBlock(r => r.ReadTypeCreate<PvPBattleWeather>(r)) ?? new PvPBattleWeather();
}
break;
}
if (version < 1)
{
Missions = new PvPBattleMissions();
}
}
}
}

View File

@@ -0,0 +1,142 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public abstract class PvPBattleRestrictionsBase<TKey> : PropertyObject, IEnumerable<TKey>
{
public static void SetFlag(ref ulong flags, ulong f, bool v)
{
if (v)
{
flags |= f;
}
else
{
flags &= ~f;
}
}
public static bool GetFlag(ulong flags, ulong f)
{
return (flags & f) != 0;
}
private Dictionary<TKey, bool> _List = new Dictionary<TKey, bool>();
public virtual Dictionary<TKey, bool> List
{
get => _List;
set => _List = value ?? new Dictionary<TKey, bool>();
}
public bool this[TKey key] { get => IsRestricted(key); set => SetRestricted(key, value); }
public PvPBattleRestrictionsBase()
{
Invalidate();
}
public PvPBattleRestrictionsBase(GenericReader reader)
: base(reader)
{ }
public abstract void Invalidate();
public virtual void Invert()
{
_List.Keys.ForEach(t => _List[t] = !_List[t]);
}
public virtual void Reset(bool val)
{
_List.Keys.ForEach(t => _List[t] = val);
}
public virtual bool Remove(TKey key)
{
return _List.Remove(key);
}
public override void Reset()
{
Reset(false);
}
public override void Clear()
{
_List.Clear();
}
public virtual void SetRestricted(TKey key, bool val)
{
if (key != null)
{
_List[key] = val;
}
}
public virtual bool IsRestricted(TKey key)
{
return key != null && _List.ContainsKey(key) && _List[key];
}
public IEnumerator<TKey> GetEnumerator()
{
return _List.Keys.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.WriteDictionary(_List, SerializeEntry);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
_List = reader.ReadDictionary(DeserializeEntry);
break;
}
}
public abstract void SerializeEntry(GenericWriter writer, TKey key, bool val);
public abstract KeyValuePair<TKey, bool> DeserializeEntry(GenericReader reader);
}
}

View File

@@ -0,0 +1,149 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPBattleItemRestrictions : PvPBattleRestrictionsBase<Type>
{
private static readonly Type _TypeOf = typeof(Item);
private static Type FindType(string name, bool full = false, bool ignoreCase = true)
{
return Type.GetType(name, false, ignoreCase) ?? (full
? ScriptCompiler.FindTypeByFullName(name, ignoreCase)
: ScriptCompiler.FindTypeByName(name, ignoreCase));
}
[CommandProperty(AutoPvP.Access)]
public bool AllowNonExceptional { get; set; }
public PvPBattleItemRestrictions()
{
AllowNonExceptional = true;
}
public PvPBattleItemRestrictions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Item Restrictions";
}
public override void Invalidate()
{ }
public virtual void SetRestricted(Item item, bool restrict)
{
if (item != null)
{
SetRestricted(item.GetType(), restrict);
}
}
public virtual void SetRestricted(string item, bool restrict)
{
if (!String.IsNullOrWhiteSpace(item))
{
SetRestricted(FindType(item), restrict);
}
}
public override void SetRestricted(Type key, bool val)
{
if (key == null)
{
return;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
base.SetRestricted(key, val);
}
}
public virtual bool IsRestricted(Item item)
{
return item != null && IsRestricted(item.GetType());
}
public override bool IsRestricted(Type key)
{
if (key == null)
{
return false;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
return base.IsRestricted(_TypeOf) || base.IsRestricted(key);
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var v = writer.SetVersion(1);
if (v > 0)
{
var flags = 0UL;
SetFlag(ref flags, 0x1, AllowNonExceptional);
writer.Write(flags);
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var v = reader.GetVersion();
if (v > 0)
{
var flags = reader.ReadULong();
AllowNonExceptional = GetFlag(flags, 0x1);
}
else
{
AllowNonExceptional = true;
}
}
public override void SerializeEntry(GenericWriter writer, Type key, bool val)
{
writer.WriteType(key);
writer.Write(val);
}
public override KeyValuePair<Type, bool> DeserializeEntry(GenericReader reader)
{
var k = reader.ReadType();
var v = reader.ReadBool();
return new KeyValuePair<Type, bool>(k, v);
}
}
}

View File

@@ -0,0 +1,125 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPBattlePetRestrictions : PvPBattleRestrictionsBase<Type>
{
private static readonly Type _TypeOf = typeof(BaseCreature);
private static Type FindType(string name, bool full = false, bool ignoreCase = true)
{
return Type.GetType(name, false, ignoreCase) ?? (full
? ScriptCompiler.FindTypeByFullName(name, ignoreCase)
: ScriptCompiler.FindTypeByName(name, ignoreCase));
}
public PvPBattlePetRestrictions()
{ }
public PvPBattlePetRestrictions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Pet Restrictions";
}
public override void Invalidate()
{ }
public virtual void SetRestricted(BaseCreature pet, bool restrict)
{
if (pet != null)
{
SetRestricted(pet.GetType(), restrict);
}
}
public virtual void SetRestricted(string pet, bool restrict)
{
if (!String.IsNullOrWhiteSpace(pet))
{
SetRestricted(FindType(pet), restrict);
}
}
public override void SetRestricted(Type key, bool val)
{
if (key == null)
{
return;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
base.SetRestricted(key, val);
}
}
public virtual bool IsRestricted(BaseCreature pet)
{
return pet != null && IsRestricted(pet.GetType());
}
public override bool IsRestricted(Type key)
{
if (key == null)
{
return false;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
return base.IsRestricted(_TypeOf) || base.IsRestricted(key);
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
public override void SerializeEntry(GenericWriter writer, Type key, bool val)
{
writer.WriteType(key);
writer.Write(val);
}
public override KeyValuePair<Type, bool> DeserializeEntry(GenericReader reader)
{
var k = reader.ReadType();
var v = reader.ReadBool();
return new KeyValuePair<Type, bool>(k, v);
}
}
}

View File

@@ -0,0 +1,105 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleRestrictions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleItemRestrictions Items { get; protected set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattlePetRestrictions Pets { get; protected set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleSkillRestrictions Skills { get; protected set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleSpellRestrictions Spells { get; protected set; }
public PvPBattleRestrictions()
{
Items = new PvPBattleItemRestrictions();
Pets = new PvPBattlePetRestrictions();
Skills = new PvPBattleSkillRestrictions();
Spells = new PvPBattleSpellRestrictions();
}
public PvPBattleRestrictions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Restrictions";
}
public override void Clear()
{
Items.Clear();
Pets.Clear();
Skills.Clear();
Spells.Clear();
}
public override void Reset()
{
Items.Reset(false);
Pets.Reset(false);
Skills.Reset(false);
Spells.Reset(false);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlock(w => w.WriteType(Items, t => Items.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Pets, t => Pets.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Skills, t => Skills.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Spells, t => Spells.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlock(r => Items = r.ReadTypeCreate<PvPBattleItemRestrictions>(r) ?? new PvPBattleItemRestrictions());
reader.ReadBlock(r => Pets = r.ReadTypeCreate<PvPBattlePetRestrictions>(r) ?? new PvPBattlePetRestrictions());
reader.ReadBlock(
r => Skills = r.ReadTypeCreate<PvPBattleSkillRestrictions>(r) ?? new PvPBattleSkillRestrictions());
reader.ReadBlock(
r => Spells = r.ReadTypeCreate<PvPBattleSpellRestrictions>(r) ?? new PvPBattleSpellRestrictions());
}
break;
}
}
}
}

View File

@@ -0,0 +1,142 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPBattleSkillRestrictions : PvPBattleRestrictionsBase<int>
{
private static readonly string[] _SkillNames = Enum.GetNames(typeof(SkillName));
private static int FindSkill(string name, bool ignoreCase = true)
{
return _SkillNames.IndexOf(
_SkillNames.FirstOrDefault(s => ignoreCase ? Insensitive.Equals(s, name) : String.Equals(s, name)));
}
public PvPBattleSkillRestrictions()
{ }
public PvPBattleSkillRestrictions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Skill Restrictions";
}
public override void Invalidate()
{
foreach (var info in SkillInfo.Table)
{
SetRestricted(info, false);
}
}
public virtual void SetRestricted(Skill skill, bool restrict)
{
if (skill != null)
{
SetRestricted(skill.Info, restrict);
}
}
public virtual void SetRestricted(SkillInfo skill, bool restrict)
{
if (skill != null)
{
SetRestricted(skill.SkillID, restrict);
}
}
public virtual void SetRestricted(string skill, bool restrict)
{
if (!String.IsNullOrWhiteSpace(skill))
{
SetRestricted(FindSkill(skill), restrict);
}
}
public virtual void SetRestricted(SkillName skill, bool restrict)
{
SetRestricted((int)skill, restrict);
}
public override void SetRestricted(int skill, bool restrict)
{
if (skill >= 0)
{
base.SetRestricted(skill, restrict);
}
}
public virtual bool IsRestricted(Skill skill)
{
return skill != null && IsRestricted(skill.Info);
}
public virtual bool IsRestricted(SkillInfo skill)
{
return skill != null && IsRestricted(skill.SkillID);
}
public virtual bool IsRestricted(string skill)
{
return !String.IsNullOrEmpty(skill) && IsRestricted(FindSkill(skill));
}
public virtual bool IsRestricted(SkillName skill)
{
return IsRestricted((int)skill);
}
public override bool IsRestricted(int key)
{
return key >= 0 && base.IsRestricted(key);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
public override void SerializeEntry(GenericWriter writer, int key, bool val)
{
writer.Write(key);
writer.Write(val);
}
public override KeyValuePair<int, bool> DeserializeEntry(GenericReader reader)
{
var k = reader.ReadInt();
var v = reader.ReadBool();
return new KeyValuePair<int, bool>(k, v);
}
}
}

View File

@@ -0,0 +1,130 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Spells;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[PropertyObject]
public class PvPBattleSpellRestrictions : PvPBattleRestrictionsBase<Type>
{
private static readonly Type _TypeOf = typeof(Spell);
private static Type FindType(string name, bool full = false, bool ignoreCase = true)
{
return Type.GetType(name, false, ignoreCase) ?? (full
? ScriptCompiler.FindTypeByFullName(name, ignoreCase)
: ScriptCompiler.FindTypeByName(name, ignoreCase));
}
public PvPBattleSpellRestrictions()
{ }
public PvPBattleSpellRestrictions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Spell Restrictions";
}
public override void Invalidate()
{
foreach (var t in SpellRegistry.Types)
{
SetRestricted(t, IsRestricted(t));
}
}
public virtual void SetRestricted(Spell spell, bool restrict)
{
if (spell != null)
{
SetRestricted(spell.GetType(), restrict);
}
}
public virtual void SetRestricted(string spell, bool restrict)
{
if (!String.IsNullOrWhiteSpace(spell))
{
SetRestricted(FindType(spell), restrict);
}
}
public override void SetRestricted(Type key, bool val)
{
if (key == null)
{
return;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
base.SetRestricted(key, val);
}
}
public virtual bool IsRestricted(Spell spell)
{
return spell != null && IsRestricted(spell.GetType());
}
public override bool IsRestricted(Type key)
{
if (key == null)
{
return false;
}
if (key.IsEqualOrChildOf(_TypeOf))
{
return base.IsRestricted(_TypeOf) || base.IsRestricted(key);
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
public override void SerializeEntry(GenericWriter writer, Type key, bool val)
{
writer.WriteType(key);
writer.Write(val);
}
public override KeyValuePair<Type, bool> DeserializeEntry(GenericReader reader)
{
var k = reader.ReadType();
var v = reader.ReadBool();
return new KeyValuePair<Type, bool>(k, v);
}
}
}

View File

@@ -0,0 +1,242 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.Reflection;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleRules : PropertyObject
{
private readonly object _CopyLock = new object();
private PropertyList<PvPBattleRules> _CopyStore;
[CommandProperty(AutoPvP.Access)]
public bool AllowSpeech { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool AllowBeneficial { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool AllowHarmful { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool AllowHousing { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool AllowSpawn { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanDie { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanHeal { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanBeDamaged { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanDamageOwnTeam { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanDamageEnemyTeam { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanHealOwnTeam { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanHealEnemyTeam { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool AllowPets { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanMount { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanFly { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanMountEthereal { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanMoveThrough { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanResurrect { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanUseStuckMenu { get; set; }
[CommandProperty(AutoPvP.Access)]
public bool CanEquip { get; set; }
public PvPBattleRules()
{
SetDefaults();
}
public PvPBattleRules(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Rules";
}
public void SetDefaults()
{
AllowBeneficial = true;
AllowHarmful = true;
AllowHousing = false;
AllowPets = false;
AllowSpawn = false;
AllowSpeech = true;
CanBeDamaged = true;
CanDamageEnemyTeam = true;
CanDamageOwnTeam = false;
CanDie = false;
CanEquip = true;
CanFly = false;
CanHeal = true;
CanHealEnemyTeam = false;
CanHealOwnTeam = true;
CanMount = false;
CanMountEthereal = false;
CanMoveThrough = false;
CanResurrect = false;
CanUseStuckMenu = false;
}
public override void Clear()
{
SetDefaults();
}
public override void Reset()
{
SetDefaults();
}
public void CopyFrom(PvPBattleRules source)
{
source.CopyTo(this);
}
public void CopyTo(PvPBattleRules target)
{
lock (_CopyLock)
{
if (_CopyStore == null)
{
_CopyStore = new PropertyList<PvPBattleRules>
{
Filter = p => p.Name != "InvokeReset" && p.Name != "InvokeClear" && p.PropertyType.IsEqual<bool>()
};
}
_CopyStore.Deserialize(this);
_CopyStore.Serialize(target);
_CopyStore.Clear();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(3);
switch (version)
{
case 3:
writer.Write(CanEquip);
goto case 2;
case 2:
writer.Write(CanMoveThrough);
goto case 1;
case 1:
writer.Write(CanFly);
goto case 0;
case 0:
{
writer.Write(AllowBeneficial);
writer.Write(AllowHarmful);
writer.Write(AllowHousing);
writer.Write(AllowPets);
writer.Write(AllowSpawn);
writer.Write(AllowSpeech);
writer.Write(CanBeDamaged);
writer.Write(CanDamageEnemyTeam);
writer.Write(CanDamageOwnTeam);
writer.Write(CanDie);
writer.Write(CanHeal);
writer.Write(CanHealEnemyTeam);
writer.Write(CanHealOwnTeam);
writer.Write(CanMount);
writer.Write(CanMountEthereal);
writer.Write(CanResurrect);
writer.Write(CanUseStuckMenu);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
SetDefaults();
var version = reader.GetVersion();
switch (version)
{
case 3:
CanEquip = reader.ReadBool();
goto case 2;
case 2:
CanMoveThrough = reader.ReadBool();
goto case 1;
case 1:
CanFly = reader.ReadBool();
goto case 0;
case 0:
{
AllowBeneficial = reader.ReadBool();
AllowHarmful = reader.ReadBool();
AllowHousing = reader.ReadBool();
AllowPets = reader.ReadBool();
AllowSpawn = reader.ReadBool();
AllowSpeech = reader.ReadBool();
CanBeDamaged = reader.ReadBool();
CanDamageEnemyTeam = reader.ReadBool();
CanDamageOwnTeam = reader.ReadBool();
CanDie = reader.ReadBool();
CanHeal = reader.ReadBool();
CanHealEnemyTeam = reader.ReadBool();
CanHealOwnTeam = reader.ReadBool();
CanMount = reader.ReadBool();
CanMountEthereal = reader.ReadBool();
CanResurrect = reader.ReadBool();
CanUseStuckMenu = reader.ReadBool();
}
break;
}
}
}
}

View File

@@ -0,0 +1,177 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleSounds : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual bool Enabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int InviteSend { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int InviteAccept { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int InviteCancel { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int QueueJoin { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int QueueLeave { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int Teleport { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int BattleOpened { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int BattlePreparing { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int BattleStarted { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int BattleEnded { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int BattleCanceled { get; set; }
public PvPBattleSounds()
{
SetDefaults();
}
public PvPBattleSounds(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Sounds";
}
public override void Clear()
{
Enabled = false;
InviteSend = -1;
InviteAccept = -1;
InviteCancel = -1;
QueueJoin = -1;
QueueLeave = -1;
Teleport = -1;
BattleOpened = -1;
BattlePreparing = -1;
BattleStarted = -1;
BattleEnded = -1;
BattleCanceled = -1;
}
public override void Reset()
{
SetDefaults();
}
public virtual void SetDefaults()
{
Enabled = true;
InviteSend = 0xF0;
InviteAccept = 0x5B5;
InviteCancel = 0x5B4;
QueueJoin = 0x664;
QueueLeave = 0x51C;
Teleport = 0x029;
BattleOpened = 0x2E8;
BattlePreparing = 0x2E8;
BattleStarted = 0x2E9;
BattleEnded = 0x2EA;
BattleCanceled = 0x2EA;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Enabled);
writer.Write(InviteSend);
writer.Write(InviteAccept);
writer.Write(InviteCancel);
writer.Write(QueueJoin);
writer.Write(QueueLeave);
writer.Write(Teleport);
writer.Write(BattleOpened);
writer.Write(BattlePreparing);
writer.Write(BattleStarted);
writer.Write(BattleEnded);
writer.Write(BattleCanceled);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Enabled = reader.ReadBool();
InviteSend = reader.ReadInt();
InviteAccept = reader.ReadInt();
InviteCancel = reader.ReadInt();
QueueJoin = reader.ReadInt();
QueueLeave = reader.ReadInt();
Teleport = reader.ReadInt();
BattleOpened = reader.ReadInt();
BattlePreparing = reader.ReadInt();
BattleStarted = reader.ReadInt();
BattleEnded = reader.ReadInt();
BattleCanceled = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,219 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleSuddenDeath : PropertyObject
{
private bool _Active;
private int _CapacityRequired = 2;
private int _DamageRange;
private DateTime _EndedWhen;
private int _MaxDamage = 40;
private int _MinDamage = 20;
private DateTime _StartedWhen;
[CommandProperty(AutoPvP.Access)]
public virtual bool Enabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Active => _Active;
[CommandProperty(AutoPvP.Access)]
public virtual DateTime StartedWhen => _StartedWhen;
[CommandProperty(AutoPvP.Access)]
public virtual DateTime EndedWhen => _EndedWhen;
[CommandProperty(AutoPvP.Access)]
public virtual int CapacityRequired
{
get => _CapacityRequired;
set => _CapacityRequired = Math.Max(2, value);
}
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan Delay { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Damages { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int DamageRange { get => _DamageRange; set => _DamageRange = Math.Max(0, value); }
[CommandProperty(AutoPvP.Access)]
public virtual int MinDamage
{
get => _MinDamage;
set => _MinDamage = Math.Max(0, Math.Min(_MaxDamage, value));
}
[CommandProperty(AutoPvP.Access)]
public virtual int MaxDamage { get => _MaxDamage; set => _MaxDamage = Math.Max(_MinDamage, value); }
public PvPBattleSuddenDeath()
{
_StartedWhen = DateTime.UtcNow;
_EndedWhen = DateTime.UtcNow;
CapacityRequired = 2;
Delay = TimeSpan.FromSeconds(30.0);
Damages = true;
DamageRange = 1;
MinDamage = 20;
MaxDamage = 40;
}
public PvPBattleSuddenDeath(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Sudden Death";
}
public override void Clear()
{
Enabled = false;
_Active = false;
_StartedWhen = DateTime.UtcNow;
_EndedWhen = DateTime.UtcNow;
CapacityRequired = 0;
Delay = TimeSpan.Zero;
Damages = false;
DamageRange = 0;
MinDamage = 0;
MaxDamage = 0;
}
public override void Reset()
{
Enabled = false;
_Active = false;
_StartedWhen = DateTime.UtcNow;
_EndedWhen = DateTime.UtcNow;
CapacityRequired = 2;
Delay = TimeSpan.FromSeconds(30.0);
Damages = true;
DamageRange = 1;
MinDamage = 20;
MaxDamage = 40;
}
public virtual void Damage(Mobile target)
{
if (target == null || target.Deleted)
{
return;
}
if (Damages)
{
target.Damage(Utility.RandomMinMax(_MinDamage, _MaxDamage));
}
}
public virtual void Damage(Mobile from, Mobile target)
{
if (target == null || target.Deleted)
{
return;
}
if (Damages)
{
target.Damage(Utility.RandomMinMax(_MinDamage, _MaxDamage), from);
}
}
public virtual void Start()
{
if (!Enabled)
{
return;
}
_StartedWhen = DateTime.UtcNow;
_Active = true;
}
public virtual void End()
{
_EndedWhen = DateTime.UtcNow;
_Active = false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Enabled);
writer.Write(_Active);
writer.Write(_StartedWhen);
writer.Write(_EndedWhen);
writer.Write(CapacityRequired);
writer.Write(Delay);
writer.Write(Damages);
writer.Write(MinDamage);
writer.Write(MaxDamage);
writer.Write(DamageRange);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Enabled = reader.ReadBool();
_Active = reader.ReadBool();
_StartedWhen = reader.ReadDateTime();
_EndedWhen = reader.ReadDateTime();
CapacityRequired = reader.ReadInt();
Delay = reader.ReadTimeSpan();
Damages = reader.ReadBool();
MinDamage = reader.ReadInt();
MaxDamage = reader.ReadInt();
DamageRange = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,224 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleTiming : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan QueuePeriod { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan PreparePeriod { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan RunningPeriod { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan EndedPeriod { get; set; }
[CommandProperty(AutoPvP.Access)]
public TimeSpan TotalCycleTime => (PreparePeriod + RunningPeriod + EndedPeriod);
public DateTime OpenedWhen { get; protected set; }
public DateTime PreparedWhen { get; protected set; }
public DateTime StartedWhen { get; protected set; }
public DateTime EndedWhen { get; protected set; }
public PvPBattleTiming()
{
QueuePeriod = TimeSpan.FromMinutes(5.0);
PreparePeriod = TimeSpan.FromMinutes(5.0);
RunningPeriod = TimeSpan.FromMinutes(15.0);
EndedPeriod = TimeSpan.FromMinutes(2.5);
OpenedWhen = DateTime.UtcNow;
PreparedWhen = DateTime.UtcNow;
StartedWhen = DateTime.UtcNow;
EndedWhen = DateTime.UtcNow;
}
public PvPBattleTiming(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Timing";
}
public override void Clear()
{
QueuePeriod = TimeSpan.Zero;
RunningPeriod = TimeSpan.Zero;
PreparePeriod = TimeSpan.Zero;
EndedPeriod = TimeSpan.Zero;
OpenedWhen = DateTime.UtcNow;
PreparedWhen = DateTime.UtcNow;
StartedWhen = DateTime.UtcNow;
EndedWhen = DateTime.UtcNow;
}
public override void Reset()
{
QueuePeriod = TimeSpan.FromMinutes(5.0);
PreparePeriod = TimeSpan.FromMinutes(5.0);
RunningPeriod = TimeSpan.FromMinutes(15.0);
EndedPeriod = TimeSpan.FromMinutes(2.5);
OpenedWhen = DateTime.UtcNow;
PreparedWhen = DateTime.UtcNow;
StartedWhen = DateTime.UtcNow;
EndedWhen = DateTime.UtcNow;
}
public void SetAllPeriods(TimeSpan duration)
{
QueuePeriod = duration;
PreparePeriod = duration;
RunningPeriod = duration;
EndedPeriod = duration;
}
public void SetPeriod(PvPBattleState state, TimeSpan duration)
{
switch (state)
{
case PvPBattleState.Queueing:
QueuePeriod = duration;
break;
case PvPBattleState.Preparing:
PreparePeriod = duration;
break;
case PvPBattleState.Running:
RunningPeriod = duration;
break;
case PvPBattleState.Ended:
EndedPeriod = duration;
break;
}
}
public void SetAllTimes(DateTime when)
{
OpenedWhen = when;
PreparedWhen = when;
StartedWhen = when;
EndedWhen = when;
}
public void SetTime(PvPBattleState state, DateTime when)
{
switch (state)
{
case PvPBattleState.Queueing:
OpenedWhen = when;
break;
case PvPBattleState.Preparing:
PreparedWhen = when;
break;
case PvPBattleState.Running:
StartedWhen = when;
break;
case PvPBattleState.Ended:
EndedWhen = when;
break;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(2);
switch (version)
{
case 2:
case 1:
case 0:
{
if (version > 1)
{
writer.Write(QueuePeriod);
}
writer.Write(PreparePeriod);
writer.Write(RunningPeriod);
writer.Write(EndedPeriod);
if (version > 0)
{
writer.WriteDeltaTime(OpenedWhen);
writer.WriteDeltaTime(PreparedWhen);
writer.WriteDeltaTime(StartedWhen);
writer.WriteDeltaTime(EndedWhen);
}
else
{
writer.Write(OpenedWhen);
writer.Write(PreparedWhen);
writer.Write(StartedWhen);
writer.Write(EndedWhen);
}
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 2:
case 1:
case 0:
{
if (version > 1)
{
QueuePeriod = reader.ReadTimeSpan();
}
PreparePeriod = reader.ReadTimeSpan();
RunningPeriod = reader.ReadTimeSpan();
EndedPeriod = reader.ReadTimeSpan();
if (version > 0)
{
OpenedWhen = reader.ReadDeltaTime();
PreparedWhen = reader.ReadDeltaTime();
StartedWhen = reader.ReadDeltaTime();
EndedWhen = reader.ReadDeltaTime();
}
else
{
OpenedWhen = reader.ReadDateTime();
PreparedWhen = reader.ReadDateTime();
StartedWhen = reader.ReadDateTime();
EndedWhen = reader.ReadDateTime();
}
}
break;
}
}
}
}

View File

@@ -0,0 +1,256 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.Network;
#endregion
namespace VitaNex.Modules.AutoPvP
{
[CustomEnum(new[] { "None", "North", "Right", "East", "Down", "South", "Left", "West", "Up", "Random" })]
public enum PvPBattleWeatherDirection : short
{
None = -0x01,
North = Direction.North,
Right = Direction.Right,
East = Direction.East,
Down = Direction.Down,
South = Direction.South,
Left = Direction.Left,
West = Direction.West,
Up = Direction.Up,
Random = 0x80
}
public class PvPBattleWeather : PropertyObject
{
public static int DefaultEffectID = 14036;
public static int DefaultImpactEffectID = 14000;
public static int DefaultImpactSound = 549;
private int _Density;
private int _EffectHue;
private int _EffectID;
private int _EffectSpeed;
private int _ImpactEffectDuration;
private int _ImpactEffectHue;
private int _ImpactEffectID;
private int _ImpactEffectSound;
private int _ImpactEffectSpeed;
[CommandProperty(AutoPvP.Access)]
public virtual bool Enabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Force { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Impacts { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int Density { get => _Density; set => _Density = Math.Max(1, Math.Min(100, value)); }
[CommandProperty(AutoPvP.Access)]
public virtual PvPBattleWeatherDirection Direction { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int EffectID { get => _EffectID; set => _EffectID = Math.Max(0, value); }
[CommandProperty(AutoPvP.Access)]
public virtual int EffectHue { get => _EffectHue; set => _EffectHue = Math.Max(0, Math.Min(3000, value)); }
[CommandProperty(AutoPvP.Access)]
public virtual int EffectSpeed
{
get => _EffectSpeed;
set => _EffectSpeed = Math.Max(1, Math.Min(10, value));
}
[CommandProperty(AutoPvP.Access)]
public virtual EffectRender EffectRender { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int ImpactEffectID { get => _ImpactEffectID; set => _ImpactEffectID = Math.Max(0, value); }
[CommandProperty(AutoPvP.Access)]
public virtual int ImpactEffectHue
{
get => _ImpactEffectHue;
set => _ImpactEffectHue = Math.Max(0, Math.Min(3000, value));
}
[CommandProperty(AutoPvP.Access)]
public virtual int ImpactEffectSpeed
{
get => _ImpactEffectSpeed;
set => _ImpactEffectSpeed = Math.Max(1, Math.Min(10, value));
}
[CommandProperty(AutoPvP.Access)]
public virtual int ImpactEffectDuration
{
get => _ImpactEffectDuration;
set => _ImpactEffectDuration = Math.Max(0, value);
}
[CommandProperty(AutoPvP.Access)]
public virtual EffectRender ImpactEffectRender { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int ImpactEffectSound
{
get => _ImpactEffectSound;
set => _ImpactEffectSound = Math.Max(0, value);
}
public PvPBattleWeather()
{
Enabled = true;
Force = false;
Impacts = true;
Density = 6;
Direction = PvPBattleWeatherDirection.South;
EffectID = DefaultEffectID;
EffectHue = 0;
EffectSpeed = 10;
EffectRender = EffectRender.Normal;
ImpactEffectID = DefaultImpactEffectID;
ImpactEffectHue = 0;
ImpactEffectSpeed = 10;
ImpactEffectDuration = 30;
ImpactEffectRender = EffectRender.Normal;
ImpactEffectSound = DefaultImpactSound;
}
public PvPBattleWeather(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Battle Weather";
}
public override void Clear()
{
Enabled = false;
Force = false;
Impacts = false;
Density = 0;
Direction = PvPBattleWeatherDirection.None;
EffectID = 0;
EffectHue = 0;
EffectSpeed = 1;
EffectRender = EffectRender.Normal;
ImpactEffectID = 0;
ImpactEffectHue = 0;
ImpactEffectSpeed = 1;
ImpactEffectDuration = 0;
ImpactEffectRender = EffectRender.Normal;
ImpactEffectSound = 0;
}
public override void Reset()
{
Enabled = true;
Force = false;
Impacts = true;
Density = 6;
Direction = PvPBattleWeatherDirection.South;
EffectID = DefaultEffectID;
EffectHue = 0;
EffectSpeed = 10;
EffectRender = EffectRender.Normal;
ImpactEffectID = DefaultImpactEffectID;
ImpactEffectHue = 0;
ImpactEffectSpeed = 10;
ImpactEffectDuration = 30;
ImpactEffectRender = EffectRender.Normal;
ImpactEffectSound = DefaultImpactSound;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Enabled);
writer.Write(Force);
writer.Write(Impacts);
writer.Write(_Density);
writer.WriteFlag(Direction);
writer.Write(_EffectID);
writer.Write(_EffectHue);
writer.Write(_EffectSpeed);
writer.WriteFlag(EffectRender);
writer.Write(_ImpactEffectID);
writer.Write(_ImpactEffectHue);
writer.Write(_ImpactEffectSpeed);
writer.Write(_ImpactEffectDuration);
writer.WriteFlag(ImpactEffectRender);
writer.Write(_ImpactEffectSound);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Enabled = reader.ReadBool();
Force = reader.ReadBool();
Impacts = reader.ReadBool();
_Density = reader.ReadInt();
Direction = reader.ReadFlag<PvPBattleWeatherDirection>();
_EffectID = reader.ReadInt();
_EffectHue = reader.ReadInt();
_EffectSpeed = reader.ReadInt();
EffectRender = reader.ReadFlag<EffectRender>();
_ImpactEffectID = reader.ReadInt();
_ImpactEffectHue = reader.ReadInt();
_ImpactEffectSpeed = reader.ReadInt();
_ImpactEffectDuration = reader.ReadInt();
ImpactEffectRender = reader.ReadFlag<EffectRender>();
_ImpactEffectSound = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,283 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public enum PvPRewardDeliveryMethod
{
None,
Custom,
Backpack,
Bank
}
public enum PvPRewardClass
{
None,
Custom,
Item
}
public class PvPReward : PropertyObject
{
private class InternalTypeSelect : ItemTypeSelectProperty
{
private readonly PvPReward _Owner;
[CommandProperty(AutoPvP.Access)]
public override string TypeName
{
get => base.TypeName;
set
{
base.TypeName = value;
if (_Owner == null)
{
return;
}
if (InternalType != null)
{
if (InternalType.IsConstructableFrom<Item>())
{
_Owner.Class = PvPRewardClass.Item;
_Owner.DeliveryMethod = PvPRewardDeliveryMethod.Backpack;
}
else
{
_Owner.Class = PvPRewardClass.Custom;
_Owner.DeliveryMethod = PvPRewardDeliveryMethod.Custom;
}
}
else
{
_Owner.Class = PvPRewardClass.None;
_Owner.DeliveryMethod = PvPRewardDeliveryMethod.None;
}
}
}
public InternalTypeSelect(PvPReward owner, GenericReader reader)
: base(reader)
{
_Owner = owner;
}
public InternalTypeSelect(PvPReward owner, string type)
: base(type)
{
_Owner = owner;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
private InternalTypeSelect _InternalTypeSelect;
private PvPRewardDeliveryMethod _DeliveryMethod = PvPRewardDeliveryMethod.Backpack;
[CommandProperty(AutoPvP.Access)]
public virtual bool Enabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int Amount { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual string TypeName
{
get => _InternalTypeSelect.TypeName;
set => _InternalTypeSelect.TypeName = value;
}
[CommandProperty(AutoPvP.Access)]
public virtual PvPRewardDeliveryMethod DeliveryMethod
{
get => _DeliveryMethod;
set
{
if (value != PvPRewardDeliveryMethod.None && Class == PvPRewardClass.Custom)
{
value = PvPRewardDeliveryMethod.Custom;
}
_DeliveryMethod = value;
}
}
[CommandProperty(AutoPvP.Access, true)]
public PvPRewardClass Class { get; private set; }
public PvPReward()
: this(String.Empty)
{ }
public PvPReward(string type)
{
_InternalTypeSelect = new InternalTypeSelect(this, type);
Enabled = false;
Amount = 1;
Class = PvPRewardClass.None;
_DeliveryMethod = PvPRewardDeliveryMethod.None;
}
public PvPReward(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
_InternalTypeSelect.Clear();
Enabled = false;
Amount = 1;
Class = PvPRewardClass.None;
_DeliveryMethod = PvPRewardDeliveryMethod.None;
}
public override void Reset()
{
_InternalTypeSelect.Reset();
Enabled = false;
Amount = 1;
Class = PvPRewardClass.None;
_DeliveryMethod = PvPRewardDeliveryMethod.Backpack;
}
public virtual List<Item> GiveReward(PlayerMobile pm)
{
var items = new List<Item>();
if (pm == null || pm.Deleted || !Enabled)
{
return items;
}
var amount = Amount;
while (amount > 0)
{
var reward = _InternalTypeSelect.CreateInstance();
if (reward == null)
{
return items;
}
items.Add(reward);
if (reward.Stackable)
{
reward.Amount = Math.Min(60000, amount);
}
amount -= reward.Amount;
}
items.ForEach(
item =>
{
switch (_DeliveryMethod)
{
case PvPRewardDeliveryMethod.Custom:
break;
case PvPRewardDeliveryMethod.Bank:
item.GiveTo(pm, GiveFlags.Bank | GiveFlags.Delete);
break;
case PvPRewardDeliveryMethod.Backpack:
item.GiveTo(pm, GiveFlags.Pack | GiveFlags.Delete);
break;
default:
item.GiveTo(pm, GiveFlags.PackBankDelete);
break;
}
});
items.RemoveAll(i => i == null || i.Deleted);
return items;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
_InternalTypeSelect.Serialize(writer);
writer.Write(Amount);
writer.Write(Enabled);
writer.WriteFlag(Class);
writer.WriteFlag(_DeliveryMethod);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
_InternalTypeSelect = new InternalTypeSelect(this, reader);
Amount = reader.ReadInt();
Enabled = reader.ReadBool();
Class = reader.ReadFlag<PvPRewardClass>();
_DeliveryMethod = reader.ReadFlag<PvPRewardDeliveryMethod>();
}
break;
}
if (_InternalTypeSelect == null)
{
_InternalTypeSelect = new InternalTypeSelect(this, String.Empty);
}
if (Amount < 1)
{
Amount = 1;
}
}
}
}

View File

@@ -0,0 +1,87 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRewards : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual PvPReward Loser { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPReward Winner { get; set; }
public PvPRewards()
{
Loser = new PvPReward();
Winner = new PvPReward();
}
public PvPRewards(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Rewards";
}
public override void Clear()
{
Loser.Clear();
Winner.Clear();
}
public override void Reset()
{
Loser.Reset();
Winner.Reset();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlock(w => w.WriteType(Loser, t => Loser.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Winner, t => Winner.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlock(r => Loser = r.ReadTypeCreate<PvPReward>(r) ?? new PvPReward());
reader.ReadBlock(r => Winner = r.ReadTypeCreate<PvPReward>(r) ?? new PvPReward());
}
break;
}
}
}
}

View File

@@ -0,0 +1,112 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPAdvancedOptions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPCommandOptions Commands { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPProfileOptions Profiles { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPSeasonOptions Seasons { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPMiscOptions Misc { get; set; }
public AutoPvPAdvancedOptions()
{
Commands = new AutoPvPCommandOptions();
Profiles = new AutoPvPProfileOptions();
Seasons = new AutoPvPSeasonOptions();
Misc = new AutoPvPMiscOptions();
}
public AutoPvPAdvancedOptions(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
Commands.Clear();
Profiles.Clear();
Seasons.Clear();
Misc.Clear();
}
public override void Reset()
{
Commands.Reset();
Profiles.Reset();
Seasons.Reset();
Misc.Reset();
}
public override string ToString()
{
return "Advanced Options";
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.WriteBlock(w => w.WriteType(Misc, t => Misc.Serialize(w)));
goto case 0;
case 0:
{
writer.WriteBlock(w => w.WriteType(Commands, t => Commands.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Profiles, t => Profiles.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Seasons, t => Seasons.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
reader.ReadBlock(r => Misc = r.ReadTypeCreate<AutoPvPMiscOptions>(r) ?? new AutoPvPMiscOptions());
goto case 0;
case 0:
{
reader.ReadBlock(r => Commands = r.ReadTypeCreate<AutoPvPCommandOptions>(r) ?? new AutoPvPCommandOptions());
reader.ReadBlock(r => Profiles = r.ReadTypeCreate<AutoPvPProfileOptions>(r) ?? new AutoPvPProfileOptions());
reader.ReadBlock(r => Seasons = r.ReadTypeCreate<AutoPvPSeasonOptions>(r) ?? new AutoPvPSeasonOptions());
}
break;
}
if (Misc == null)
{
Misc = new AutoPvPMiscOptions();
}
}
}
}

View File

@@ -0,0 +1,193 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Linq;
using Server;
using Server.Commands;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPCommandOptions : PropertyObject
{
private string _BattlesCommand;
private string _ConfigCommand;
private string _ProfilesCommand;
[CommandProperty(AutoPvP.Access)]
public virtual string ConfigCommand
{
get => _ConfigCommand;
set => CommandUtility.Replace(_ConfigCommand, AutoPvP.Access, OnConfigCommand, (_ConfigCommand = value));
}
[CommandProperty(AutoPvP.Access)]
public virtual string ProfilesCommand
{
get => _ProfilesCommand;
set => CommandUtility.Replace(_ProfilesCommand, AccessLevel.Player, OnProfilesCommand, (_ProfilesCommand = value));
}
[CommandProperty(AutoPvP.Access)]
public virtual string BattlesCommand
{
get => _BattlesCommand;
set => CommandUtility.Replace(_BattlesCommand, AccessLevel.Player, OnBattlesCommand, (_BattlesCommand = value));
}
public AutoPvPCommandOptions()
{
ConfigCommand = "PvPConfig";
ProfilesCommand = "PvPRanks";
BattlesCommand = "Battles";
}
public AutoPvPCommandOptions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Command Options";
}
public override void Clear()
{
ConfigCommand = null;
ProfilesCommand = null;
BattlesCommand = null;
}
public override void Reset()
{
ConfigCommand = "PvPConfig";
ProfilesCommand = "PvPRanks";
BattlesCommand = "Battles";
}
public virtual void InvokeConfigCommand(Mobile m)
{
if (m != null)
{
CommandSystem.Handle(m, CommandSystem.Prefix + ConfigCommand);
}
}
public virtual void InvokeBattlesCommand(Mobile m)
{
if (m != null)
{
CommandSystem.Handle(m, CommandSystem.Prefix + BattlesCommand);
}
}
public virtual void InvokeProfilesCommand(Mobile m)
{
if (m != null)
{
CommandSystem.Handle(m, CommandSystem.Prefix + ProfilesCommand);
}
}
protected virtual void OnConfigCommand(CommandEventArgs e)
{
if (e.Mobile == null || e.Mobile.Deleted || !(e.Mobile is PlayerMobile))
{
return;
}
if (e.Mobile.AccessLevel >= AutoPvP.Access)
{
e.Mobile.SendGump(new PropertiesGump(e.Mobile, AutoPvP.CMOptions));
}
}
protected virtual void OnProfilesCommand(CommandEventArgs e)
{
if (e.Mobile == null || e.Mobile.Deleted || !(e.Mobile is PlayerMobile))
{
return;
}
if (AutoPvP.CMOptions.ModuleEnabled || e.Mobile.AccessLevel >= AutoPvP.Access)
{
SuperGump.Send(new PvPProfilesUI(e.Mobile, null));
}
}
protected virtual void OnBattlesCommand(CommandEventArgs e)
{
if (e.Mobile == null || e.Mobile.Deleted || !(e.Mobile is PlayerMobile))
{
return;
}
if (AutoPvP.CMOptions.ModuleEnabled || e.Mobile.AccessLevel >= AutoPvP.Access)
{
PvPBattle battle = null;
if (e.Arguments != null && e.Arguments.Length > 0)
{
var shortcut = e.Arguments[0];
if (!System.String.IsNullOrWhiteSpace(shortcut))
{
battle = AutoPvP.Battles.Values.FirstOrDefault(b => b != null && !b.Deleted && Insensitive.Equals(b.Shortcut, shortcut));
}
}
PvPBattlesUI.DisplayTo(e.Mobile, battle, false);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(ConfigCommand);
writer.Write(ProfilesCommand);
writer.Write(BattlesCommand);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
ConfigCommand = reader.ReadString();
ProfilesCommand = reader.ReadString();
BattlesCommand = reader.ReadString();
}
break;
}
}
}
}

View File

@@ -0,0 +1,159 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPExecuteCommands : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual bool SaveEnabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Save
{
get => SaveEnabled;
set
{
if (value)
{
Execute("SAVE");
}
}
}
[CommandProperty(AutoPvP.Access)]
public virtual bool LoadEnabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Load
{
get => LoadEnabled;
set
{
if (value)
{
Execute("LOAD");
}
}
}
[CommandProperty(AutoPvP.Access)]
public virtual bool SyncEnabled { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool Sync
{
get => SyncEnabled;
set
{
if (value)
{
Execute("SYNC");
}
}
}
public AutoPvPExecuteCommands()
{
SaveEnabled = LoadEnabled = SyncEnabled = true;
}
public AutoPvPExecuteCommands(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Command Interface";
}
public override void Clear()
{
SaveEnabled = LoadEnabled = SyncEnabled = false;
}
public override void Reset()
{
SaveEnabled = LoadEnabled = SyncEnabled = true;
}
public virtual void Execute(string cmd)
{
switch (cmd)
{
case "SAVE":
{
if (SaveEnabled)
{
AutoPvP.Save();
}
}
break;
case "LOAD":
{
if (LoadEnabled)
{
AutoPvP.Load();
}
}
break;
case "SYNC":
{
if (SyncEnabled)
{
AutoPvP.Sync();
}
}
break;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(SaveEnabled);
writer.Write(LoadEnabled);
writer.Write(SyncEnabled);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
SaveEnabled = reader.ReadBool();
LoadEnabled = reader.ReadBool();
SyncEnabled = reader.ReadBool();
}
break;
}
}
}
}

View File

@@ -0,0 +1,104 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPMiscOptions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual bool UseCategories { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool DeserterAssoc { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual TimeSpan DeserterLockout { get; set; }
public AutoPvPMiscOptions()
{
UseCategories = true;
DeserterAssoc = true;
DeserterLockout = TimeSpan.FromMinutes(30);
}
public AutoPvPMiscOptions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Misc Options";
}
public override void Clear()
{
UseCategories = false;
DeserterAssoc = false;
DeserterLockout = TimeSpan.Zero;
}
public override void Reset()
{
UseCategories = true;
DeserterAssoc = true;
DeserterLockout = TimeSpan.FromMinutes(30);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
{
writer.Write(DeserterAssoc);
writer.Write(DeserterLockout);
}
goto case 0;
case 0:
writer.Write(UseCategories);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
{
DeserterAssoc = reader.ReadBool();
DeserterLockout = reader.ReadTimeSpan();
}
goto case 0;
case 0:
UseCategories = reader.ReadBool();
break;
}
}
}
}

View File

@@ -0,0 +1,94 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPProfileOptions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual bool AllowPlayerSearch { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual bool AllowPlayerDelete { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPProfileRankOrder RankingOrder { get; set; }
public AutoPvPProfileOptions()
{
AllowPlayerSearch = true;
RankingOrder = PvPProfileRankOrder.Points;
}
public AutoPvPProfileOptions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Profile Options";
}
public override void Clear()
{
AllowPlayerSearch = false;
AllowPlayerDelete = false;
RankingOrder = PvPProfileRankOrder.None;
}
public override void Reset()
{
AllowPlayerSearch = true;
AllowPlayerDelete = false;
RankingOrder = PvPProfileRankOrder.Points;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(AllowPlayerSearch);
writer.Write(AllowPlayerDelete);
writer.WriteFlag(RankingOrder);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
AllowPlayerSearch = reader.ReadBool();
AllowPlayerDelete = reader.ReadBool();
RankingOrder = reader.ReadFlag<PvPProfileRankOrder>();
}
break;
}
}
}
}

View File

@@ -0,0 +1,161 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using VitaNex.Schedules;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPSeasonOptions : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public ScheduleInfo ScheduleInfo
{
get => AutoPvP.SeasonSchedule.Info;
set => AutoPvP.SeasonSchedule.Info = value;
}
[CommandProperty(AutoPvP.Access)]
public virtual int CurrentSeason { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int TopListCount { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int RunnersUpCount { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual PvPRewards Rewards { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int SkipTicks { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual int SkippedTicks { get; set; }
public AutoPvPSeasonOptions()
{
CurrentSeason = 1;
TopListCount = 3;
RunnersUpCount = 7;
Rewards = new PvPRewards();
}
public AutoPvPSeasonOptions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "Season Options";
}
public override void Clear()
{
ScheduleInfo.Clear();
TopListCount = 0;
RunnersUpCount = 0;
SkipTicks = 0;
SkippedTicks = 0;
Rewards.Clear();
}
public override void Reset()
{
ScheduleInfo.Clear();
TopListCount = 3;
RunnersUpCount = 7;
SkipTicks = 0;
SkippedTicks = 0;
Rewards.Reset();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
{
writer.Write(SkipTicks);
writer.Write(SkippedTicks);
}
goto case 0;
case 0:
{
writer.WriteBlock(
w =>
{
w.Write(CurrentSeason);
w.Write(TopListCount);
w.Write(RunnersUpCount);
w.WriteType(ScheduleInfo, t => ScheduleInfo.Serialize(w));
w.Write(AutoPvP.SeasonSchedule.Enabled);
});
writer.WriteBlock(w => w.WriteType(Rewards, t => Rewards.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
var scheduled = AutoPvP.SeasonSchedule.Enabled;
switch (version)
{
case 1:
{
SkipTicks = reader.ReadInt();
SkippedTicks = reader.ReadInt();
}
goto case 0;
case 0:
{
reader.ReadBlock(
r =>
{
CurrentSeason = r.ReadInt();
TopListCount = r.ReadInt();
RunnersUpCount = r.ReadInt();
ScheduleInfo = r.ReadTypeCreate<ScheduleInfo>(r) ?? new ScheduleInfo();
scheduled = r.ReadBool();
});
reader.ReadBlock(r => Rewards = r.ReadTypeCreate<PvPRewards>(r) ?? new PvPRewards());
}
break;
}
AutoPvP.SeasonSchedule.Enabled = scheduled;
}
}
}

View File

@@ -0,0 +1,97 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPOptions : CoreModuleOptions
{
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPAdvancedOptions Advanced { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPStatistics Statistics { get; set; }
[CommandProperty(AutoPvP.Access)]
public virtual AutoPvPExecuteCommands ExecuteCommands { get; set; }
public AutoPvPOptions()
: base(typeof(AutoPvP))
{
Advanced = new AutoPvPAdvancedOptions();
Statistics = new AutoPvPStatistics();
ExecuteCommands = new AutoPvPExecuteCommands();
}
public AutoPvPOptions(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "System Options";
}
public override void Clear()
{
Advanced.Clear();
Statistics.Clear();
ExecuteCommands.Clear();
}
public override void Reset()
{
Advanced.Reset();
Statistics.Reset();
ExecuteCommands.Reset();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlock(w => w.WriteType(Advanced, t => Advanced.Serialize(w)));
writer.WriteBlock(w => w.WriteType(Statistics, t => Statistics.Serialize(w)));
writer.WriteBlock(w => w.WriteType(ExecuteCommands, t => ExecuteCommands.Serialize(w)));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlock(r => Advanced = r.ReadTypeCreate<AutoPvPAdvancedOptions>(r) ?? new AutoPvPAdvancedOptions());
reader.ReadBlock(r => Statistics = r.ReadTypeCreate<AutoPvPStatistics>(r) ?? new AutoPvPStatistics());
reader.ReadBlock(
r => ExecuteCommands = r.ReadTypeCreate<AutoPvPExecuteCommands>(r) ?? new AutoPvPExecuteCommands());
}
break;
}
}
}
}

View File

@@ -0,0 +1,105 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using VitaNex.IO;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class AutoPvPStatistics : PropertyObject
{
[CommandProperty(AutoPvP.Access)]
public virtual DataStoreStatus BattlesStatus => AutoPvP.Profiles.Status;
[CommandProperty(AutoPvP.Access)]
public virtual DataStoreStatus ProfilesStatus => AutoPvP.Battles.Status;
[CommandProperty(AutoPvP.Access)]
public virtual int Battles => AutoPvP.Battles.Count;
[CommandProperty(AutoPvP.Access)]
public virtual int BattlesInternal => AutoPvP.CountBattles(PvPBattleState.Internal);
[CommandProperty(AutoPvP.Access)]
public virtual int BattlesEnded => AutoPvP.CountBattles(PvPBattleState.Ended);
[CommandProperty(AutoPvP.Access)]
public virtual int BattlesPreparing => AutoPvP.CountBattles(PvPBattleState.Preparing);
[CommandProperty(AutoPvP.Access)]
public virtual int BattlesQueueing => AutoPvP.CountBattles(PvPBattleState.Queueing);
[CommandProperty(AutoPvP.Access)]
public virtual int BattlesRunning => AutoPvP.CountBattles(PvPBattleState.Running);
[CommandProperty(AutoPvP.Access)]
public virtual int Participants => AutoPvP.TotalParticipants();
[CommandProperty(AutoPvP.Access)]
public virtual int Spectators => AutoPvP.TotalSpectators();
[CommandProperty(AutoPvP.Access)]
public virtual int Queueing => AutoPvP.TotalQueued();
[CommandProperty(AutoPvP.Access)]
public virtual int Profiles => AutoPvP.Profiles.Count;
[CommandProperty(AutoPvP.Access)]
public virtual int Scenarios => AutoPvP.Scenarios.Length;
public AutoPvPStatistics()
{ }
public AutoPvPStatistics(GenericReader reader)
: base(reader)
{ }
public override string ToString()
{
return "View Statistics";
}
public override void Clear()
{ }
public override void Reset()
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
break;
}
}
}
}

View File

@@ -0,0 +1,487 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.Schedules;
using VitaNex.SuperGumps.UI;
using VitaNex.Text;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleUI : HtmlPanelGump<PvPBattle>
{
public bool UseConfirmDialog { get; set; }
public PvPBattleUI(Mobile user, Gump parent = null, PvPBattle battle = null, bool useConfirm = true)
: base(user, parent, emptyText: "No battle selected.", title: "PvP Battle Overview", selected: battle)
{
UseConfirmDialog = useConfirm;
ForceRecompile = true;
//AutoRefresh = true;
}
protected override void Compile()
{
base.Compile();
if (Selected == null || Selected.Deleted)
{
return;
}
Html = String.Empty;
if (User.AccessLevel >= AutoPvP.Access)
{
var errors = new List<string>();
if (!Selected.Validate(User, errors))
{
Html += "*This battle has failed validation*\n\n".WrapUOHtmlBig().WrapUOHtmlColor(Color.IndianRed, false);
Html += String.Join("\n", errors).WrapUOHtmlColor(Color.Yellow);
Html += "\n\n";
}
}
Html += Selected.ToHtmlString(User);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.Clear();
if (Selected != null && !Selected.Deleted)
{
if (User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
"Edit Options",
b =>
{
Minimize();
var pg = new PropertiesGump(User, Selected)
{
X = b.X,
Y = b.Y
};
User.SendGump(pg);
},
HighlightHue);
list.AppendEntry(
"Edit Advanced Options",
b =>
{
Minimize();
var pg = new PropertiesGump(User, Selected.Options)
{
X = b.X,
Y = b.Y
};
User.SendGump(pg);
},
HighlightHue);
if (Selected.State == PvPBattleState.Internal)
{
list.AppendEntry(
"Edit Spectate Region",
b =>
{
if (Selected.SpectateRegion == null)
{
Selected.SpectateRegion = RegionExtUtility.Create<PvPSpectateRegion>(Selected);
}
new PvPSpectateBoundsGump(User, Selected, Hide(true)).Send();
},
HighlightHue);
list.AppendEntry(
"Edit Battle Region",
b =>
{
if (Selected.BattleRegion == null)
{
Selected.BattleRegion = RegionExtUtility.Create<PvPBattleRegion>(Selected);
}
new PvPBattleBoundsGump(User, Selected, Hide(true)).Send();
},
HighlightHue);
}
list.AppendEntry(
"Edit Doors",
b => new PvPDoorsUI(User, Selected, Hide(true), UseConfirmDialog).Send(),
HighlightHue);
list.AppendEntry(
"Edit Description",
b => new TextInputPanelGump<PvPBattle>(User, Hide(true))
{
Title = "Battle Description (HTML/BBC Supported)",
Input = Selected.Description,
Limit = 1000,
Callback = s =>
{
s = s.ParseBBCode();
if (!String.IsNullOrWhiteSpace(s))
{
Selected.Description = s;
}
Refresh(true);
}
}.Send(),
HighlightHue);
}
list.AppendEntry(
"View Schedule",
b => new ScheduleOverviewGump(User, Selected.Schedule, Hide(true)).Send(),
User.AccessLevel >= AutoPvP.Access ? HighlightHue : TextHue);
if (User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
"View Rules/Restrictions",
b =>
{
var opts = new MenuGumpOptions();
opts.AppendEntry(
"Inherit Rules/Restrictions",
b2 =>
{
var opts2 = new MenuGumpOptions();
foreach (var ba in AutoPvP.Battles.Values.Where(ba => ba != Selected))
{
opts2.AppendEntry(
ba.Name,
() =>
{
Selected.Options.Rules.CopyFrom(ba.Options.Rules);
Selected.Options.Restrictions.Items.List = //
new Dictionary<Type, bool>(ba.Options.Restrictions.Items.List);
Selected.Options.Restrictions.Pets.List = //
new Dictionary<Type, bool>(ba.Options.Restrictions.Pets.List);
Selected.Options.Restrictions.Spells.List = //
new Dictionary<Type, bool>(ba.Options.Restrictions.Spells.List);
Selected.Options.Restrictions.Skills.List = //
new Dictionary<int, bool>(ba.Options.Restrictions.Skills.List);
Refresh(true);
});
}
new MenuGump(User, this, opts2, b).Send();
});
opts.AppendEntry(
new ListGumpEntry(
"Rules",
mb =>
{
Refresh();
var g = new PropertiesGump(User, Selected.Options.Rules)
{
X = mb.X,
Y = mb.Y
};
User.SendGump(g);
}));
opts.AppendEntry(
"Items",
mb => new PvPRestrictItemsListGump(User, Selected.Options.Restrictions.Items, Hide(true)).Send());
opts.AppendEntry(
"Pets",
mb => new PvPRestrictPetsListGump(User, Selected.Options.Restrictions.Pets, Hide(true)).Send());
opts.AppendEntry(
"Skills",
mb => new PvPRestrictSkillsListGump(User, Selected.Options.Restrictions.Skills, Hide(true)).Send());
opts.AppendEntry(
"Spells",
mb => new PvPRestrictSpellsListGump(User, Selected.Options.Restrictions.Spells, Hide(true)).Send());
new MenuGump(User, this, opts, b).Send();
},
User.AccessLevel >= AutoPvP.Access ? HighlightHue : TextHue);
list.AppendEntry(
"Reset Statistics",
b =>
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Reset Battle Statistics?",
Html = "All data associated with the battle statistics will " +
"be transferred to player profiles then cleared.\nThis action can not be reversed!\n" +
"Do you want to continue?",
AcceptHandler = OnConfirmResetStatistics,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmResetStatistics(b);
}
},
HighlightHue);
if (Selected.State == PvPBattleState.Internal)
{
if (Selected.Validate(User))
{
list.AppendEntry(
"Publish",
b =>
{
Selected.State = PvPBattleState.Queueing;
Refresh(true);
},
HighlightHue);
}
}
else
{
list.AppendEntry(
"Internalize",
b =>
{
Selected.State = PvPBattleState.Internal;
Refresh(true);
},
HighlightHue);
if (!Selected.Hidden)
{
if (Selected.Validate(User))
{
list.AppendEntry(
"Hide",
b =>
{
Selected.Hidden = true;
Refresh(true);
},
HighlightHue);
}
}
else
{
list.AppendEntry(
"Unhide",
b =>
{
Selected.Hidden = false;
Refresh(true);
},
HighlightHue);
}
}
list.AppendEntry(
"Delete",
b =>
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Delete Battle?",
Html = "All data associated with this battle will be deleted.\n" +
"This action can not be reversed!\nDo you want to continue?",
AcceptHandler = OnConfirmDeleteBattle,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmDeleteBattle(b);
}
},
HighlightHue);
}
list.AppendEntry(
"Command List",
b =>
{
var html = new StringBuilder();
Selected.GetHtmlCommandList(User, html);
new HtmlPanelGump<PvPBattle>(User, this)
{
Title = "Command List",
Html = html.ToString(),
Selected = Selected
}.Send();
});
var profile = AutoPvP.EnsureProfile(User as PlayerMobile);
if (profile != null && !profile.Deleted)
{
if (profile.IsSubscribed(Selected))
{
list.AppendEntry(
"Unsubscribe",
b =>
{
profile.Unsubscribe(Selected);
User.SendMessage("You have unsubscribed from {0} notifications.", Selected.Name);
Refresh(true);
});
}
else
{
list.AppendEntry(
"Subscribe",
b =>
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Subscriptions",
Html = "Subscribing to a battle allows you to see its world broadcast notifications.\n\n" +
"Do you want to subscribe to " + Selected.Name + "?",
AcceptHandler = OnConfirmSubscribe,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmSubscribe(b);
}
});
}
}
if (User is PlayerMobile)
{
var user = (PlayerMobile)User;
if (Selected.IsParticipant(user))
{
list.AppendEntry("Quit & Leave", b => Selected.Quit(user, true));
}
else
{
if (Selected.IsQueued(user))
{
list.AppendEntry("Leave Queue", b => Selected.Dequeue(user));
}
else if (Selected.CanQueue(user))
{
list.AppendEntry("Join Queue", b => Selected.Enqueue(user));
}
if (Selected.IsSpectator(user))
{
list.AppendEntry("Leave Spectators", b => Selected.RemoveSpectator(user, true));
}
else if (Selected.CanSpectate(user))
{
list.AppendEntry("Join Spectators", b => Selected.AddSpectator(user, true));
}
}
}
}
base.CompileMenuOptions(list);
}
protected virtual void OnConfirmSubscribe(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Close();
return;
}
var profile = AutoPvP.EnsureProfile(User as PlayerMobile);
if (profile != null && !profile.Deleted)
{
profile.Subscribe(Selected);
User.SendMessage("You have subscribed to {0} notifications.", Selected.Name);
Refresh(true);
}
}
protected virtual void OnConfirmResetStatistics(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Close();
return;
}
Selected.ResetStatistics();
Refresh(true);
}
protected virtual void OnConfirmDeleteBattle(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Close();
return;
}
Selected.Delete();
Close();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,458 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using Server.Items;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
using VitaNex.Targets;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPDoorsUI : ListGump<BaseDoor>
{
public PvPBattle Battle { get; set; }
public bool UseConfirmDialog { get; set; }
public PvPDoorsUI(Mobile user, PvPBattle battle, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "There are no doors to display.", title: "PvP Battle Doors")
{
Battle = battle;
UseConfirmDialog = useConfirm;
ForceRecompile = true;
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.Clear();
if (User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
new ListGumpEntry(
"Remove All",
b =>
{
if (UseConfirmDialog)
{
Send(
new ConfirmDialogGump(
User,
this,
title: "Remove All Doors?",
html:
"All doors in the list will be removed (not deleted).\nThis action can not be reversed.\n\nDo you want to continue?",
onAccept: OnConfirmRemoveAllDoors));
}
else
{
OnConfirmRemoveAllDoors(b);
}
},
HighlightHue));
list.AppendEntry(new ListGumpEntry("Add Door", b => SelectAddDoor(), HighlightHue));
list.AppendEntry(
new ListGumpEntry(
"Open All",
b => List.ForEach(
door =>
{
if (door == null || door.Deleted || door.Open)
{
return;
}
door.Open = true;
if (!door.UseChainedFunctionality)
{
return;
}
door.GetChain()
.ForEach(
chained =>
{
if (chained == null || chained.Deleted || chained.Open)
{
return;
}
chained.Open = true;
});
}),
HighlightHue));
list.AppendEntry(
new ListGumpEntry(
"Close All",
b => List.ForEach(
door =>
{
if (door == null || door.Deleted || !door.Open)
{
return;
}
door.Open = false;
if (!door.UseChainedFunctionality)
{
return;
}
door.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && chained.Open)
{
chained.Open = false;
}
});
}),
ErrorHue));
list.AppendEntry(
new ListGumpEntry(
"Unlock All",
b => List.ForEach(
door =>
{
if (door == null || door.Deleted || !door.Locked)
{
return;
}
door.Locked = false;
if (!door.UseChainedFunctionality)
{
return;
}
door.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && chained.Locked)
{
chained.Locked = false;
}
});
}),
HighlightHue));
list.AppendEntry(
new ListGumpEntry(
"Lock All",
b => List.ForEach(
door =>
{
if (door == null || door.Deleted || door.Locked)
{
return;
}
door.Locked = true;
if (!door.UseChainedFunctionality)
{
return;
}
door.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && !chained.Locked)
{
chained.Locked = true;
}
});
}),
ErrorHue));
}
base.CompileMenuOptions(list);
}
protected virtual void SelectAddDoor()
{
Minimize();
User.Target = new ItemSelectTarget<BaseDoor>(OnDoorAdd, OnDoorAddCancel);
}
protected virtual void OnDoorAdd(Mobile m, BaseDoor door)
{
if (!Battle.Doors.Contains(door))
{
Battle.Doors.Add(door);
m.SendMessage("The door has been added to the list.");
SelectAddDoor();
}
else if (Minimized)
{
Maximize();
}
Refresh(true);
}
protected virtual void OnDoorAddCancel(Mobile m)
{
if (Minimized)
{
Maximize();
}
Refresh(true);
}
protected virtual void OnConfirmRemoveAllDoors(GumpButton button)
{
foreach (var team in List)
{
team.Delete();
}
Refresh(true);
}
protected override void CompileList(List<BaseDoor> list)
{
list.Clear();
list.AddRange(Battle.Doors);
base.CompileList(list);
}
public override string GetSearchKeyFor(BaseDoor key)
{
return key != null ? (key.Name ?? key.Serial.ToString()) : base.GetSearchKeyFor(null);
}
protected override void SelectEntry(GumpButton button, BaseDoor entry)
{
base.SelectEntry(button, entry);
if (button == null || entry == null || entry.Deleted)
{
return;
}
if (User.AccessLevel < AutoPvP.Access)
{
Refresh(true);
return;
}
var list = new MenuGumpOptions();
list.AppendEntry(
new ListGumpEntry(
"Remove",
b =>
{
Battle.Doors.Remove(entry);
Refresh(true);
},
HighlightHue));
if (entry.Open)
{
list.AppendEntry(
new ListGumpEntry(
"Close",
b =>
{
if (entry.Deleted || !entry.Open)
{
return;
}
entry.Open = false;
if (entry.UseChainedFunctionality)
{
entry.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && chained.Open)
{
chained.Open = false;
}
});
}
Refresh(true);
},
ErrorHue));
}
else
{
list.AppendEntry(
new ListGumpEntry(
"Open",
b =>
{
if (entry.Deleted || entry.Open)
{
return;
}
entry.Open = true;
if (entry.UseChainedFunctionality)
{
entry.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && !chained.Open)
{
chained.Open = true;
}
});
}
Refresh(true);
},
HighlightHue));
}
if (entry.Open)
{
list.AppendEntry(
new ListGumpEntry(
"Lock",
b =>
{
if (entry.Deleted || entry.Locked)
{
return;
}
entry.Locked = true;
if (entry.UseChainedFunctionality)
{
entry.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && !chained.Locked)
{
chained.Locked = true;
}
});
}
Refresh(true);
},
ErrorHue));
}
else
{
list.AppendEntry(
new ListGumpEntry(
"Unlock",
b =>
{
if (entry.Deleted || !entry.Locked)
{
return;
}
entry.Locked = false;
if (entry.UseChainedFunctionality)
{
entry.GetChain()
.ForEach(
chained =>
{
if (chained != null && !chained.Deleted && chained.Locked)
{
chained.Locked = false;
}
});
}
Refresh(true);
},
HighlightHue));
}
Send(new MenuGump(User, Refresh(), list, button));
}
protected override void CompileEntryLayout(
SuperGumpLayout layout,
int length,
int index,
int pIndex,
int yOffset,
BaseDoor entry)
{
base.CompileEntryLayout(layout, length, index, pIndex, yOffset, entry);
layout.Replace(
"label/list/entry/" + index,
() =>
{
AddLabelCropped(65, 2 + yOffset, 150, 20, GetLabelHue(index, pIndex, entry), GetLabelText(index, pIndex, entry));
AddLabelCropped(
205,
2 + yOffset,
170,
20,
GetStateLabelHue(index, pIndex, entry),
GetStateLabelText(index, pIndex, entry));
});
}
protected override int GetLabelHue(int index, int pageIndex, BaseDoor entry)
{
return entry != null
? ((entry.Hue > 0 && entry.Hue < 3000) ? entry.Hue : TextHue)
: base.GetLabelHue(index, pageIndex, null);
}
protected override string GetLabelText(int index, int pageIndex, BaseDoor entry)
{
return entry != null && !entry.Deleted
? (entry.Name ?? entry.Serial.ToString())
: base.GetLabelText(index, pageIndex, entry);
}
protected virtual string GetStateLabelText(int index, int pageIndex, BaseDoor entry)
{
return entry != null ? (entry.Open ? "Open" : "Closed") : String.Empty;
}
protected virtual int GetStateLabelHue(int index, int pageIndex, BaseDoor entry)
{
return entry != null ? (entry.Open ? HighlightHue : ErrorHue) : TextHue;
}
}
}

View File

@@ -0,0 +1,129 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPProfileUI : HtmlPanelGump<PvPProfile>
{
public bool UseConfirmDialog { get; set; }
public PvPProfileUI(Mobile user, PvPProfile profile, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "No profile selected.", title: "PvP Profile Overview", selected: profile)
{
UseConfirmDialog = useConfirm;
}
protected override void Compile()
{
base.Compile();
if (Selected == null || Selected.Deleted)
{
Selected = AutoPvP.EnsureProfile(User as PlayerMobile, true);
}
Html = Selected.ToHtmlString(User);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
if (Selected == null || Selected.Deleted)
{
Selected = AutoPvP.EnsureProfile(User as PlayerMobile, true);
}
if ((Selected.Owner == User && AutoPvP.CMOptions.Advanced.Profiles.AllowPlayerDelete) ||
User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(new ListGumpEntry("Clear Statistics", OnResetStatistics, HighlightHue));
list.AppendEntry(new ListGumpEntry("Delete Profile", OnDeleteProfile, HighlightHue));
}
base.CompileMenuOptions(list);
}
protected virtual void OnResetStatistics(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Selected = AutoPvP.EnsureProfile(User as PlayerMobile);
}
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, Refresh())
{
Title = "Reset Profile Statistics?",
Html = "All data associated with the profile statistics will be lost.\n" +
"This action can not be reversed!\nDo you want to continue?",
AcceptHandler = OnConfirmResetStatistics,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmResetStatistics(button);
}
}
protected virtual void OnDeleteProfile(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Selected = AutoPvP.EnsureProfile(User as PlayerMobile);
}
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, Refresh())
{
Title = "Delete Profile?",
Html = "All data associated with this profile will be deleted.\n" +
"This action can not be reversed!\nDo you want to continue?",
AcceptHandler = OnConfirmDeleteProfile,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmDeleteProfile(button);
}
}
protected virtual void OnConfirmResetStatistics(GumpButton button)
{
if (Selected != null && !Selected.Deleted)
{
Selected.History.Entries.Clear();
}
Refresh(true);
}
protected virtual void OnConfirmDeleteProfile(GumpButton button)
{
if (Selected != null && !Selected.Deleted)
{
Selected.Delete();
}
Close();
}
}
}

View File

@@ -0,0 +1,83 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPProfilesSortUI : MenuGump
{
public PvPProfilesUI ListGump { get; set; }
public PvPProfilesSortUI(Mobile user, PvPProfilesUI listGump, Gump parent = null, GumpButton clicked = null)
: base(user, parent, clicked: clicked)
{
ListGump = listGump;
}
protected override void CompileOptions(MenuGumpOptions list)
{
if (ListGump != null)
{
if (ListGump.SortOrder != PvPProfileRankOrder.None)
{
list.AppendEntry(
"No Sorting",
button =>
{
ListGump.SortOrder = PvPProfileRankOrder.None;
ListGump.Refresh(true);
});
}
if (ListGump.SortOrder != PvPProfileRankOrder.Kills)
{
list.AppendEntry(
"Kills",
button =>
{
ListGump.SortOrder = PvPProfileRankOrder.Kills;
ListGump.Refresh(true);
});
}
if (ListGump.SortOrder != PvPProfileRankOrder.Points)
{
list.AppendEntry(
"Points",
button =>
{
ListGump.SortOrder = PvPProfileRankOrder.Points;
ListGump.Refresh(true);
});
}
if (ListGump.SortOrder != PvPProfileRankOrder.Wins)
{
list.AppendEntry(
"Wins",
button =>
{
ListGump.SortOrder = PvPProfileRankOrder.Wins;
ListGump.Refresh(true);
});
}
}
base.CompileOptions(list);
}
}
}

View File

@@ -0,0 +1,314 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Server;
using Server.Gumps;
using Server.Misc;
using Server.Mobiles;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPProfilesUI : ListGump<PvPProfile>
{
public PvPSeason Season { get; set; }
public PvPProfileRankOrder SortOrder { get; set; }
public bool UseConfirmDialog { get; set; }
public PvPProfilesUI(
Mobile user,
PvPSeason season,
Gump parent = null,
bool useConfirm = true,
PvPProfileRankOrder sortOrder = PvPProfileRankOrder.None)
: base(user, parent, emptyText: "There are no profiles to display.", title: "PvP Profiles")
{
Season = season ?? AutoPvP.CurrentSeason;
SortOrder = sortOrder != PvPProfileRankOrder.None ? sortOrder : AutoPvP.CMOptions.Advanced.Profiles.RankingOrder;
UseConfirmDialog = useConfirm;
CanSearch = User.AccessLevel > AccessLevel.Player || AutoPvP.CMOptions.Advanced.Profiles.AllowPlayerSearch;
ForceRecompile = true;
}
protected override void Compile()
{
if (AutoPvP.SeasonSchedule.Enabled)
{
Title = "PvP Profiles (Season " + (Season != null ? Season.Number : AutoPvP.CurrentSeason.Number) + ")";
}
base.Compile();
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.Clear();
if (User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
new ListGumpEntry(
"Delete All",
button => new ConfirmDialogGump(User, this)
{
Title = "Delete All Profiles?",
Html = "All profiles in the database will be deleted, erasing all data associated with them.\n" +
"This action can not be reversed.\n\nDo you want to continue?",
AcceptHandler = subButton =>
{
var profiles = new List<PvPProfile>(AutoPvP.Profiles.Values);
foreach (var p in profiles.Where(p => p != null && !p.Deleted))
{
p.Delete();
}
Refresh(true);
},
CancelHandler = Refresh
}.Send(),
HighlightHue));
}
list.AppendEntry(new ListGumpEntry("My Profile", OnMyProfile));
list.AppendEntry(
new ListGumpEntry("Sort By (" + SortOrder + ")", b => new PvPProfilesSortUI(User, this, this, b).Send()));
if (Season != null)
{
list.AppendEntry(
new ListGumpEntry(
"Overall Ranks",
b =>
{
Season = null;
Refresh(true);
}));
}
var season = AutoPvP.CurrentSeason;
if (Season != season)
{
list.AppendEntry(
new ListGumpEntry(
String.Format("Season {0:#,0} Ranks", season.Number),
b =>
{
Season = season;
Refresh(true);
}));
}
if (season.Number > 1)
{
list.AppendEntry(
new ListGumpEntry(
"Select Season",
b => new InputDialogGump(User, this)
{
Title = "Select Season",
Html = "Enter the number for the season you wish to view rankings for.\nSeasons 1 to " + season.Number,
InputText = Season == null ? "" : Season.Number.ToString(CultureInfo.InvariantCulture),
Callback = (ib, text) =>
{
if (Int32.TryParse(text, out var num))
{
if (!AutoPvP.Seasons.TryGetValue(num, out var s) || s == null)
{
User.SendMessage(ErrorHue, "Invalid Season selection.");
}
else
{
Season = s;
}
}
Refresh(true);
},
CancelHandler = Refresh
}.Send()));
}
base.CompileMenuOptions(list);
}
protected virtual void OnMyProfile(GumpButton button)
{
new PvPProfileUI(User, AutoPvP.EnsureProfile(User as PlayerMobile), Hide(true)).Send();
}
protected override void CompileList(List<PvPProfile> list)
{
list.Clear();
list.AddRange(AutoPvP.GetSortedProfiles(SortOrder, Season));
base.CompileList(list);
}
public override string GetSearchKeyFor(PvPProfile key)
{
if (key != null && !key.Deleted && key.Owner != null)
{
return key.Owner.RawName;
}
return base.GetSearchKeyFor(key);
}
protected override void CompileEntryLayout(SuperGumpLayout layout, Dictionary<int, PvPProfile> range)
{
var sup = SupportsUltimaStore;
var bgID = sup ? 40000 : 9270;
var fillID = sup ? 40004 : 2624;
var yOff = range.Count * 30;
layout.Add(
"background/footer/help",
() =>
{
AddBackground(0, 75 + yOff, Width + 20, 130, bgID);
AddImageTiled(10, 85 + yOff, Width, 110, fillID);
});
layout.Add("html/footer/help", () => AddHtml(20, 85 + yOff, Width - 10, 110, GetHelpText(), false, false));
base.CompileEntryLayout(layout, range);
}
protected override void CompileEntryLayout(
SuperGumpLayout layout,
int length,
int index,
int pIndex,
int yOffset,
PvPProfile entry)
{
base.CompileEntryLayout(layout, length, index, pIndex, yOffset, entry);
var wOffset = (Width - 10) / Columns;
var xOffset = (pIndex % Columns) * wOffset;
layout.Replace(
"label/list/entry/" + index,
() =>
{
var ww = (wOffset - 40) / 2;
var hue = GetLabelHue(index, pIndex, entry);
var text = GetLabelText(index, pIndex, entry);
AddLabelCropped(60 + xOffset, 2 + yOffset, ww, 20, hue, text);
hue = GetSortLabelHue(index, pIndex, entry);
text = GetSortLabelText(index, pIndex, entry);
AddLabelCropped(60 + xOffset + ww, 2 + yOffset, ww, 20, hue, text);
});
}
protected virtual string GetHelpText()
{
return String.Format(
"PvP profiles store all of your battle statistics.\n" +
"They can be ranked in order of total points, wins or kills.\n" +
"Do you think you have what it takes to earn the top rank in {0}?",
ServerList.ServerName)
.WrapUOHtmlColor(DefaultHtmlColor, false);
}
protected override int GetLabelHue(int index, int pageIndex, PvPProfile entry)
{
if (index < 3)
{
return HighlightHue;
}
if (entry != null)
{
return Notoriety.GetHue(Notoriety.Compute(User, entry.Owner));
}
return base.GetLabelHue(index, pageIndex, null);
}
protected override string GetLabelText(int index, int pageIndex, PvPProfile entry)
{
if (entry != null && entry.Owner != null)
{
return String.Format("{0}: {1}", index + 1, entry.Owner.RawName);
}
return base.GetLabelText(index, pageIndex, entry);
}
protected virtual string GetSortLabelText(int index, int pageIndex, PvPProfile entry)
{
if (entry != null)
{
var key = "Rank";
long val = index;
if (SortOrder != PvPProfileRankOrder.None)
{
key = SortOrder.ToString().SpaceWords().ToUpperWords();
val = AutoPvP.GetSortedValue(SortOrder, entry, Season);
}
return String.Format("{0}: {1:#,0}", key, val);
}
return String.Empty;
}
protected virtual int GetSortLabelHue(int index, int pageIndex, PvPProfile entry)
{
if (entry != null)
{
if (SortOrder == PvPProfileRankOrder.None)
{
return index <= AutoPvP.CMOptions.Advanced.Seasons.TopListCount ? HighlightHue : TextHue;
}
return AutoPvP.GetSortedValue(SortOrder, entry, Season) <= 0 ? ErrorHue : TextHue;
}
return ErrorHue;
}
protected override void SelectEntry(GumpButton button, PvPProfile entry)
{
base.SelectEntry(button, entry);
if (button != null && entry != null && !entry.Deleted)
{
new PvPProfileUI(User, entry, Hide(true), UseConfirmDialog).Send();
}
}
}
}

View File

@@ -0,0 +1,73 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPInviteGump : ConfirmDialogGump
{
public PvPInviteGump(Mobile user, PvPBattle battle, Gump parent = null)
: base(user, parent, title: "Call To Arms")
{
Battle = battle;
}
public PvPBattle Battle { get; set; }
protected override void Compile()
{
base.Compile();
Html = Battle != null ? Battle.ToHtmlString(User) : "Battle does not exist.";
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Add(
"textentry/body/question",
() => AddLabelCropped(25, Height - 45, Width - 80, 20, HighlightHue, "Accept or Decline?"));
}
protected override void OnAccept(GumpButton button)
{
base.OnAccept(button);
if (Battle != null && !Battle.Deleted)
{
Battle.AcceptInvite(User as PlayerMobile);
}
Close(true);
}
protected override void OnCancel(GumpButton button)
{
base.OnCancel(button);
if (Battle != null && !Battle.Deleted)
{
Battle.DeclineInvite(User as PlayerMobile);
}
Close(true);
}
}
}

View File

@@ -0,0 +1,166 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Gumps;
using VitaNex.Network;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPBattleBoundsGump : Rect3DListGump
{
private RegionExtUtility.PreviewRegion _SpectatePreview;
public PvPBattle Battle { get; set; }
public PvPBattleBoundsGump(Mobile user, PvPBattle battle, Gump parent = null)
: base(
user,
parent,
list: battle.Options.Locations.BattleBounds,
emptyText: "There are no bounds in the list.",
title: "Battle Region Bounds")
{
Battle = battle;
InputMap = Battle.Map;
Preview = true;
PreviewHue = TextHue;
PreviewEffect = 3259;
PreviewName = String.Format("Battle Region Preview: {0} ({1})", Battle.Name, Battle.Serial);
ForceRecompile = true;
}
public override List<Rectangle3D> GetExternalList()
{
return Battle.Options.Locations.BattleBounds;
}
protected override bool OnBeforeListAdd()
{
if (!base.OnBeforeListAdd())
{
return false;
}
if (InputRect != null && InputRect.Value.ToRectangle2D()
.EnumeratePoints()
.Any(Battle.Options.Locations.SpectateBounds.Contains))
{
User.SendMessage(ErrorHue, "Bounds can not overlap Spectate region.");
return false;
}
return true;
}
protected override void HandleApplyChanges()
{
base.HandleApplyChanges();
Battle.Map = InputMap;
Battle.InvalidateBattleRegion();
}
public override void ClearPreview()
{
base.ClearPreview();
if (_SpectatePreview == null)
{
return;
}
_SpectatePreview.Unregister();
_SpectatePreview = null;
}
public override void DisplayPreview()
{
base.DisplayPreview();
if (!Preview || InputMap == null || InputMap == Map.Internal || Battle.SpectateRegion == null ||
Battle.SpectateRegion.Area.Length == 0)
{
if (_SpectatePreview != null)
{
_SpectatePreview.Unregister();
_SpectatePreview = null;
}
return;
}
if (_SpectatePreview != null)
{
if (_SpectatePreview.Map == InputMap &&
_SpectatePreview.Area.GetBoundsHashCode() == Battle.SpectateRegion.Area.GetBoundsHashCode())
{
_SpectatePreview.Refresh();
return;
}
_SpectatePreview.Unregister();
_SpectatePreview = null;
}
_SpectatePreview = Battle.SpectateRegion.DisplayPreview(ErrorHue, PreviewEffect, EffectRender.Darken);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
var regions = Region
.Regions.Not(r => r == null || !r.Registered || r is PvPRegion || r is RegionExtUtility.PreviewRegion)
.Where(r => r.Contains(User.Location, User.Map))
.ToArray();
if (regions.Length > 0)
{
var opts = new MenuGumpOptions();
regions.ForEach(
r => opts.AppendEntry(
new ListGumpEntry(
r.Name,
() =>
{
ClearPreview();
var prev = Preview;
Preview = false;
r.Area.ForEach(AddToList);
Preview = prev;
DisplayPreview();
})));
list.AppendEntry(new ListGumpEntry("Use Region...", b => Send(new MenuGump(User, Refresh(), opts, b))));
}
else
{
list.RemoveEntry("Use Region...");
}
base.CompileMenuOptions(list);
}
}
}

View File

@@ -0,0 +1,166 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Gumps;
using VitaNex.Network;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPSpectateBoundsGump : Rect3DListGump
{
public PvPBattle Battle { get; set; }
private RegionExtUtility.PreviewRegion _BattlePreview;
public PvPSpectateBoundsGump(Mobile user, PvPBattle battle, Gump parent = null)
: base(
user,
parent,
list: battle.Options.Locations.SpectateBounds,
emptyText: "There are no bounds in the list.",
title: "Spectate Region Bounds")
{
Battle = battle;
InputMap = Battle.Map;
Preview = true;
PreviewHue = HighlightHue;
PreviewEffect = 3259;
PreviewName = String.Format("Spectate Region Preview: {0} ({1})", Battle.Name, Battle.Serial);
ForceRecompile = true;
}
public override List<Rectangle3D> GetExternalList()
{
return Battle.Options.Locations.SpectateBounds;
}
protected override bool OnBeforeListAdd()
{
if (!base.OnBeforeListAdd())
{
return false;
}
if (InputRect != null && InputRect.Value.ToRectangle2D()
.EnumeratePoints()
.Any(Battle.Options.Locations.BattleBounds.Contains))
{
User.SendMessage(ErrorHue, "Bounds can not overlap Battle region.");
return false;
}
return true;
}
protected override void HandleApplyChanges()
{
base.HandleApplyChanges();
Battle.Map = InputMap;
Battle.InvalidateSpectateRegion();
}
public override void ClearPreview()
{
base.ClearPreview();
if (_BattlePreview == null)
{
return;
}
_BattlePreview.Unregister();
_BattlePreview = null;
}
public override void DisplayPreview()
{
base.DisplayPreview();
if (!Preview || InputMap == null || InputMap == Map.Internal || Battle.BattleRegion == null ||
Battle.BattleRegion.Area.Length == 0)
{
if (_BattlePreview != null)
{
_BattlePreview.Unregister();
_BattlePreview = null;
}
return;
}
if (_BattlePreview != null)
{
if (_BattlePreview.Map == InputMap &&
_BattlePreview.Area.GetBoundsHashCode() == Battle.BattleRegion.Area.GetBoundsHashCode())
{
_BattlePreview.Refresh();
return;
}
_BattlePreview.Unregister();
_BattlePreview = null;
}
_BattlePreview = Battle.BattleRegion.DisplayPreview(ErrorHue, PreviewEffect, EffectRender.Darken);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
var regions = Region
.Regions.Not(r => r == null || !r.Registered || r is PvPRegion || r is RegionExtUtility.PreviewRegion)
.Where(r => r.Contains(User.Location, User.Map))
.ToArray();
if (regions.Length > 0)
{
var opts = new MenuGumpOptions();
regions.ForEach(
r => opts.AppendEntry(
new ListGumpEntry(
r.Name,
() =>
{
ClearPreview();
var prev = Preview;
Preview = false;
r.Area.ForEach(AddToList);
Preview = prev;
DisplayPreview();
})));
list.AppendEntry(new ListGumpEntry("Use Region...", b => Send(new MenuGump(User, Refresh(), opts, b))));
}
else
{
list.RemoveEntry("Use Region...");
}
base.CompileMenuOptions(list);
}
}
}

View File

@@ -0,0 +1,63 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictItemsListGump : PvPRestrictionListGump<Type>
{
public PvPBattleItemRestrictions ItemRestrictions => Restrictions as PvPBattleItemRestrictions;
public PvPRestrictItemsListGump(
Mobile user,
PvPBattleItemRestrictions res,
Gump parent = null,
bool useConfirm = true)
: base(user, res, parent, false, useConfirm)
{ }
protected override void CompileList(List<Type> list)
{
base.CompileList(list);
list.Sort((a, b) => (String.Compare(GetSearchKeyFor(a), GetSearchKeyFor(b), StringComparison.Ordinal)));
}
public override string GetSearchKeyFor(Type key)
{
return key != null ? key.Name : base.GetSearchKeyFor(null);
}
protected override string GetLabelText(int index, int pageIndex, Type entry)
{
return entry != null ? entry.Name : base.GetLabelText(index, pageIndex, null);
}
protected override string OnAddEntryGetHtml()
{
return base.OnAddEntryGetHtml() + "\nUse Type names derived from Item.\n" +
"Adding 'Item' itself will count for every derived type.";
}
protected override void OnAddEntryConfirm(GumpButton b, string text)
{
ItemRestrictions.SetRestricted(text, true);
Refresh(true);
}
}
}

View File

@@ -0,0 +1,59 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictPetsListGump : PvPRestrictionListGump<Type>
{
public PvPBattlePetRestrictions PetRestrictions => Restrictions as PvPBattlePetRestrictions;
public PvPRestrictPetsListGump(Mobile user, PvPBattlePetRestrictions res, Gump parent = null, bool useConfirm = true)
: base(user, res, parent, false, useConfirm)
{ }
protected override void CompileList(List<Type> list)
{
base.CompileList(list);
list.Sort((a, b) => (String.Compare(GetSearchKeyFor(a), GetSearchKeyFor(b), StringComparison.Ordinal)));
}
public override string GetSearchKeyFor(Type key)
{
return key != null ? key.Name : base.GetSearchKeyFor(null);
}
protected override string GetLabelText(int index, int pageIndex, Type entry)
{
return entry != null ? entry.Name : base.GetLabelText(index, pageIndex, null);
}
protected override string OnAddEntryGetHtml()
{
return base.OnAddEntryGetHtml() + "\nUse Type names derived from BaseCreature.\n" +
"Adding 'BaseCreature' itself will count for every derived type.";
}
protected override void OnAddEntryConfirm(GumpButton b, string text)
{
PetRestrictions.SetRestricted(text, true);
Refresh(true);
}
}
}

View File

@@ -0,0 +1,62 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictSkillsListGump : PvPRestrictionListGump<int>
{
public PvPBattleSkillRestrictions SkillRestrictions => Restrictions as PvPBattleSkillRestrictions;
public PvPRestrictSkillsListGump(
Mobile user,
PvPBattleSkillRestrictions res,
Gump parent = null,
bool useConfirm = true)
: base(user, res, parent, true, useConfirm)
{ }
protected override void CompileList(List<int> list)
{
base.CompileList(list);
list.Sort((a, b) => (String.Compare(GetSearchKeyFor(a), GetSearchKeyFor(b), StringComparison.Ordinal)));
}
public override string GetSearchKeyFor(int key)
{
return key >= 0 ? ((SkillName)key).ToString() : base.GetSearchKeyFor(key);
}
protected override string GetLabelText(int index, int pageIndex, int entry)
{
return entry < 0 ? "Unknown" : ((SkillName)entry).ToString();
}
protected override string OnAddEntryGetHtml()
{
return base.OnAddEntryGetHtml() + "\nUse skill names without spaces.\n";
}
protected override void OnAddEntryConfirm(GumpButton b, string text)
{
SkillRestrictions.SetRestricted(text, true);
Refresh(true);
}
}
}

View File

@@ -0,0 +1,63 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictSpellsListGump : PvPRestrictionListGump<Type>
{
public PvPBattleSpellRestrictions SpellRestrictions => Restrictions as PvPBattleSpellRestrictions;
public PvPRestrictSpellsListGump(
Mobile user,
PvPBattleSpellRestrictions res,
Gump parent = null,
bool useConfirm = true)
: base(user, res, parent, false, useConfirm)
{ }
protected override void CompileList(List<Type> list)
{
base.CompileList(list);
list.Sort((a, b) => (String.Compare(GetSearchKeyFor(a), GetSearchKeyFor(b), StringComparison.Ordinal)));
}
public override string GetSearchKeyFor(Type key)
{
return key != null ? key.Name : base.GetSearchKeyFor(null);
}
protected override string GetLabelText(int index, int pageIndex, Type entry)
{
return entry != null ? entry.Name : base.GetLabelText(index, pageIndex, null);
}
protected override string OnAddEntryGetHtml()
{
return base.OnAddEntryGetHtml() +
"\nUse Type names derived from Spell.\nAdding 'Spell' itself will count for every derived type.";
}
protected override void OnAddEntryConfirm(GumpButton b, string text)
{
SpellRestrictions.SetRestricted(text, true);
Refresh(true);
}
}
}

View File

@@ -0,0 +1,119 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictionListEntryGump<TKey> : MenuGump
{
public PvPRestrictionListEntryGump(
Mobile user,
PvPBattleRestrictionsBase<TKey> res,
Gump parent = null,
GumpButton clicked = null,
TKey key = default(TKey),
bool locked = false,
bool useConfirm = true)
: base(user, parent, clicked: clicked)
{
Restrictions = res;
Key = key;
Locked = locked;
UseConfirmDialog = useConfirm;
}
public PvPBattleRestrictionsBase<TKey> Restrictions { get; set; }
public TKey Key { get; set; }
public bool Locked { get; set; }
public bool UseConfirmDialog { get; set; }
protected override void CompileOptions(MenuGumpOptions list)
{
list.Clear();
if (User.AccessLevel >= AutoPvP.Access)
{
if (Restrictions.IsRestricted(Key))
{
list.AppendEntry(
new ListGumpEntry(
"Set Unrestricted",
button =>
{
Restrictions.SetRestricted(Key, false);
Refresh(true);
},
ErrorHue));
}
else
{
list.AppendEntry(
new ListGumpEntry(
"Set Restricted",
button =>
{
Restrictions.SetRestricted(Key, true);
Refresh(true);
},
HighlightHue));
}
if (!Locked && User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
new ListGumpEntry(
"Delete",
button =>
{
if (UseConfirmDialog)
{
Send(
new ConfirmDialogGump(
User,
Refresh(),
title: "Delete Entry?",
html:
"All data associated with this entry will be deleted.\nThis action can not be reversed!\nDo you want to continue?",
onAccept: OnConfirmDelete));
}
else
{
OnConfirmDelete(button);
}
}));
}
}
base.CompileOptions(list);
list.Replace("Cancel", new ListGumpEntry("Done", Cancel));
}
protected virtual void OnConfirmDelete(GumpButton button)
{
if (Selected == null)
{
Close();
return;
}
Restrictions.Remove(Key);
Close();
}
}
}

View File

@@ -0,0 +1,216 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Collections.Generic;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPRestrictionListGump<TKey> : ListGump<TKey>
{
private const string _HelpText = "Restrictions: Lists specific restrictions for this battle.";
public PvPBattleRestrictionsBase<TKey> Restrictions { get; set; }
public virtual bool Locked { get; set; }
public virtual bool UseConfirmDialog { get; set; }
public PvPRestrictionListGump(
Mobile user,
PvPBattleRestrictionsBase<TKey> res,
Gump parent = null,
bool locked = true,
bool useConfirm = true)
: base(
user,
parent,
emptyText: "There are no restrictions to display.",
title: res != null ? res.ToString() : "Restrictions")
{
Restrictions = res;
Locked = locked;
UseConfirmDialog = useConfirm;
ForceRecompile = true;
}
protected override void CompileList(List<TKey> list)
{
list.Clear();
list.AddRange(Restrictions.List.Keys);
base.CompileList(list);
}
protected override int GetLabelHue(int index, int pageIndex, TKey entry)
{
return entry != null
? (Restrictions.IsRestricted(entry) ? ErrorHue : HighlightHue)
: base.GetLabelHue(index, pageIndex, default(TKey));
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.AppendEntry(new ListGumpEntry("Restrict All", OnRestrictAll, HighlightHue));
list.AppendEntry(new ListGumpEntry("Unrestrict All", OnUnrestrictAll, HighlightHue));
list.AppendEntry(new ListGumpEntry("Invert All", OnInvertAll, HighlightHue));
if (!Locked && User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(new ListGumpEntry("Delete All", OnDeleteAll, HighlightHue));
list.AppendEntry(new ListGumpEntry("Add Entry", OnAddRestriction, HighlightHue));
}
list.AppendEntry(new ListGumpEntry("Help", ShowHelp));
base.CompileMenuOptions(list);
}
protected virtual void ShowHelp(GumpButton button)
{
if (User != null && !User.Deleted)
{
new NoticeDialogGump(User, this, null, null, "Help", _HelpText).Send();
}
}
protected virtual void OnDeleteAll(GumpButton button)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Delete All Entries?",
Html = "All entries in the " + Restrictions + " will be deleted, erasing all data associated with them.\n" +
"This action can not be undone.\n\nDo you want to continue?",
AcceptHandler = b =>
{
Restrictions.Clear();
Refresh(true);
},
CancelHandler = Refresh
}.Send();
}
else
{
Restrictions.Clear();
Refresh(true);
}
}
protected virtual void OnRestrictAll(GumpButton button)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Restrict All Entries?",
Html = "All entries in the " + Restrictions + " will be restricted.\n" +
"This action can not be undone.\n\nDo you want to continue?",
AcceptHandler = b =>
{
Restrictions.Reset(true);
Refresh(true);
},
CancelHandler = Refresh
}.Send();
}
else
{
Restrictions.Reset(true);
Refresh(true);
}
}
protected virtual void OnUnrestrictAll(GumpButton button)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Unrestrict All Entries?",
Html = "All entries in the " + Restrictions + " will be unrestricted.\n" +
"This action can not be undone.\n\nDo you want to continue?",
AcceptHandler = b =>
{
Restrictions.Reset(false);
Refresh(true);
},
CancelHandler = Refresh
}.Send();
}
else
{
Restrictions.Reset(false);
Refresh(true);
}
}
protected virtual void OnInvertAll(GumpButton button)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, this)
{
Title = "Invert All Entries?",
Html = "All entries in the " + Restrictions + " will be toggled to their opposite setting.\n" +
"This action can not be undone.\n\nDo you want to continue?",
AcceptHandler = b =>
{
Restrictions.Invert();
Refresh(true);
},
CancelHandler = Refresh
}.Send();
}
else
{
Restrictions.Invert();
Refresh(true);
}
}
protected virtual void OnAddRestriction(GumpButton button)
{
new InputDialogGump(User, this)
{
Title = "Add Restriction",
Html = OnAddEntryGetHtml(),
Callback = OnAddEntryConfirm,
CancelHandler = Refresh
}.Send();
}
protected virtual string OnAddEntryGetHtml()
{
return "Add an entry by name.";
}
protected virtual void OnAddEntryConfirm(GumpButton b, string text)
{ }
protected override void SelectEntry(GumpButton button, TKey entry)
{
base.SelectEntry(button, entry);
if (button != null && entry != null)
{
new PvPRestrictionListEntryGump<TKey>(User, Restrictions, Refresh(), button, entry, Locked, UseConfirmDialog)
.Send();
}
}
}
}

View File

@@ -0,0 +1,84 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPScenarioUI : HtmlPanelGump<PvPScenario>
{
public bool UseConfirmDialog { get; set; }
public PvPScenarioUI(Mobile user, PvPScenario scenario, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "No scenario selected.", title: "PvP Scenario Overview", selected: scenario)
{
UseConfirmDialog = useConfirm;
}
protected override void Compile()
{
base.Compile();
if (Selected != null)
{
Html = Selected.ToHtmlString(User);
}
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
if (Selected != null && User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry("Create Battle", OnCreate, HighlightHue);
}
base.CompileMenuOptions(list);
}
private void OnCreate(GumpButton b)
{
if (UseConfirmDialog)
{
new ConfirmDialogGump(User, Hide(true))
{
Title = "Create New Battle?",
Html = "This action will create a new battle from the selected scenario.\nDo you want to continue?",
AcceptHandler = OnConfirmCreateBattle,
CancelHandler = Refresh
}.Send();
}
else
{
OnConfirmCreateBattle(b);
}
}
protected virtual void OnConfirmCreateBattle(GumpButton button)
{
if (Selected == null)
{
Close();
return;
}
var battle = AutoPvP.CreateBattle(Selected);
Close(true);
PvPBattlesUI.DisplayTo(User, battle, false);
}
}
}

View File

@@ -0,0 +1,71 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPScenariosUI : ListGump<PvPScenario>
{
public bool UseConfirmDialog { get; set; }
public PvPScenariosUI(Mobile user, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "There are no scenarios to display.", title: "PvP Scenarios")
{
UseConfirmDialog = useConfirm;
ForceRecompile = true;
Width = 600;
Columns = 3;
EntriesPerPage = 12;
}
public override string GetSearchKeyFor(PvPScenario key)
{
return key != null ? key.Name : base.GetSearchKeyFor(null);
}
protected override string GetLabelText(int index, int pageIndex, PvPScenario entry)
{
return entry != null
? String.Format("{0} ({1})", entry.Name, entry.TypeOf.Name)
: base.GetLabelText(index, pageIndex, null);
}
protected override void CompileList(List<PvPScenario> list)
{
list.Clear();
list.AddRange(AutoPvP.Scenarios);
base.CompileList(list);
}
protected override void SelectEntry(GumpButton button, PvPScenario entry)
{
base.SelectEntry(button, entry);
if (button != null && entry != null)
{
new PvPScenarioUI(User, entry, Hide(true), UseConfirmDialog).Send();
}
}
}
}

View File

@@ -0,0 +1,149 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public class PvPTeamUI : HtmlPanelGump<PvPTeam>
{
public bool UseConfirmDialog { get; set; }
public PvPTeamUI(Mobile user, PvPTeam battle, Gump parent = null, bool useConfirm = true)
: base(user, parent, emptyText: "No team selected.", title: "PvP Team Overview", selected: battle)
{
UseConfirmDialog = useConfirm;
ForceRecompile = true;
}
protected override void Compile()
{
base.Compile();
if (Selected == null || Selected.Deleted)
{
return;
}
Html = String.Empty;
if (User.AccessLevel >= AutoPvP.Access)
{
var errors = new List<string>();
if (!Selected.Validate(User, errors))
{
Html += "*This team has failed validation*\n\n".WrapUOHtmlTag("BIG").WrapUOHtmlColor(Color.OrangeRed, false);
Html += String.Join("\n", errors).WrapUOHtmlColor(Color.Yellow);
Html += "\n\n";
}
}
Html += Selected.ToHtmlString(User);
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
list.Clear();
if (Selected != null && !Selected.Deleted)
{
if (User.AccessLevel >= AutoPvP.Access)
{
list.AppendEntry(
new ListGumpEntry(
"Edit Options",
b =>
{
Minimize();
User.SendGump(new PropertiesGump(User, Selected));
},
HighlightHue));
list.AppendEntry(
new ListGumpEntry(
"Delete",
b =>
{
if (UseConfirmDialog)
{
Send(
new ConfirmDialogGump(
User,
this,
title: "Delete Team?",
html:
"All data associated with this team will be deleted.\nThis action can not be reversed!\nDo you want to continue?",
onAccept: OnConfirmDeleteTeam));
}
else
{
OnConfirmDeleteTeam(b);
}
},
HighlightHue));
}
var user = User as PlayerMobile;
if (user != null)
{
if (Selected.Battle.IsParticipant(user, out var team))
{
if (team == Selected)
{
list.AppendEntry(new ListGumpEntry("Quit & Leave", b => Selected.Battle.Quit(User, true)));
}
}
else
{
if (Selected.Battle.IsQueued(user))
{
if (Selected.Battle.Queue[user] == Selected)
{
list.AppendEntry(new ListGumpEntry("Leave Queue", b => Selected.Battle.Dequeue(user)));
}
}
else if (!Selected.Battle.AutoAssign && Selected.Battle.CanQueue(user))
{
list.AppendEntry(new ListGumpEntry("Join Queue", b => Selected.Battle.Enqueue(user, Selected)));
}
}
}
}
base.CompileMenuOptions(list);
}
protected virtual void OnConfirmDeleteTeam(GumpButton button)
{
if (Selected == null || Selected.Deleted)
{
Close();
return;
}
Selected.Delete();
Close();
}
}
}

View File

@@ -0,0 +1,122 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Modules.AutoPvP
{
public delegate T BattleNotorietyHandler<out T>(PlayerMobile x, PlayerMobile y);
public static class BattleNotoriety
{
public const int Bubble = -1;
public static void Enable()
{
NotoUtility.RegisterNameHandler(MobileNotoriety, Int32.MaxValue - 100);
NotoUtility.RegisterBeneficialHandler(AllowBeneficial, Int32.MaxValue - 100);
NotoUtility.RegisterHarmfulHandler(AllowHarmful, Int32.MaxValue - 100);
}
public static void Disable()
{
NotoUtility.UnregisterNameHandler(MobileNotoriety);
NotoUtility.UnregisterBeneficialHandler(AllowBeneficial);
NotoUtility.UnregisterHarmfulHandler(AllowHarmful);
}
public static bool AllowBeneficial(Mobile a, Mobile b, out bool handled)
{
handled = false;
if (!AutoPvP.CMOptions.ModuleEnabled)
{
return false;
}
if (NotoUtility.Resolve(a, b, out PlayerMobile x, out PlayerMobile y))
{
var battle = AutoPvP.FindBattle(y);
if (battle != null && !battle.Deleted)
{
var allow = battle.AllowBeneficial(a, b, out handled);
if (handled)
{
return allow;
}
}
}
return false;
}
public static bool AllowHarmful(Mobile a, Mobile b, out bool handled)
{
handled = false;
if (!AutoPvP.CMOptions.ModuleEnabled)
{
return false;
}
if (NotoUtility.Resolve(a, b, out PlayerMobile x, out PlayerMobile y))
{
var battle = AutoPvP.FindBattle(y);
if (battle != null && !battle.Deleted)
{
var allow = battle.AllowHarmful(a, b, out handled);
if (handled)
{
return allow;
}
}
}
return false;
}
public static int MobileNotoriety(Mobile a, Mobile b, out bool handled)
{
handled = false;
if (!AutoPvP.CMOptions.ModuleEnabled)
{
return Bubble;
}
if (NotoUtility.Resolve(a, b, out PlayerMobile x, out PlayerMobile y))
{
var battle = AutoPvP.FindBattle(y);
if (battle != null && !battle.Deleted)
{
var result = battle.NotorietyHandler(a, b, out handled);
if (handled)
{
return result;
}
}
}
return Bubble;
}
}
}