Updates Packets & Randomizer (#43)

* Fixes a bug with the main loop. Removes unnecessary optimizations for RDRand.

* WIP - Rewriting packets.

* Cleanup and updates README

* Converts more packets

* Fixes header

* Converts Effects packets.

* Forgot the send command

* Adds the start of containers packets.

* Adds message packets with caching

* Extends the send methods

* Starts to add Acquire methods

* Converted the packets

* Cleanup

* Cleanup

* Adds more packets

* Adds more packets

* Fixes clearing arrays from pool. Adds Mobile Incoming

* Converts more packets.

* Moves more packets

* Moves more packets

* Test compression

* Merges

* Migrating to an idiomatic syntax that also supports compression, and proxying.

* Optimize the stack alloc. Changes attributes

* Converted container packets

* Visual Studio doesn't auto save files. I am still getting used to subpar IDEs.

* Adds static packet caching. Will profile later. Converts more packets

* Fixes packets and changes how compression is configured

* WIP - Adds basics for Gumps. Not finished though.

* Fix file

* Fixes formatting

* Changed SpanWriter to be more idiomatic.

* Fixes Span vs RawSpan and missing stackallocs

* Converts over some more gumps

* WIP - Deletes 32bit support.

* Drops RDRand32 support.

* Fixes gump compilation

* Converting gump components

* Removes old huffman compression function

* Revert signature for backwards compatibility

* WIP - Converting more gump components

* Creates ArraySet for the strings. Updates AppendTo to reference that.

* Converts the maining gump components

* Cleans up gump components

* Cleans up directives

* Cleans up ArraySet and moves it. Adds null-coalescing-assignment

* Cleanup, Target Packets, and C# 8 changes.

* Removed OPL Packet

* World packets

* Fixing packet uses

* Cleans up code. Fixes packet uses in various places.

* More cleanup for packets

* Code cleanup

* Converts more packet uses and cleans up more code

* More code cleanup

* Finishes fixing the packets in Item

* Updates secure trade packets

* Updates core and gets it to compile.

* Moved packets to scripts. Fixed account handler use of packets

* Code cleanup

* Updates chat packets

* Code cleanuo

* Adds party packets, but need to implement them.

* Party packets WIP

* Finishes party packets

* Rearrange movement namespaces and classes

* Finishes plant packets

* Code Formatting

* Fixes moving effects

* Code cleanup, eliminates equipinfo

* Adds more packets. Fixes bugs with various packets.

* Finishes mahjon packets

* Fixes mahjong packet

* Code cleanup

* Finishes mahjong packets

* Adds Map packets

* Add multifacet maps and charts

* Cleans up some packets with UTF8

* Optimizes packets

* Cleans up more packets. Moves the MessageHelper

* Removes assistant support. Removes extended protocol. Incorporates MapUO packets as normal packets.

* Updates protocol extensions packet receiver

* Fixes a few bugs. Fixes a few more packets.

* Code cleanup and fixing more packets

* Fixes packet effects

* Cleaned up more code

* Buff Icon cleanup

* Removed unused constructors

* Code Cleanup. Adds BoatHS Packets

* Moves house files. Updates house foundation packets.

* Deployment cleanup

* Fixes:

* Code cleanup

* More code cleanup

* More code cleanup

* Cleaned up BaseHouse

* Enforces styling

* Converts foreach to linq where possible.

* Dont need that

* Goals/Readme updates

* Removes 32bit support at the highest level. Turns on HRT by default.

* Code cleanup. Fixes extended features packet.

* Fixes various bugs

* Code cleanup

* Code cleanup

* Code cleanup. Fixes gump X/Y assignment.

* Code cleanup using |= operator

* More code cleanup

* Cleanup

* Fixes spacing issues. Thanks Visual Studio. You suck.

* Compiler error

* Fixes NPE from RunUO 2.7

* Renames ScriptCompiler to AssemblyHandler. Fixes packets. Updates README

* Fixes more packets. Stupid trailing nulls.

* Fixes various bugs.

* Fixes for gumps

* Fixes more gump stuff. Going to split it out later since it is getting insane

* Recoded the gump writing

* WIP

* *Added output path of scripts project to dev branch
*Activated debugging in code
This commit is contained in:
Kamron Batman 2019-11-11 03:40:16 -08:00 committed by 3HMonkey
parent 7aa8fd3df1
commit 179cb50557
588 changed files with 10843 additions and 16177 deletions

View file

@ -4,7 +4,6 @@ using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Prompts;
namespace Server.Engines.BulkOrders
{

View file

@ -1,7 +1,6 @@
using System.Collections.Generic;
using Server.Gumps;
using Server.Multis;
using Server.Prompts;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Items;

View file

@ -1,3 +1,4 @@
using System.Linq;
using Server.Mobiles;
namespace Server.Engines.BulkOrders

View file

@ -2,7 +2,7 @@ namespace Server.Engines.BulkOrders
{
public class LargeTailorBOD : LargeBOD
{
public static double[] m_TailoringMaterialChances =
public static readonly double[] m_TailoringMaterialChances =
{
0.857421875, // None
0.125000000, // Spined
@ -19,7 +19,6 @@ namespace Server.Engines.BulkOrders
switch (Utility.Random(14))
{
default:
case 0:
entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Farmer);
break;
case 1:

View file

@ -357,7 +357,14 @@ namespace Server.Engines.BulkOrders
int[][][] goldTable = m_GoldTable;
int typeIndex = ComputeType(type, itemCount);
int quanIndex = quantity == 20 ? 2 : quantity == 15 ? 1 : 0;
int quanIndex = quantity switch
{
20 => 2,
15 => 1,
_ => 0
};
int mtrlIndex = material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite
? 1 + (material - BulkMaterialType.DullCopper)
: 0;
@ -599,11 +606,28 @@ namespace Server.Engines.BulkOrders
{
int[][][] goldTable = Core.AOS ? m_AosGoldTable : m_OldGoldTable;
int typeIndex = (itemCount == 6 ? 3 : itemCount == 5 ? 2 : itemCount == 4 ? 1 : 0) * 2 + (exceptional ? 1 : 0);
int quanIndex = quantity == 20 ? 2 : quantity == 15 ? 1 : 0;
int mtrlIndex = material == BulkMaterialType.Barbed ? 3 :
material == BulkMaterialType.Horned ? 2 :
material == BulkMaterialType.Spined ? 1 : 0;
int typeIndex = itemCount switch
{
6 => 3,
5 => 2,
4 => 1,
_ => 0
} * 2 + (exceptional ? 1 : 0);
int quanIndex = quantity switch
{
20 => 2,
15 => 1,
_ => 0
};
int mtrlIndex = material switch
{
BulkMaterialType.Barbed => 3,
BulkMaterialType.Horned => 2,
BulkMaterialType.Spined => 1,
_ => 0
};
int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
@ -615,7 +639,7 @@ namespace Server.Engines.BulkOrders
#region Constructors
private static int[][] m_ClothHues =
private static readonly int[][] m_ClothHues =
{
new[] { 0x483, 0x48C, 0x488, 0x48A },
new[] { 0x495, 0x48B, 0x486, 0x485 },
@ -678,13 +702,15 @@ namespace Server.Engines.BulkOrders
};
}
private static Item CreateRunicKit(int type)
{
if (type >= 1 && type <= 3)
return new RunicSewingKit(CraftResource.RegularLeather + type, 60 - type * 15);
private static Item CreateRunicKit(int type) =>
type >= 1 && type <= 3
? new RunicSewingKit(CraftResource.RegularLeather + type, 60 - type * 15)
: throw new InvalidOperationException();
throw new InvalidOperationException();
}
private static Item CreatePowerScroll(int type) =>
type == 5 || type == 10 || type == 15 || type == 20
? new PowerScroll(SkillName.Tailoring, 100 + type)
: throw new InvalidOperationException();
private static Item CreatePowerScroll(int type)
{

View file

@ -65,22 +65,16 @@ namespace Server.Engines.CannedEvil
Skull = null;
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
{
from.SendLocalizedMessage(500446); // That is too far away.
}
else if (!Harrower.CanSpawn)
{
from.SendMessage("The harrower has already been spawned.");
}
else if (m_Skull == null)
{
from.SendLocalizedMessage(1049485); // What would you like to sacrifice?
from.Target = new SacrificeTarget(this);
}
else
{
SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull!
}
SendLocalizedMessageTo(from, 1049487); // I already have my champions awakening skull!
}
public void EndSacrifice(Mobile from, ChampionSkull skull)
@ -92,25 +86,15 @@ namespace Server.Engines.CannedEvil
Skull = null;
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
{
from.SendLocalizedMessage(500446); // That is too far away.
}
else if (!Harrower.CanSpawn)
{
from.SendMessage("The harrower has already been spawned.");
}
else if (skull == null)
{
SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull!
}
SendLocalizedMessageTo(from, 1049488); // That is not my champions awakening skull!
else if (m_Skull != null)
{
SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull!
}
SendLocalizedMessageTo(from, 1049487); // I already have my champions awakening skull!
else if (!skull.IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1049486); // You can only sacrifice items that are in your backpack!
}
else
{
if (skull.Type == Type)
@ -121,9 +105,7 @@ namespace Server.Engines.CannedEvil
Skull = skull;
}
else
{
SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull!
}
SendLocalizedMessageTo(from, 1049488); // That is not my champions awakening skull!
}
}

View file

@ -950,24 +950,24 @@ namespace Server.Engines.CannedEvil
Dictionary<Mobile, int> validEntries = new Dictionary<Mobile, int>();
foreach (KeyValuePair<Mobile, int> kvp in m_DamageEntries)
if (IsEligible(kvp.Key, artifact))
foreach (var (key, value) in m_DamageEntries)
if (IsEligible(key, artifact))
{
validEntries.Add(kvp.Key, kvp.Value);
totalDamage += kvp.Value;
validEntries.Add(key, value);
totalDamage += value;
}
int randomDamage = Utility.RandomMinMax(1, totalDamage);
totalDamage = 0;
foreach (KeyValuePair<Mobile, int> kvp in validEntries)
foreach (var (key, value) in validEntries)
{
totalDamage += kvp.Value;
totalDamage += value;
if (totalDamage >= randomDamage)
{
GiveArtifact(kvp.Key, artifact);
GiveArtifact(key, artifact);
return;
}
}
@ -1001,10 +1001,10 @@ namespace Server.Engines.CannedEvil
writer.Write(m_SPawnSzMod);
writer.Write(m_DamageEntries.Count);
foreach (KeyValuePair<Mobile, int> kvp in m_DamageEntries)
foreach (var (key, value) in m_DamageEntries)
{
writer.Write(kvp.Key);
writer.Write(kvp.Value);
writer.Write(key);
writer.Write(value);
}
writer.Write(ConfinedRoaming);

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
namespace Server.Engines.Chat
{
@ -401,18 +402,7 @@ namespace Server.Engines.Chat
}
}
public static Channel FindChannelByName(string name)
{
for (int i = 0; i < Channels.Count; ++i)
{
Channel channel = Channels[i];
if (channel.m_Name == name)
return channel;
}
return null;
}
public static Channel FindChannelByName(string name) => Channels.FirstOrDefault(channel => channel.m_Name == name);
public static void Initialize()
{

View file

@ -1,12 +1,13 @@
using System;
using System.IO;
using System.Linq;
using Server.Accounting;
using Server.Misc;
using Server.Network;
namespace Server.Engines.Chat
{
public class ChatSystem
public static class ChatSystem
{
public static bool Enabled{ get; set; } = true;
@ -18,7 +19,7 @@ namespace Server.Engines.Chat
public static void SendCommandTo(Mobile to, ChatCommand type, string param1 = null, string param2 = null)
{
to?.Send(new ChatMessagePacket(null, (int)type + 20, param1, param2));
ChatPackets.SendChatMessage(to?.NetState, null, (int)type + 20, param1, param2);
}
public static void OpenChatWindowRequest(NetState state, PacketReader pvSrc)
@ -61,21 +62,11 @@ namespace Server.Engines.Chat
{
// TODO: Optimize this search
foreach (Account checkAccount in Accounts.GetAccounts())
if (Accounts.GetAccounts().Cast<Account>().Any(checkAccount => Insensitive.Equals(checkAccount.GetTag("ChatName")?.Trim(), chatName)))
{
string existingName = checkAccount.GetTag("ChatName");
if (existingName != null)
{
existingName = existingName.Trim();
if (Insensitive.Equals(existingName, chatName))
{
from.SendMessage("Nickname already in use.");
SendCommandTo(from, ChatCommand.AskNewNickname);
return;
}
}
from.SendMessage("Nickname already in use.");
SendCommandTo(from, ChatCommand.AskNewNickname);
return;
}
accountChatName = chatName;
@ -129,17 +120,15 @@ namespace Server.Engines.Chat
if (handler.RequireConference && channel == null)
user.SendMessage(31); /* You must be in a conference to do this.
* To join a conference, select one from the Conference menu.
*/
* To join a conference, select one from the Conference menu.
*/
else if (handler.RequireModerator && !user.IsModerator)
user.SendMessage(29); // You must have operator status to do this.
else
handler.Callback(user, channel, param);
}
else
{
Console.WriteLine("Client: {0}: Unknown chat action 0x{1:X}: {2}", state, actionID, param);
}
}
catch (Exception e)
{
@ -147,4 +136,4 @@ namespace Server.Engines.Chat
}
}
}
}
}

View file

@ -1,6 +1,6 @@
namespace Server.Engines.Chat
{
public class ChatActionHandlers
public static class ChatActionHandlers
{
private static ChatActionHandler[] m_Handlers;
@ -112,8 +112,8 @@ namespace Server.Engines.Chat
{
from.IgnorePrivateMessage = true;
from.SendMessage(38); /* You will no longer receive private messages.
* Those who send you a message will be notified that you are blocking incoming messages.
*/
* Those who send you a message will be notified that you are blocking incoming messages.
*/
}
public static void TogglePrivateMessages(ChatUser from, Channel channel, string param)

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Server.Accounting;
namespace Server.Engines.Chat
@ -64,16 +65,14 @@ namespace Server.Engines.Chat
return false;
}
public void SendMessage(int number, string param1 = null, string param2 = null)
public void SendMessage(int number, string param1 = "", string param2 = "")
{
if (Mobile.NetState != null)
Mobile.Send(new ChatMessagePacket(Mobile, number, param1, param2));
ChatPackets.SendChatMessage(Mobile.NetState, Mobile, number, param1, param2);
}
public void SendMessage(int number, Mobile from, string param1, string param2)
public void SendMessage(int number, Mobile from, string param1 = "", string param2 = "")
{
if (Mobile.NetState != null)
Mobile.Send(new ChatMessagePacket(from, number, param1, param2));
ChatPackets.SendChatMessage(Mobile.NetState, from, number, param1, param2);
}
public bool IsIgnored(ChatUser check) => Ignored.Contains(check);
@ -81,9 +80,7 @@ namespace Server.Engines.Chat
public void AddIgnored(ChatUser user)
{
if (IsIgnored(user))
{
SendMessage(22, user.Username); // You are already ignoring %1.
}
else
{
Ignored.Add(user);
@ -106,9 +103,7 @@ namespace Server.Engines.Chat
SendMessage(26); // You are no longer ignoring anyone.
}
else
{
SendMessage(25, user.Username); // You are not ignoring %1.
}
}
public static ChatUser AddChatUser(Mobile from)
@ -172,18 +167,7 @@ namespace Server.Engines.Chat
return c;
}
public static ChatUser GetChatUser(string username)
{
for (int i = 0; i < m_Users.Count; ++i)
{
ChatUser user = m_Users[i];
if (user.Username == username)
return user;
}
return null;
}
public static ChatUser GetChatUser(string username) => m_Users.FirstOrDefault(user => user.Username == username);
public static void GlobalSendCommand(ChatCommand command, string param1, string param2 = null)
{

View file

@ -1,6 +1,6 @@
namespace Server.Chat
{
public class ChatSystem
public static class ChatSystem
{
public static void Initialize()
{
@ -12,4 +12,4 @@ namespace Server.Chat
e.Mobile.SendMessage("Chat is not currently supported.");
}
}
}
}

View file

@ -1,28 +1,36 @@
using Server.Buffers;
using Server.Network;
namespace Server.Engines.Chat
{
public sealed class ChatMessagePacket : Packet
public static class ChatPackets
{
public ChatMessagePacket(Mobile who, int number, string param1, string param2) : base(0xB2)
public static void SendChatMessage(NetState ns, Mobile who, int number, string param1, string param2)
{
if (param1 == null)
param1 = string.Empty;
if (ns == null)
return;
if (param2 == null)
param2 = string.Empty;
param1 ??= "";
param2 ??= "";
EnsureCapacity(13 + (param1.Length + param2.Length) * 2);
int length = 13 + (param1.Length + param2.Length) * 2;
//base(0xB2)
m_Stream.Write((ushort)(number - 20));
SpanWriter writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xB2); // Packet ID
writer.Write((ushort)length); // Dynamic Length
writer.Write((ushort)(number - 20));
if (who != null)
m_Stream.WriteAsciiFixed(who.Language, 4);
writer.WriteAsciiFixed(who.Language, 4);
else
m_Stream.Write(0);
writer.Position += 4;
m_Stream.WriteBigUniNull(param1);
m_Stream.WriteBigUniNull(param2);
writer.WriteBigUniNull(param1);
writer.WriteBigUniNull(param2);
ns.Send(writer.Span);
}
}
}
}

View file

@ -512,7 +512,7 @@ namespace Server.Engines.ConPVP
if (offset < offsets.Length)
p = offsets[offset++];
else
p = offsets[offsets.Length - 1];
p = offsets[^1];
p.X = p.X * matrix[0, 0] + p.Y * matrix[0, 1];
p.Y = p.X * matrix[1, 0] + p.Y * matrix[1, 1];
@ -574,12 +574,15 @@ namespace Server.Engines.ConPVP
if (hasBounds)
{
List<Mobile> pets = new List<Mobile>();
IPooledEnumerable eable = facet.GetMobilesInBounds(m_Bounds);
foreach (Mobile mob in facet.GetMobilesInBounds(m_Bounds))
foreach (Mobile mob in eable)
if (mob is BaseCreature pet && pet.Controlled && pet.ControlMaster != null &&
Players.Contains(pet.ControlMaster))
pets.Add(pet);
eable.Free();
foreach (Mobile pet in pets)
{
pet.Combatant = null;
@ -749,7 +752,7 @@ namespace Server.Engines.ConPVP
#region Offsets & Rotation
private static Point2D[] m_EdgeOffsets =
private static readonly Point2D[] m_EdgeOffsets =
{
/*
* /\
@ -772,7 +775,7 @@ namespace Server.Engines.ConPVP
};
// nw corner
private static Point2D[] m_CornerOffsets =
private static readonly Point2D[] m_CornerOffsets =
{
/*
* /\
@ -793,7 +796,7 @@ namespace Server.Engines.ConPVP
new Point2D(3, 0)
};
private static int[][,] m_Rotate =
private static readonly int[][,] m_Rotate =
{
new[,] { { +1, 0 }, { 0, +1 } }, // west
new[,] { { -1, 0 }, { 0, -1 } }, // east

View file

@ -160,7 +160,7 @@ namespace Server.Engines.ConPVP
if (spell is RecallSpell)
from.SendMessage("You may not cast this spell.");
string title = null;
string title;
string option;
if (spell is ArcanistSpell)
@ -854,16 +854,9 @@ namespace Server.Engines.ConPVP
Participant p = Participants[i];
if (p.Eliminated)
{
++eliminated;
if (eliminated == Participants.Count - 1)
hasWinner = true;
}
hasWinner |= ++eliminated == Participants.Count - 1;
else
{
winner = p;
}
}
return hasWinner ? winner ?? Participants[0] : null;
@ -1630,16 +1623,7 @@ namespace Server.Engines.ConPVP
int rx = dx - dy;
int ry = dx + dy;
bool eastToWest;
if (rx >= 0 && ry >= 0)
eastToWest = false;
else if (rx >= 0)
eastToWest = true;
else if (ry >= 0)
eastToWest = true;
else
eastToWest = false;
bool eastToWest = (rx < 0 || ry < 0) && (rx >= 0 || ry >= 0);
Effects.PlaySound(wall, Arena.Facet, 0x1F6);
@ -1817,9 +1801,7 @@ namespace Server.Engines.ConPVP
}
}
else
{
defs = basedef.Options;
}
int changes = 0;
@ -1999,9 +1981,7 @@ namespace Server.Engines.ConPVP
if (!Registered)
return;
if (count != -1)
StartedReadyCountdown = true;
StartedReadyCountdown |= count != -1;
ReadyCount = count;
if (count == 0)

View file

@ -293,7 +293,7 @@ namespace Server.Engines.ConPVP
if (list.Count > 0)
{
Point3D p = list[list.Count - 1];
Point3D p = list[^1];
if (p.X != ix || p.Y != iy || p.Z != iz)
list.Add(new Point3D(ix, iy, iz));
@ -308,7 +308,7 @@ namespace Server.Engines.ConPVP
z += zslp;
}
if (list.Count > 0 && list[list.Count - 1] != dest)
if (list.Count > 0 && list[^1] != dest)
list.Add(dest);
/*if ( dist3d > 4 && ( dest.X != org.X || dest.Y != org.Y ) )
@ -429,10 +429,7 @@ namespace Server.Engines.ConPVP
if (t.Z <= point.Z && t.Z + height >= point.Z &&
(id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) != 0)
{
if (i > m_PathIdx)
point = m_Path[i - 1];
else
point = GetWorldLocation();
point = i > m_PathIdx ? m_Path[i - 1] : GetWorldLocation();
HitObject(point, t.Z, height);
return;
}
@ -448,13 +445,9 @@ namespace Server.Engines.ConPVP
continue;
if (i is BRGoal)
{
height = 17;
}
else if (i is Blocker)
{
height = 20;
}
else
{
ItemData id = i.ItemData;
@ -473,10 +466,7 @@ namespace Server.Engines.ConPVP
(i is Blocker || loc.Z <= point.Z && loc.Z + height >= point.Z))
{
found = true;
if (j > m_PathIdx)
point = m_Path[j - 1];
else
point = GetWorldLocation();
point = j > m_PathIdx ? m_Path[j - 1] : GetWorldLocation();
break;
}
}
@ -494,9 +484,7 @@ namespace Server.Engines.ConPVP
HitObject(point, loc.Z, height);
}
else
{
HitObject(point, loc.Z, height);
}
return;
}
@ -511,12 +499,11 @@ namespace Server.Engines.ConPVP
if (m == null || m == Thrower)
continue;
Point3D point;
Point3D loc = m.Location;
for (int j = m_PathIdx; j < pathCheckEnd && !found; j++)
{
point = m_Path[j];
Point3D point = m_Path[j];
if (loc.X == point.X && loc.Y == point.Y &&
loc.Z <= point.Z && loc.Z + 16 >= point.Z)
@ -550,9 +537,10 @@ namespace Server.Engines.ConPVP
else if (m_Path.Count > 0)
MoveToWorld(m_Path.Last);
int myZ = Map.GetAverageZ(X, Y);
int myZ = Map?.GetAverageZ(X, Y) ?? 0;
StaticTile[] statics = Map?.Tiles?.GetStaticTiles(X, Y, true) ?? new StaticTile[0];
StaticTile[] statics = Map.Tiles.GetStaticTiles(X, Y, true);
for (int j = 0; j < statics.Length; j++)
{
StaticTile t = statics[j];
@ -676,7 +664,7 @@ namespace Server.Engines.ConPVP
if (m_Bomb.Parent == null && m_Bomb.m_Game?.Controller != null)
{
if (!m_Bomb.m_Flying && m_Bomb.Map != Map.Internal)
Effects.SendLocationEffect(m_Bomb.GetWorldLocation(), m_Bomb.Map, 0x377A, 16, 10, m_Bomb.Hue, 0);
Effects.SendLocationEffect(m_Bomb.GetWorldLocation(), m_Bomb.Map, 0x377A, 16, 10, m_Bomb.Hue);
if (m_Bomb.Location != m_Bomb.m_Game.Controller.BombHome)
{
@ -983,9 +971,7 @@ namespace Server.Engines.ConPVP
total = entries.Count;
}
else
foreach (BRPlayerInfo player in section.Players.Values)
if (player.Score > 0)
total++;
total += section.Players.Values.Count(player => player.Score > 0);
entries.Sort();
@ -1722,12 +1708,13 @@ namespace Server.Engines.ConPVP
for (int i = 0; i < m_Context.Participants.Count; ++i)
{
if (!(m_Context.Participants[i] is Participant p) || p.Players == null)
DuelPlayer[] players = m_Context.Participants[i]?.Players;
if (players == null)
continue;
for (int j = 0; j < p.Players.Length; ++j)
for (int j = 0; j < players.Length; ++j)
{
DuelPlayer dp = p.Players[j];
DuelPlayer dp = players[j];
if (dp?.Mobile != null)
{
@ -1736,16 +1723,16 @@ namespace Server.Engines.ConPVP
}
}
if (i == winner.TeamID)
if (i == winner?.TeamID)
continue;
if (p.Players != null)
for (int j = 0; j < p.Players.Length; ++j)
if (p.Players[j] != null)
p.Players[j].Eliminated = true;
for (int j = 0; j < players.Length; ++j)
if (players[j] != null)
players[j].Eliminated = true;
}
m_Context.Finish(m_Context.Participants[winner.TeamID]);
if (winner != null)
m_Context.Finish(m_Context.Participants[winner.TeamID]);
}
public override void OnStop()

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Server.Gumps;
using Server.Items;
@ -70,17 +71,13 @@ namespace Server.Engines.ConPVP
{
CTFTeamInfo teamInfo = game.Controller.TeamInfo[i % 8];
if (teamInfo?.Flag == null)
continue;
entries.Add(teamInfo);
if (teamInfo?.Flag != null)
entries.Add(teamInfo);
}
else
foreach (CTFPlayerInfo player in section.Players.Values)
if (player.Score > 0)
entries.Add(player);
entries.AddRange(section.Players.Values.Where(player => player.Score > 0));
entries.Sort(delegate(IRankedCTF a, IRankedCTF b) { return b.Score - a.Score; });
entries.Sort((a, b) => b.Score - a.Score);
int height = 0;
@ -111,7 +108,8 @@ namespace Server.Engines.ConPVP
if (section == null)
for (int i = 0; i < entries.Count; ++i)
{
CTFTeamInfo teamInfo = entries[i] as CTFTeamInfo;
if (!(entries[i] is CTFTeamInfo teamInfo))
continue;
AddImage(30, 70 + i * 75, 10152);
AddImage(30, 85 + i * 75, 10151);
@ -194,10 +192,7 @@ namespace Server.Engines.ConPVP
private void AddColoredText(int x, int y, int width, int height, string text, int color)
{
if (color == 0)
AddHtml(x, y, width, height, text);
else
AddHtml(x, y, width, height, Color(text, color));
AddHtml(x, y, width, height, color == 0 ? text : Color(text, color));
}
}
@ -246,10 +241,8 @@ namespace Server.Engines.ConPVP
else if (ourTeam == useTeam)
{
if (Location == m_TeamInfo.Origin && Map == m_TeamInfo.Game.Facet)
{
from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", Name,
"Touch me not for I am chaste."));
}
Packets.SendUnicodeMessage(from.NetState, Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", Name,
"Touch me not for I am chaste.");
else
{
CTFPlayerInfo playerInfo = useTeam[from];
@ -306,9 +299,7 @@ namespace Server.Engines.ConPVP
m_ReturnCount = Math.Min(m_ReturnCount, 10);
}
else
{
SendHome();
}
}
private void StopCountdown()
@ -417,9 +408,7 @@ namespace Server.Engines.ConPVP
}
}
else
{
from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "Those are not my cookies.");
}
}
else if (obj is Mobile passTo)
{
@ -943,15 +932,8 @@ namespace Server.Engines.ConPVP
if (ourFlagCarrier != null && GetTeamInfo(ourFlagCarrier) == teamInfo)
{
for (int j = 0; j < ourFlagCarrier.Aggressors.Count; ++j)
{
if (!(ourFlagCarrier.Aggressors[j] is AggressorInfo aggr) ||
aggr.Defender != ourFlagCarrier || aggr.Attacker != mob)
continue;
if (ourFlagCarrier.Aggressors.Any(t => t.Defender == ourFlagCarrier && t.Attacker == mob))
playerInfo.Score += 2; // helped defend guy capturing enemy flag
break;
}
if (mob.Map == ourFlagCarrier.Map && ourFlagCarrier.InRange(mob, 12))
playerInfo.Score += 1; // helped defend guy capturing enemy flag

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Server.Gumps;
using Server.Items;
@ -72,11 +73,9 @@ namespace Server.Engines.ConPVP
entries.Add(teamInfo);
}
else
foreach (DDPlayerInfo player in section.Players.Values)
if (player.Score > 0)
entries.Add(player);
entries.AddRange(section.Players.Values.Where(player => player.Score > 0));
entries.Sort(delegate(IRankedCTF a, IRankedCTF b) { return b.Score - a.Score; });
entries.Sort((a, b) => b.Score - a.Score);
int height = 0;
@ -107,7 +106,8 @@ namespace Server.Engines.ConPVP
if (section == null)
for (int i = 0; i < entries.Count; ++i)
{
DDTeamInfo teamInfo = entries[i] as DDTeamInfo;
if (!(entries[i] is DDTeamInfo teamInfo))
continue;
AddImage(30, 70 + i * 75, 10152);
AddImage(30, 85 + i * 75, 10151);

View file

@ -171,8 +171,7 @@ namespace Server.Engines.ConPVP
King = m;
if (m_KingTimer == null)
m_KingTimer = new KingTimer(this);
m_KingTimer ??= new KingTimer(this);
m_KingTimer.Stop();
m_KingTimer.StartHillTicker();
@ -1113,12 +1112,13 @@ namespace Server.Engines.ConPVP
for (int i = 0; i < m_Context.Participants.Count; ++i)
{
if (!(m_Context.Participants[i] is Participant p) || p.Players == null)
DuelPlayer[] players = m_Context.Participants[i]?.Players;
if (players == null)
continue;
for (int j = 0; j < p.Players.Length; ++j)
for (int j = 0; j < players.Length; ++j)
{
DuelPlayer dp = p.Players[j];
DuelPlayer dp = players[j];
if (dp?.Mobile != null)
{
@ -1130,10 +1130,9 @@ namespace Server.Engines.ConPVP
if (i == winner?.TeamID)
continue;
if (p.Players != null)
for (int j = 0; j < p.Players.Length; ++j)
if (p.Players[j] != null)
p.Players[j].Eliminated = true;
for (int j = 0; j < players.Length; ++j)
if (players[j] != null)
players[j].Eliminated = true;
}
if (winner != null)
@ -1149,7 +1148,7 @@ namespace Server.Engines.ConPVP
if (Controller.Hills[i] != null)
Controller.Hills[i].Game = null;
foreach (KHBoard board in Controller.Boards)
foreach (var board in Controller.Boards)
if (board != null)
board.m_Game = null;

View file

@ -106,7 +106,7 @@ namespace Server.Engines.ConPVP
foreach (Mobile view in mob.GetMobilesInRange(18))
if (!mob.CanSee(view))
mob.Send(view.RemovePacket);
Packets.SendRemoveEntity(mob.NetState, view.Serial);
mob.LocalOverheadMessage(MessageType.Emote, 0x3B2, false,
"* Your mind focuses intently on the fight and all other distractions fade away *");

View file

@ -93,9 +93,7 @@ namespace Server.Engines.ConPVP
for (int i = 0; i < info.Switches.Length; ++i)
{
int sid = info.Switches[i];
if (sid >= 0 && sid < m_Page.Options.Length)
opts[sid] = true;
opts[sid] |= sid >= 0 && sid < m_Page.Options.Length;
}
for (int i = 0; i < opts.Length; ++i)

View file

@ -173,7 +173,7 @@ namespace Server.Engines.ConPVP
}
Resize(Players.Length + 1);
Players[Players.Length - 1] = new DuelPlayer(player, this);
Players[^1] = new DuelPlayer(player, this);
}
public void Resize(int count)

View file

@ -433,7 +433,7 @@ namespace Server.Engines.ConPVP
if (Pyramid.Levels.Count < 1)
break;
PyramidLevel top = Pyramid.Levels[Pyramid.Levels.Count - 1];
PyramidLevel top = Pyramid.Levels[^1];
if (top.FreeAdvance != null || top.Matches.Count != 1)
break;
@ -451,7 +451,7 @@ namespace Server.Engines.ConPVP
if (Pyramid.Levels.Count < 2)
break;
PyramidLevel top = Pyramid.Levels[Pyramid.Levels.Count - 1];
PyramidLevel top = Pyramid.Levels[^1];
if (top.FreeAdvance != null || top.Matches.Count != 1)
break;
@ -471,7 +471,7 @@ namespace Server.Engines.ConPVP
GiveAwards(part.Players, TrophyRank.Silver, cash / 2);
}
PyramidLevel next = Pyramid.Levels[Pyramid.Levels.Count - 2];
PyramidLevel next = Pyramid.Levels[^2];
if (next.Matches.Count > 2)
break;
@ -495,7 +495,7 @@ namespace Server.Engines.ConPVP
}
}
private void GiveAwards(List<Mobile> players, TrophyRank rank, int cash)
private void GiveAwards(IReadOnlyList<Mobile> players, TrophyRank rank, int cash)
{
if (players.Count == 0)
return;
@ -663,69 +663,39 @@ namespace Server.Engines.ConPVP
try
{
if (EventController != null)
{
Alert("The tournament has completed!",
$"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won!");
}
else if (TourneyType == TourneyType.RandomTeam)
{
Alert("The tournament has completed!",
$"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!");
}
else if (TourneyType == TourneyType.Faction)
{
if (m_ParticipantsPerMatch == 4)
{
string name = "(null)";
switch (Pyramid.Levels[0].Matches[0].Participants.IndexOf(
winner))
string name = Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) switch
{
case 0:
{
name = "Minax";
break;
}
case 1:
{
name = "Council of Mages";
break;
}
case 2:
{
name = "True Britannians";
break;
}
case 3:
{
name = "Shadowlords";
break;
}
}
0 => "Minax",
1 => "Council of Mages",
2 => "True Britannians",
3 => "Shadowlords",
_ => "(null)"
};
Alert("The tournament has completed!", $"The {name} team has won!");
}
else if (m_ParticipantsPerMatch == 2)
{
Alert("The tournament has completed!",
$"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!");
}
else
{
Alert("The tournament has completed!",
$"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!");
}
}
else if (TourneyType == TourneyType.RedVsBlue)
{
Alert("The tournament has completed!",
$"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!");
}
else
{
Alert("The tournament has completed!",
$"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}.");
}
}
catch
{
@ -739,7 +709,7 @@ namespace Server.Engines.ConPVP
}
else if (Pyramid.Levels.Count > 0)
{
PyramidLevel activeLevel = Pyramid.Levels[Pyramid.Levels.Count - 1];
PyramidLevel activeLevel = Pyramid.Levels[^1];
bool stillGoing = false;
for (int i = 0; i < activeLevel.Matches.Count; ++i)
@ -846,7 +816,6 @@ namespace Server.Engines.ConPVP
$"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!");
}
else
{
Alert("The tournament has completed!",
$"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!");
}

View file

@ -484,8 +484,7 @@ namespace Server.Engines.Craft
if (m_TypesTable[j][0] == baseType)
types[i] = m_TypesTable[j];
if (types[i] == null)
types[i] = new[] { baseType };
types[i] ??= new[] { baseType };
amounts[i] = craftRes.Amount;
@ -910,8 +909,7 @@ namespace Server.Engines.Craft
hammer.Delete();
}
if (tool.UsesRemaining < 1 && tool.BreakOnDepletion)
toolBroken = true;
toolBroken |= tool.UsesRemaining < 1 && tool.BreakOnDepletion;
if (toolBroken)
tool.Delete();
@ -1033,8 +1031,7 @@ namespace Server.Engines.Craft
tool.UsesRemaining--;
if (tool.UsesRemaining < 1 && tool.BreakOnDepletion)
toolBroken = true;
toolBroken |= tool.UsesRemaining < 1 && tool.BreakOnDepletion;
if (toolBroken)
tool.Delete();

View file

@ -33,7 +33,7 @@ namespace Server.Engines.Craft
public int ID{ get; }
public TextDefinition TextDefinition => m_TD ?? (m_TD = new TextDefinition(CraftItem.NameNumber, CraftItem.NameString));
public TextDefinition TextDefinition => m_TD ??= new TextDefinition(CraftItem.NameNumber, CraftItem.NameString);
public static void Initialize()
{
@ -52,15 +52,13 @@ namespace Server.Engines.Craft
{
if (targeted is PlayerMobile mobile)
{
foreach (KeyValuePair<int, Recipe> kvp in Recipes)
mobile.AcquireRecipe(kvp.Key);
foreach (var (key, _) in Recipes)
mobile.AcquireRecipe(key);
m.SendMessage("You teach them all of the recipes.");
}
else
{
m.SendMessage("That is not a player!");
}
});
}
@ -86,4 +84,4 @@ namespace Server.Engines.Craft
});
}
}
}
}

View file

@ -491,7 +491,7 @@ namespace Server.Engines.Craft
if (!usingDeed)
{
CraftContext context = m_CraftSystem.GetContext(from);
m_CraftSystem.GetContext(from);
from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, number));
}
else
@ -504,4 +504,4 @@ namespace Server.Engines.Craft
}
}
}
}
}

View file

@ -17,7 +17,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044001;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefAlchemy());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefAlchemy();
public override double GetChanceAtMin(CraftItem item) => 0.0;

View file

@ -30,7 +30,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044002;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBlacksmithy());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefBlacksmithy();
public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive;

View file

@ -15,7 +15,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044006;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBowFletching());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefBowFletching();
public override CraftECA ECA => CraftECA.FiftyPercentChanceMinusTenPercent;

View file

@ -15,7 +15,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044004;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCarpentry());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefCarpentry();
public override double GetChanceAtMin(CraftItem item) => 0.5;

View file

@ -15,7 +15,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044008;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCartography());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefCartography();
public override double GetChanceAtMin(CraftItem item) => 0.0;

View file

@ -15,7 +15,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044003;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCooking());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefCooking();
public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive;

View file

@ -16,7 +16,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044622;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefGlassblowing());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefGlassblowing();
public override double GetChanceAtMin(CraftItem item) => item.ItemType == typeof(HollowPrism) ? 0.5 : 0.0;

View file

@ -36,7 +36,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044009;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefInscription());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefInscription();
public override double GetChanceAtMin(CraftItem item) => 0.0;

View file

@ -16,7 +16,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044500;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefMasonry());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefMasonry();
public override double GetChanceAtMin(CraftItem item) => 0.0;

View file

@ -23,7 +23,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044005;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTailoring());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefTailoring();
public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive;

View file

@ -31,7 +31,7 @@ namespace Server.Engines.Craft
public override int GumpTitleNumber => 1044007;
public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTinkering());
public static CraftSystem CraftSystem => m_CraftSystem ??= new DefTinkering();
public override double GetChanceAtMin(CraftItem item)
{

View file

@ -5,11 +5,6 @@ using Server.Mobiles;
using Server.Network;
using Server.Spells;
/*
this is From me to you, Under no terms, Conditions... K? to apply you
just simply Unpatch/delete, Stick these in, Same location.. Restart
*/
namespace Server.Engines.Doom
{
public class LeverPuzzleController : Item
@ -326,7 +321,7 @@ namespace Server.Engines.Doom
SendLocationEffect(lp_Center, 0x1153, 0, 60, 1);
PlaySounds(lp_Center, cs1);
Effects.SendBoltEffect(player, true);
Effects.SendBoltEffect(player);
player.MoveToWorld(lr_Enter, Map.Malas);
m_Timer = new LampRoomTimer(this);
@ -417,25 +412,24 @@ namespace Server.Engines.Doom
public static void SendLocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue)
{
Effects.SendPacket(p, Map.Malas, new LocationEffect(p, itemID, speed, duration, hue, 0));
Effects.SendLocationEffect(p, Map.Malas, itemID, speed, duration, hue);
}
public static void PlayerSendASCII(Mobile player, int index)
{
player.Send(new AsciiMessage(Serial.MinusOne, 0xFFFF, MessageType.Label, MsgParams[index][0],
MsgParams[index][1], null, Msgs[index]));
Packets.SendAsciiMessage(player.NetState, Serial.MinusOne, 0xFFFF, MessageType.Label, MsgParams[index][0],
MsgParams[index][1], null, Msgs[index]);
}
/* I cant find any better way to send "speech" using fonts other than default */
public static void POHMessage(Mobile from, int index)
{
Packet p = new AsciiMessage(from.Serial, from.Body, MessageType.Regular, MsgParams[index][0],
IPooledEnumerable eable = from.Map.GetClientsInRange(from.Location);
foreach (NetState state in eable)
Packets.SendAsciiMessage(state, from.Serial, from.Body, MessageType.Regular, MsgParams[index][0],
MsgParams[index][1], from.Name, Msgs[index]);
p.Acquire();
foreach (NetState state in from.Map.GetClientsInRange(from.Location))
state.Send(p);
Packet.Release(p);
eable.Free();
}
public override void Serialize(GenericWriter writer)

View file

@ -39,7 +39,7 @@ namespace Server.Engines.Doom
public void CallBackMessage()
{
PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060003, ""); // You try to pry the box open...
PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060003); // You try to pry the box open...
}
public override void OnAfterDelete()

View file

@ -77,17 +77,15 @@ namespace Server.Engines.Doom
public Mobile m_Occupant;
public LeverPuzzleRegion(LeverPuzzleController controller, int[] loc)
: base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), new Rectangle2D(loc[0], loc[1], 1, 1))
{
: base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), new Rectangle2D(loc[0], loc[1], 1, 1)) =>
Register();
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Occupant => m_Occupant?.Alive == true ? m_Occupant : null;
public override void OnEnter(Mobile m)
{
if (m != null && m_Occupant == null && m is PlayerMobile && m.Alive)
if (m_Occupant == null && m is PlayerMobile && m.Alive)
m_Occupant = m;
}

View file

@ -93,8 +93,8 @@ namespace Server.Ethics
if (IsImbued(child, true))
return true;
return false;
}
public static bool IsImbued(Item item, bool recurse) =>
Find(item) != null || recurse && item.Items.Any(child => IsImbued(child, true));
public static void Initialize()
{

View file

@ -33,7 +33,9 @@ namespace Server.Ethics.Evil
SpellHelper.GetSurfaceTop(ref p);
foreach (Mobile mob in from.Mobile.GetMobilesInRange(6))
IPooledEnumerable eable = from.Mobile.GetMobilesInRange(6);
foreach (Mobile mob in eable)
{
if (mob == from.Mobile || !SpellHelper.ValidIndirectTarget(from.Mobile, mob))
continue;
@ -54,6 +56,8 @@ namespace Server.Ethics.Evil
powerFunctioned = true;
}
eable.Free();
if (powerFunctioned)
{
SpellHelper.Turn(from.Mobile, p);
@ -71,4 +75,4 @@ namespace Server.Ethics.Evil
}
}
}
}
}

View file

@ -80,13 +80,11 @@ namespace Server.Ethics.Evil
}
}
else
{
sb.Append('.');
}
from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString());
FinishInvoke(from);
}
}
}
}

View file

@ -33,7 +33,9 @@ namespace Server.Ethics.Hero
SpellHelper.GetSurfaceTop(ref p);
foreach (Mobile mob in from.Mobile.GetMobilesInRange(6))
IPooledEnumerable eable = from.Mobile.GetMobilesInRange(6);
foreach (Mobile mob in eable)
{
if (mob != from.Mobile && SpellHelper.ValidIndirectTarget(from.Mobile, mob))
continue;
@ -54,6 +56,8 @@ namespace Server.Ethics.Hero
powerFunctioned = true;
}
eable.Free();
if (powerFunctioned)
{
SpellHelper.Turn(from.Mobile, p);
@ -71,4 +75,4 @@ namespace Server.Ethics.Hero
}
}
}
}
}

View file

@ -80,13 +80,11 @@ namespace Server.Ethics.Hero
}
}
else
{
sb.Append('.');
}
from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString());
FinishInvoke(from);
}
}
}
}

View file

@ -8,7 +8,6 @@ using Server.Ethics;
using Server.Guilds;
using Server.Items;
using Server.Mobiles;
using Server.Prompts;
using Server.Targeting;
namespace Server.Factions
@ -133,21 +132,12 @@ namespace Server.Factions
public static void HandleAtrophy()
{
foreach (Faction f in Factions)
if (!f.State.IsAtrophyReady)
return;
if (Factions.Any(f => !f.State.IsAtrophyReady))
return;
List<PlayerState> activePlayers = new List<PlayerState>();
List<PlayerState> activePlayers = (from f in Factions from ps in f.Members where ps.KillPoints > 0 && ps.IsActive select ps).ToList();
foreach (Faction f in Factions)
foreach (PlayerState ps in f.Members)
if (ps.KillPoints > 0 && ps.IsActive)
activePlayers.Add(ps);
int distrib = 0;
foreach (Faction f in Factions)
distrib += f.State.CheckAtrophy();
int distrib = Factions.Sum(f => f.State.CheckAtrophy());
if (activePlayers.Count == 0)
return;
@ -158,12 +148,7 @@ namespace Server.Factions
public static void DistributePoints(int distrib)
{
List<PlayerState> activePlayers = new List<PlayerState>();
foreach (Faction f in Factions)
foreach (PlayerState ps in f.Members)
if (ps.KillPoints > 0 && ps.IsActive)
activePlayers.Add(ps);
List<PlayerState> activePlayers = (from f in Factions from ps in f.Members where ps.KillPoints > 0 && ps.IsActive select ps).ToList();
if (activePlayers.Count > 0)
for (int i = 0; i < distrib; ++i)
@ -187,13 +172,9 @@ namespace Server.Factions
return;
if (recvState == null || recvState.Faction != giveState.Faction)
{
from.SendLocalizedMessage(1042497); // Only faction mates can be honored this way.
}
else if (giveState.KillPoints < 5)
{
from.SendLocalizedMessage(1042499); // You must have at least five kill points to honor them.
}
else
{
recvState.LastHonorTime = DateTime.UtcNow;
@ -205,9 +186,7 @@ namespace Server.Factions
}
}
else
{
from.SendLocalizedMessage(1042496); // You may only honor another player.
}
}
public virtual void AddMember(Mobile mob)
@ -649,11 +628,7 @@ namespace Server.Factions
public static void FactionItemReset_OnCommand(CommandEventArgs e)
{
List<Item> items = new List<Item>();
foreach (Item item in World.Items.Values)
if (item is IFactionItem && !(item is HoodedShroudOfShadows))
items.Add(item);
List<Item> items = World.Items.Values.Where(item => item is IFactionItem && !(item is HoodedShroudOfShadows)).ToList();
int[] hues = new int[Factions.Count * 2];
@ -673,16 +648,7 @@ namespace Server.Factions
if (fci.FactionItemState != null || item.LootType != LootType.Blessed)
continue;
bool isHued = false;
for (int j = 0; j < hues.Length; ++j)
if (item.Hue == hues[j])
{
isHued = true;
break;
}
if (isHued)
if (hues.Any(t => item.Hue == t))
{
fci.FactionItemState = null;
++count;
@ -841,7 +807,7 @@ namespace Server.Factions
Silver += tithed;
silver = silver - tithed;
silver -= tithed;
if (silver > 0)
mob.AddToBackpack(new Silver(silver));
@ -887,19 +853,12 @@ namespace Server.Factions
Faction smallest = FindSmallestFaction();
if (smallest == null)
return true; // sanity
if ((Members.Count + influx) * 100 / StabilityFactor > smallest.Members.Count)
return false;
return true;
return smallest == null || (Members.Count + influx) * 100 / StabilityFactor <= smallest.Members.Count;
}
public static void HandleDeath(Mobile victim, Mobile killer)
{
if (killer == null)
killer = victim.FindMostRecentDamager(true);
killer ??= victim.FindMostRecentDamager(true);
PlayerState killerState = PlayerState.Find(killer);
Container killerPack = killer?.Backpack;
@ -941,7 +900,7 @@ namespace Server.Factions
int silver = killerState.Faction.AwardSilver(killer, bc.FactionSilverWorth);
if (silver > 0)
killer.SendLocalizedMessage(1042748,
killer?.SendLocalizedMessage(1042748,
silver.ToString("N0")); // Thou hast earned ~1_AMOUNT~ silver for vanquishing the vile creature.
}
@ -982,7 +941,7 @@ namespace Server.Factions
{
if (victimState.KillPoints <= -6)
{
killer.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from.
killer?.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from.
#region Ethics
@ -1024,13 +983,12 @@ namespace Server.Factions
{
victimState.IsActive = true;
if (1 > Utility.Random(3))
killerState.IsActive = true;
killerState.IsActive |= 1 > Utility.Random(3);
int silver = killerState.Faction.AwardSilver(killer, award * 40);
if (silver > 0)
killer.SendLocalizedMessage(1042736,
killer?.SendLocalizedMessage(1042736,
$"{silver:N0} silver\t{victim.Name}"); // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~!
}
@ -1039,9 +997,9 @@ namespace Server.Factions
int offset = award != 1 ? 0 : 2; // for pluralization
string args = $"{award}\t{victim.Name}\t{killer.Name}";
string args = $"{award}\t{victim.Name}\t{killer?.Name ?? ""}";
killer.SendLocalizedMessage(1042737 + offset,
killer?.SendLocalizedMessage(1042737 + offset,
args); // Thou hast been honored with ~1_KILL_POINTS~ kill point(s) for vanquishing ~2_DEAD_PLAYER~!
victim.SendLocalizedMessage(1042738 + offset,
args); // Thou has lost ~1_KILL_POINTS~ kill point(s) to ~3_ATTACKER_NAME~ for being vanquished!
@ -1073,7 +1031,7 @@ namespace Server.Factions
}
else
{
killer.SendLocalizedMessage(
killer?.SendLocalizedMessage(
1042231); // You have recently defeated this enemy and thus their death brings you no honor.
}
}
@ -1284,9 +1242,7 @@ namespace Server.Factions
AddResponse("They have been kicked from their faction.");
}
else
{
LogFailure("They are not in a faction.");
}
break;
}
@ -1300,9 +1256,7 @@ namespace Server.Factions
AddResponse("The account has been banned from joining factions.");
}
else
{
AddResponse("The account is already banned from joining factions.");
}
for (int i = 0; i < acct.Length; ++i)
{
@ -1322,9 +1276,7 @@ namespace Server.Factions
}
}
else
{
LogFailure("They have no assigned account.");
}
break;
}
@ -1333,9 +1285,7 @@ namespace Server.Factions
if (mob.Account is Account acct)
{
if (acct.GetTag("FactionBanned") == null)
{
AddResponse("The account is not already banned from joining factions.");
}
else
{
acct.RemoveTag("FactionBanned");
@ -1343,9 +1293,7 @@ namespace Server.Factions
}
}
else
{
LogFailure("They have no assigned account.");
}
break;
}

View file

@ -260,9 +260,7 @@ namespace Server.Factions
public void OnGivenSilverTo(Mobile mob)
{
if (SilverGiven == null)
SilverGiven = new List<SilverGivenEntry>();
SilverGiven ??= new List<SilverGivenEntry>();
SilverGiven.Add(new SilverGivenEntry(mob));
}

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
@ -41,9 +42,7 @@ namespace Server
if (chance > Utility.Random(100))
{
int weight = 0;
foreach (WeightedItem item in _items) weight += item.Weight;
int weight = _items.Sum(item => item.Weight);
weight = Utility.Random(weight);
@ -177,4 +176,4 @@ namespace Server
public Item Construct() => Activator.CreateInstance(Type) as Item;
}
}
}
}

View file

@ -25,7 +25,9 @@ namespace Server
bool used = false;
foreach (Mobile mob in from.GetMobilesInRange(8))
IPooledEnumerable eable = from.GetMobilesInRange(8);
foreach (Mobile mob in eable)
if (mob.Player && !mob.Alive && from.InLOS(mob))
{
if (Faction.Find(mob) != ourFaction) continue;
@ -41,6 +43,8 @@ namespace Server
}
}
eable.Free();
if (used)
{
from.LocalOverheadMessage(MessageType.Regular, 2219, false, "The urn shatters as you invoke its power.");

View file

@ -113,10 +113,15 @@ namespace Server.Factions
return 502956; // You cannot place a trap on that.
if (Core.ML)
foreach (Item item in m.GetItemsInRange(p, 0))
{
IPooledEnumerable eable = m.GetItemsInRange(p, 0);
foreach (Item item in eable)
if (item is BaseFactionTrap trap && trap.Faction == Faction)
return 1075263; // There is already a trap belonging to your faction at this location.;
eable.Free();
}
switch (AllowedPlacing)
{
case AllowedPlacing.FactionStronghold:
@ -129,22 +134,12 @@ namespace Server.Factions
return 1010355; // This trap can only be placed in your stronghold
}
case AllowedPlacing.AnyFactionTown:
{
Town town = Town.FromRegion(Region.Find(p, m));
if (town != null)
return 0;
return 1010356; // This trap can only be placed in a faction town
}
return Town.FromRegion(Region.Find(p, m)) != null ? 0 : 1010356;
case AllowedPlacing.ControlledFactionTown:
{
Town town = Town.FromRegion(Region.Find(p, m));
if (town != null && town.Owner == Faction)
return 0;
return 1010357; // This trap can only be placed in a town your faction controls
return town != null && town.Owner == Faction ? 0 : 1010357;
}
}
@ -155,17 +150,16 @@ namespace Server.Factions
{
base.OnMovement(m, oldLocation);
if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6))
if (Faction.Find(m) != null &&
(m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble())
PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap]
if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6) &&
Faction.Find(m) != null && (m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble())
PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap]
}
public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args)
{
NetState ns = to?.NetState;
ns?.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args));
Packets.SendMessageLocalized(ns, Serial, ItemID, MessageType.Regular, hue, 3, number, name, args);
}
public virtual bool CheckDecay()
@ -252,10 +246,7 @@ namespace Server.Factions
if (faction == null && mob is BaseFactionGuard guard)
faction = guard.Faction;
if (faction == null)
return false;
return faction != Faction;
return faction != null && faction != Faction;
}
}
}

View file

@ -23,7 +23,7 @@ namespace Server.Factions
public override void DoVisibleEffect()
{
Effects.SendLocationEffect(GetWorldLocation(), Map, 0x36BD, 15, 10);
Effects.SendLocationEffect(GetWorldLocation(), Map, 0x36BD, 15);
}
public override void DoAttackEffect(Mobile m)

View file

@ -8,6 +8,10 @@ namespace Server.Factions
{
}
public FactionSawTrap(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041047; // faction saw trap
public override int AttackMessage => 1010544; // The blade cuts deep into your skin!
@ -19,7 +23,7 @@ namespace Server.Factions
public override void DoVisibleEffect()
{
Effects.SendLocationEffect(Location, Map, 0x11AD, 25, 10);
Effects.SendLocationEffect(Location, Map, 0x11AD, 25);
}
public override void DoAttackEffect(Mobile m)

View file

@ -313,7 +313,9 @@ namespace Server.Factions
actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb);
}
foreach (Mobile m in m_Mobile.GetMobilesInRange(12))
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(12);
foreach (Mobile m in eable)
if (m != m_Mobile && CanDispel(m))
{
double prio = m_Mobile.GetDistanceToSqrt(m);
@ -331,6 +333,8 @@ namespace Server.Factions
}
}
eable.Free();
return active ?? inactive;
}

View file

@ -23,7 +23,7 @@ namespace Server.Engines.Harvest
new MutateEntry(0.0, 125.0, -2375.0, false, typeof(PrizedFish), typeof(WondrousFish), typeof(TrulyRareFish),
typeof(PeculiarFish)),
new MutateEntry(0.0, 105.0, -420.0, false, typeof(Boots), typeof(Shoes), typeof(Sandals), typeof(ThighBoots)),
new MutateEntry(0.0, 200.0, -200.0, false, new Type[1] { null })
new MutateEntry(0.0, 200.0, -200.0, false, new Type[] { null })
};
private static int[] m_WaterTiles =
@ -87,7 +87,7 @@ namespace Server.Engines.Harvest
Definitions.Add(fish);
}
public static Fishing System => m_System ?? (m_System = new Fishing());
public static Fishing System => m_System ??= new Fishing();
public HarvestDefinition Definition{ get; }

View file

@ -126,7 +126,7 @@ namespace Server.Engines.Harvest
Definitions.Add(lumber);
}
public static Lumberjacking System => m_System ?? (m_System = new Lumberjacking());
public static Lumberjacking System => m_System ??= new Lumberjacking();
public HarvestDefinition Definition{ get; }

View file

@ -153,7 +153,7 @@ namespace Server.Engines.Harvest
#endregion
}
public static Mining System => m_System ?? (m_System = new Mining());
public static Mining System => m_System ??= new Mining();
public HarvestDefinition OreAndStone{ get; }

View file

@ -1,7 +1,9 @@
using System;
using System.Linq;
using Server.Engines.ConPVP;
using Server.Factions;
using Server.Gumps;
using Server.Menus;
using Server.Menus.Questions;
using Server.Mobiles;
using Server.Multis;
@ -27,9 +29,7 @@ namespace Server.Engines.Help
public override void OnResponse(NetState state, int index)
{
if (index == 0)
{
m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged.
}
else if (index == 1)
{
PageEntry entry = PageQueue.GetEntry(m_From);
@ -141,49 +141,49 @@ namespace Server.Engines.Help
AddButton(80, 90, 5540, 5541, 7);
AddHtmlLocalized(110, 90, 450, 145, 1062572, true,
true); /* <U><CENTER>Another player is harassing me (or Exploiting).</CENTER></U><BR>
* VERBAL HARASSMENT<BR>
* Use this option when another player is verbally harassing your character.
* Verbal harassment behaviors include but are not limited to, using bad language, threats etc..
* Before you submit a complaint be sure you understand what constitutes harassment
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=40"><EFBFBD> what is verbal harassment? -</A>
* and that you have followed these steps:<BR>
* 1. You have asked the player to stop and they have continued.<BR>
* 2. You have tried to remove yourself from the situation.<BR>
* 3. You have done nothing to instigate or further encourage the harassment.<BR>
* 4. You have added the player to your ignore list.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=138">- How do I ignore a player?</A><BR>
* 5. You have read and understand Origin<EFBFBD>s definition of harassment.<BR>
* 6. Your account information is up to date. (Including a current email address)<BR>
* *If these steps have not been taken, GMs may be unable to take action against the offending player.<BR>
* **A chat log will be review by a GM to assess the validity of this complaint.
* Abuse of this system is a violation of the Rules of Conduct.<BR>
* EXPLOITING<BR>
* Use this option to report someone who may be exploiting or cheating.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=41"><EFBFBD> What constitutes an exploit?</a>
*/
true); /* <U><CENTER>Another player is harassing me (or Exploiting).</CENTER></U><BR>
* VERBAL HARASSMENT<BR>
* Use this option when another player is verbally harassing your character.
* Verbal harassment behaviors include but are not limited to, using bad language, threats etc..
* Before you submit a complaint be sure you understand what constitutes harassment
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=40"><EFBFBD> what is verbal harassment? -</A>
* and that you have followed these steps:<BR>
* 1. You have asked the player to stop and they have continued.<BR>
* 2. You have tried to remove yourself from the situation.<BR>
* 3. You have done nothing to instigate or further encourage the harassment.<BR>
* 4. You have added the player to your ignore list.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=138">- How do I ignore a player?</A><BR>
* 5. You have read and understand Origin<EFBFBD>s definition of harassment.<BR>
* 6. Your account information is up to date. (Including a current email address)<BR>
* *If these steps have not been taken, GMs may be unable to take action against the offending player.<BR>
* **A chat log will be review by a GM to assess the validity of this complaint.
* Abuse of this system is a violation of the Rules of Conduct.<BR>
* EXPLOITING<BR>
* Use this option to report someone who may be exploiting or cheating.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=41"><EFBFBD> What constitutes an exploit?</a>
*/
AddButton(80, 240, 5540, 5541, 8);
AddHtmlLocalized(110, 240, 450, 145, 1062573, true,
true); /* <U><CENTER>Another player is harassing me using game mechanics.</CENTER></U><BR>
* <BR>
* PHYSICAL HARASSMENT<BR>
* Use this option when another player is harassing your character using game mechanics.
* Physical harassment includes but is not limited to luring, Kill Stealing, and any act that causes a players death in Trammel.
* Before you submit a complaint be sure you understand what constitutes harassment
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=59"> <EFBFBD> what is physical harassment?</A>
* and that you have followed these steps:<BR>
* 1. You have asked the player to stop and they have continued.<BR>
* 2. You have tried to remove yourself from the situation.<BR>
* 3. You have done nothing to instigate or further encourage the harassment.<BR>
* 4. You have added the player to your ignore list.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=138"> - how do I ignore a player?</A><BR>
* 5. You have read and understand Origin<EFBFBD>s definition of harassment.<BR>
* 6. Your account information is up to date. (Including a current email address)<BR>
* *If these steps have not been taken, GMs may be unable to take action against the offending player.<BR>
* **This issue will be reviewed by a GM to assess the validity of this complaint.
* Abuse of this system is a violation of the Rules of Conduct.
*/
true); /* <U><CENTER>Another player is harassing me using game mechanics.</CENTER></U><BR>
* <BR>
* PHYSICAL HARASSMENT<BR>
* Use this option when another player is harassing your character using game mechanics.
* Physical harassment includes but is not limited to luring, Kill Stealing, and any act that causes a players death in Trammel.
* Before you submit a complaint be sure you understand what constitutes harassment
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=59"> <EFBFBD> what is physical harassment?</A>
* and that you have followed these steps:<BR>
* 1. You have asked the player to stop and they have continued.<BR>
* 2. You have tried to remove yourself from the situation.<BR>
* 3. You have done nothing to instigate or further encourage the harassment.<BR>
* 4. You have added the player to your ignore list.
* <A HREF="http://uo.custhelp.com/cgi-bin/uo.cfg/php/enduser/std_adp.php?p_faqid=138"> - how do I ignore a player?</A><BR>
* 5. You have read and understand Origin<EFBFBD>s definition of harassment.<BR>
* 6. Your account information is up to date. (Including a current email address)<BR>
* *If these steps have not been taken, GMs may be unable to take action against the offending player.<BR>
* **This issue will be reviewed by a GM to assess the validity of this complaint.
* Abuse of this system is a violation of the Rules of Conduct.
*/
AddButton(150, 390, 5540, 5541, 0, GumpButtonType.Page, 1);
AddHtmlLocalized(180, 390, 335, 40, 1001015); // NO - I meant to ask for help with another matter.
@ -196,9 +196,8 @@ namespace Server.Engines.Help
private static void EventSink_HelpRequest(HelpRequestEventArgs e)
{
foreach (Gump g in e.Mobile.NetState.Gumps)
if (g is HelpGump)
return;
if (e.Mobile.NetState.Gumps.OfType<HelpGump>().Any())
return;
if (!PageQueue.CheckAllowedToPage(e.Mobile))
return;
@ -224,9 +223,9 @@ namespace Server.Engines.Help
return false;
}
public override void OnResponse(NetState state, RelayInfo info)
public override void OnResponse(NetState sender, RelayInfo info)
{
Mobile from = state.Mobile;
Mobile from = sender.Mobile;
PageType type = (PageType)(-1);

View file

@ -1,5 +1,3 @@
using Server.Prompts;
namespace Server.Engines.Help
{
public class PagePrompt : Prompt
@ -16,11 +14,11 @@ namespace Server.Engines.Help
public override void OnResponse(Mobile from, string text)
{
from.SendLocalizedMessage(501234, "",
0x35); /* The next available Counselor/Game Master will respond as soon as possible.
* Please check your Journal for messages every few minutes.
*/
0x35); /* The next available Counselor/Game Master will respond as soon as possible.
* Please check your Journal for messages every few minutes.
*/
PageQueue.Enqueue(new PageEntry(from, text, m_Type));
}
}
}
}

View file

@ -48,9 +48,9 @@ namespace Server.Engines.Help
else
{
m_From.SendLocalizedMessage(501234, "",
0x35); /* The next available Counselor/Game Master will respond as soon as possible.
* Please check your Journal for messages every few minutes.
*/
0x35); /* The next available Counselor/Game Master will respond as soon as possible.
* Please check your Journal for messages every few minutes.
*/
PageQueue.Enqueue(new PageEntry(m_From, text, m_Type));
}

View file

@ -82,8 +82,6 @@ namespace Server.Engines.Help
private class InternalTimer : Timer
{
private static TimeSpan StatusDelay = TimeSpan.FromMinutes(2.0);
private PageEntry m_Entry;
public InternalTimer(PageEntry entry) : base(TimeSpan.FromSeconds(1.0), StatusDelay) => m_Entry = entry;

View file

@ -32,7 +32,7 @@ namespace Server.Engines.Help
AddHtmlLocalized(34, 28, 65, 24, 3001002, 0xFFFFFF); // Message
}
public override void OnResponse(NetState state, RelayInfo info)
public override void OnResponse(NetState sender, RelayInfo info)
{
m_Mobile.SendGump(new PageResponseGump(m_Mobile, m_Name, m_Text));
@ -100,20 +100,20 @@ namespace Server.Engines.Help
}
}
public override void OnResponse(NetState state, RelayInfo info)
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID >= 1 && info.ButtonID <= m_List.Length)
{
if (PageQueue.List.IndexOf(m_List[info.ButtonID - 1]) >= 0)
{
PageEntryGump g = new PageEntryGump(state.Mobile, m_List[info.ButtonID - 1]);
PageEntryGump g = new PageEntryGump(sender.Mobile, m_List[info.ButtonID - 1]);
g.SendTo(state);
g.SendTo(sender);
}
else
{
state.Mobile.SendGump(new PageQueueGump());
state.Mobile.SendMessage("That page has been removed.");
sender.Mobile.SendGump(new PageQueueGump());
sender.Mobile.SendMessage("That page has been removed.");
}
}
}
@ -553,12 +553,12 @@ namespace Server.Engines.Help
g.SendTo(state);
}
public override void OnResponse(NetState state, RelayInfo info)
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID != 0 && PageQueue.List.IndexOf(m_Entry) < 0)
{
state.Mobile.SendGump(new PageQueueGump());
state.Mobile.SendMessage("That page has been removed.");
sender.Mobile.SendGump(new PageQueueGump());
sender.Mobile.SendMessage("That page has been removed.");
return;
}
@ -566,18 +566,18 @@ namespace Server.Engines.Help
{
case 0: // close
{
if (m_Entry.Handler != state.Mobile)
if (m_Entry.Handler != sender.Mobile)
{
PageQueueGump g = new PageQueueGump();
g.SendTo(state);
g.SendTo(sender);
}
break;
}
case 1: // go to sender
{
Mobile m = state.Mobile;
Mobile m = sender.Mobile;
if (m_Entry.Sender.Deleted)
{
@ -594,14 +594,14 @@ namespace Server.Engines.Help
m.SendMessage("You have been teleported to that page's sender.");
Resend(state);
Resend(sender);
}
break;
}
case 2: // go to handler
{
Mobile m = state.Mobile;
Mobile m = sender.Mobile;
Mobile h = m_Entry.Handler;
if (h != null)
@ -620,20 +620,20 @@ namespace Server.Engines.Help
m.MoveToWorld(h.Location, h.Map);
m.SendMessage("You have been teleported to that page's handler.");
Resend(state);
Resend(sender);
}
}
else
{
m.SendMessage("Nobody is handling that page.");
Resend(state);
Resend(sender);
}
break;
}
case 3: // go to page location
{
Mobile m = state.Mobile;
Mobile m = sender.Mobile;
if (m_Entry.PageMap == null || m_Entry.PageMap == Map.Internal)
{
@ -644,9 +644,9 @@ namespace Server.Engines.Help
// m_Entry.AddResponse(state.Mobile, "[Go PageLoc]");
m.MoveToWorld(m_Entry.PageLocation, m_Entry.PageMap);
state.Mobile.SendMessage("You have been teleported to the original page location.");
sender.Mobile.SendMessage("You have been teleported to the original page location.");
Resend(state);
Resend(sender);
}
break;
@ -656,16 +656,14 @@ namespace Server.Engines.Help
if (m_Entry.Handler == null)
{
// m_Entry.AddResponse(state.Mobile, "[Handling]");
m_Entry.Handler = state.Mobile;
m_Entry.Handler = sender.Mobile;
state.Mobile.SendMessage("You are now handling the page.");
sender.Mobile.SendMessage("You are now handling the page.");
}
else
{
state.Mobile.SendMessage("Someone is already handling that page.");
}
sender.Mobile.SendMessage("Someone is already handling that page.");
Resend(state);
Resend(sender);
break;
}
@ -676,59 +674,57 @@ namespace Server.Engines.Help
// m_Entry.AddResponse(state.Mobile, "[Deleting]");
PageQueue.Remove(m_Entry);
state.Mobile.SendMessage("You delete the page.");
sender.Mobile.SendMessage("You delete the page.");
PageQueueGump g = new PageQueueGump();
g.SendTo(state);
g.SendTo(sender);
}
else
{
state.Mobile.SendMessage("Someone is handling that page, it can not be deleted.");
sender.Mobile.SendMessage("Someone is handling that page, it can not be deleted.");
Resend(state);
Resend(sender);
}
break;
}
case 6: // abandon page
{
if (m_Entry.Handler == state.Mobile)
if (m_Entry.Handler == sender.Mobile)
{
// m_Entry.AddResponse(state.Mobile, "[Abandoning]");
state.Mobile.SendMessage("You abandon the page.");
sender.Mobile.SendMessage("You abandon the page.");
m_Entry.Handler = null;
}
else
{
state.Mobile.SendMessage("You are not handling that page.");
}
sender.Mobile.SendMessage("You are not handling that page.");
Resend(state);
Resend(sender);
break;
}
case 7: // page handled
{
if (m_Entry.Handler == state.Mobile)
if (m_Entry.Handler == sender.Mobile)
{
// m_Entry.AddResponse(state.Mobile, "[Handled]");
PageQueue.Remove(m_Entry);
m_Entry.Handler = null;
state.Mobile.SendMessage("You mark the page as handled, and remove it from the queue.");
sender.Mobile.SendMessage("You mark the page as handled, and remove it from the queue.");
PageQueueGump g = new PageQueueGump();
g.SendTo(state);
g.SendTo(sender);
}
else
{
state.Mobile.SendMessage("You are not handling that page.");
sender.Mobile.SendMessage("You are not handling that page.");
Resend(state);
Resend(sender);
}
break;
@ -743,20 +739,20 @@ namespace Server.Engines.Help
//m_Entry.Sender.SendMessage( 0x482, "{0} tells you:", state.Mobile.Name );
//m_Entry.Sender.SendMessage( 0x482, text.Text );
Resend(state);
Resend(sender);
break;
}
case 9: // predef overview
{
Resend(state);
state.Mobile.SendGump(new PredefGump(state.Mobile, null));
Resend(sender);
sender.Mobile.SendGump(new PredefGump(sender.Mobile, null));
break;
}
case 10: // View Speech Log
{
Resend(state);
Resend(sender);
if (m_Entry.SpeechLog != null) state.Mobile.SendGump(new SpeechLogGump(m_Entry.Sender, m_Entry.SpeechLog));
@ -772,7 +768,7 @@ namespace Server.Engines.Help
m_Entry.Sender.SendGump(new MessageSentGump(m_Entry.Sender, state.Mobile.Name,
preresp[index].Message));
Resend(state);
Resend(sender);
break;
}

View file

@ -46,9 +46,7 @@ namespace Server.Engines.Help
string sLog;
if (page < 0 || page > lastPage)
{
sLog = "";
}
else
{
int max = log.Count - (lastPage - page) * MaxEntriesPerPage;

View file

@ -14,9 +14,9 @@ namespace Server.Menus.Questions
Locations = locations;
}
public int Name{ get; }
public int Name { get; }
public Point3D[] Locations{ get; }
public Point3D[] Locations { get; }
}
public class StuckMenu : Gump
@ -162,7 +162,7 @@ namespace Server.Menus.Questions
m_Mobile.Frozen = false;
}
public override void OnResponse(NetState state, RelayInfo info)
public override void OnResponse(NetState sender, RelayInfo info)
{
StopClose();

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Gumps;
using Server.Network;
@ -47,22 +48,9 @@ namespace Server.Items
int version = reader.ReadEncodedInt();
int length = reader.ReadEncodedInt();
for (int i = 0;; i++)
if (i < length)
{
PuzzleChestCylinder cylinder = (PuzzleChestCylinder)reader.ReadInt();
if (i < Cylinders.Length)
Cylinders[i] = cylinder;
}
else if (i < Cylinders.Length)
{
Cylinders[i] = RandomCylinder();
}
else
{
break;
}
for (int i = 0; i < Cylinders.Length; i++)
Cylinders[i] = i < length ? (PuzzleChestCylinder)reader.ReadInt() : RandomCylinder();
}
public PuzzleChestCylinder[] Cylinders{ get; } = new PuzzleChestCylinder[Length];
@ -296,7 +284,7 @@ namespace Server.Items
{
case 0:
{
Effects.SendLocationEffect(to, to.Map, 0x113A, 20, 10);
Effects.SendLocationEffect(to, to.Map, 0x113A, 20);
to.PlaySound(0x231);
to.LocalOverheadMessage(MessageType.Regular, 0x44, 1010523); // A toxic vapor envelops thee.
@ -326,7 +314,7 @@ namespace Server.Items
}
default:
{
to.BoltEffect(0);
to.BoltEffect();
to.LocalOverheadMessage(MessageType.Regular, 0xDA, 1010526); // Lightning arcs through thy body.
AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 0, 0, 0, 0, 100);
@ -409,12 +397,8 @@ namespace Server.Items
for (int i = 0; i < 2; i++)
{
Item item;
if (Core.AOS)
item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
else
item = Loot.RandomArmorOrShieldOrWeapon();
Item item = Core.AOS ?
Loot.RandomArmorOrShieldOrWeaponOrJewelry() : Loot.RandomArmorOrShieldOrWeapon();
if (item is BaseWeapon weapon)
{
@ -475,13 +459,7 @@ namespace Server.Items
public void CleanupGuesses()
{
List<Mobile> toDelete = new List<Mobile>();
foreach (KeyValuePair<Mobile, PuzzleChestSolutionAndTime> kvp in m_Guesses)
if (DateTime.UtcNow - kvp.Value.When > CleanupTime)
toDelete.Add(kvp.Key);
foreach (Mobile m in toDelete)
foreach (Mobile m in from kvp in m_Guesses where DateTime.UtcNow - kvp.Value.When > CleanupTime select kvp.Key)
m_Guesses.Remove(m);
}
@ -499,10 +477,10 @@ namespace Server.Items
for (int i = 0; i < Hints.Length; i++) writer.Write((int)Hints[i]);
writer.WriteEncodedInt(m_Guesses.Count);
foreach (KeyValuePair<Mobile, PuzzleChestSolutionAndTime> kvp in m_Guesses)
foreach (var (key, value) in m_Guesses)
{
writer.Write(kvp.Key);
kvp.Value.Serialize(writer);
writer.Write(key);
value.Serialize(writer);
}
}
@ -680,9 +658,7 @@ namespace Server.Items
}
if (info.ButtonID == 1)
{
m_Chest.SubmitSolution(m_From, m_Solution);
}
else
{
if (info.Switches.Length == 0)

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Buffers;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
@ -87,7 +89,7 @@ namespace Server.Engines.MLQuests.Gumps
CloseCurrent(ns);
m_Pending[ns] = new RaceChangeState(owner, ns, targetRace);
ns.Send(new RaceChanger(from.Female, targetRace));
SendRaceChanger(ns, from.Female, targetRace);
}
private static void CloseCurrent(NetState ns)
@ -98,7 +100,7 @@ namespace Server.Engines.MLQuests.Gumps
m_Pending.Remove(ns);
}
ns.Send(CloseRaceChanger.Instance);
SendCloseRaceChanger(ns);
}
private static void Timeout(NetState ns)
@ -106,30 +108,21 @@ namespace Server.Engines.MLQuests.Gumps
if (IsPending(ns))
{
m_Pending.Remove(ns);
ns.Send(CloseRaceChanger.Instance);
SendCloseRaceChanger(ns);
}
}
public static bool IsWearingEquipment(Mobile from)
{
foreach (Item item in from.Items)
switch (item.Layer)
return from.Items.Select(item => item.Layer switch
{
case Layer.Hair:
case Layer.FacialHair:
case Layer.Backpack:
case Layer.Mount:
case Layer.Bank:
{
continue; // ignore
}
default:
{
return true;
}
}
return false;
Layer.Hair => false,
Layer.FacialHair => false,
Layer.Backpack => false,
Layer.Mount => false,
Layer.Bank => false,
_ => true
}).FirstOrDefault();
}
private static bool CanChange(PlayerMobile from, Race targetRace)
@ -238,38 +231,34 @@ namespace Server.Engines.MLQuests.Gumps
m_Timeout = Timer.DelayCall(m_TimeoutDelay, Timeout, ns);
}
}
}
public sealed class RaceChanger : Packet
{
public RaceChanger(bool female, Race targetRace)
: base(0xBF)
public static void SendRaceChanger(NetState ns, bool female, Race targetRace)
{
EnsureCapacity(7);
if (ns == null)
return;
m_Stream.Write((short)0x2A);
m_Stream.Write((byte)(female ? 1 : 0));
m_Stream.Write((byte)(targetRace.RaceID + 1));
SpanWriter writer = new SpanWriter(stackalloc byte[7]);
writer.Write((byte)0xBF); // Packet ID
writer.Write((ushort)0x07); // Dynamic Length
writer.Write((short)0x2A);
writer.Write(female);
writer.Write((byte)(targetRace.RaceID + 1));
ns.Send(writer.Span);
}
private static void SendCloseRaceChanger(NetState ns)
{
ns?.Send(stackalloc byte[]
{
0xBF, // Packet ID
0x07, // Dynamic Length
0x00,
0xFF
});
}
}
public sealed class CloseRaceChanger : Packet
{
public static readonly Packet Instance = SetStatic(new CloseRaceChanger());
private CloseRaceChanger()
: base(0xBF)
{
EnsureCapacity(7);
m_Stream.Write((short)0x2A);
m_Stream.Write((byte)0);
m_Stream.Write((byte)0xFF);
}
}
#region For testing
public class RaceChangeDeed : Item, IRaceChanger
{
[Constructible]
@ -330,6 +319,4 @@ namespace Server.Engines.MLQuests.Gumps
int version = reader.ReadInt();
}
}
#endregion
}

View file

@ -86,14 +86,7 @@ namespace Server.Engines.MLQuests
public virtual int Version => 0;
public bool HasObjective<T>() where T : BaseObjective
{
foreach (BaseObjective obj in Objectives)
if (obj is T)
return true;
return false;
}
public bool HasObjective<T>() where T : BaseObjective => Objectives.OfType<T>().Any();
public virtual void Generate()
{
@ -151,11 +144,7 @@ namespace Server.Engines.MLQuests
}
}
foreach (BaseObjective obj in Objectives)
if (!obj.CanOffer(quester, pm, message))
return false;
return true;
return Objectives.All(obj => obj.CanOffer(quester, pm, message));
}
public virtual void SendOffer(IQuestGiver quester, PlayerMobile pm)

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Mobiles;
namespace Server.Engines.MLQuests
@ -113,14 +114,7 @@ namespace Server.Engines.MLQuests
return quest != null && HasDoneQuest(quest);
}
public bool HasDoneQuest(MLQuest quest)
{
foreach (MLDoneQuestInfo info in m_DoneQuests)
if (info.m_Quest == quest)
return true;
return false;
}
public bool HasDoneQuest(MLQuest quest) => m_DoneQuests.Any(info => info.m_Quest == quest);
public bool HasDoneQuest(MLQuest quest, out DateTime nextAvailable)
{
@ -180,20 +174,10 @@ namespace Server.Engines.MLQuests
{
MLQuest quest = MLQuestSystem.FindQuest(questType);
if (quest == null)
return null;
return FindInstance(quest);
return quest == null ? null : FindInstance(quest);
}
public MLQuestInstance FindInstance(MLQuest quest)
{
foreach (MLQuestInstance instance in QuestInstances)
if (instance.Quest == quest)
return instance;
return null;
}
public MLQuestInstance FindInstance(MLQuest quest) => QuestInstances.FirstOrDefault(instance => instance.Quest == quest);
public bool IsDoingQuest(Type questType)
{

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Engines.MLQuests.Gumps;
using Server.Engines.MLQuests.Objectives;
using Server.Engines.MLQuests.Rewards;
@ -36,16 +37,7 @@ namespace Server.Engines.MLQuests
Objectives = new BaseObjectiveInstance[quest.Objectives.Count];
BaseObjectiveInstance obj;
bool timed = false;
for (int i = 0; i < quest.Objectives.Count; ++i)
{
Objectives[i] = obj = quest.Objectives[i].CreateInstance(this);
if (obj.IsTimed)
timed = true;
}
bool timed = quest.Objectives.Aggregate(false, (current, t) => current | t.CreateInstance(this).IsTimed);
Register();
@ -113,14 +105,8 @@ namespace Server.Engines.MLQuests
Removed = true;
}
public bool AllowsQuestItem(Item item, Type type)
{
foreach (BaseObjectiveInstance objective in Objectives)
if (!objective.Expired && objective.AllowsQuestItem(item, type))
return true;
return false;
}
public bool AllowsQuestItem(Item item, Type type) =>
Objectives.Any(objective => !objective.Expired && objective.AllowsQuestItem(item, type));
public bool IsCompleted()
{
@ -252,13 +238,11 @@ namespace Server.Engines.MLQuests
if (Quest.ObjectiveType == ObjectiveType.All)
{
// TODO: 1115877 - You no longer have the required items to complete this quest.
foreach (BaseObjectiveInstance objective in Objectives)
if (!objective.IsCompleted())
return;
if (Objectives.Any(objective => !objective.IsCompleted()))
return;
foreach (BaseObjectiveInstance objective in Objectives)
if (!objective.OnBeforeClaimReward())
return;
if (Objectives.Any(objective => !objective.OnBeforeClaimReward()))
return;
foreach (BaseObjectiveInstance objective in Objectives)
objective.OnClaimReward();
@ -314,14 +298,7 @@ namespace Server.Engines.MLQuests
{
// On OSI a more naive method of checking is used.
// For containers, only the actual container item counts.
bool canFit = true;
foreach (Item rewardItem in rewards)
if (!Player.AddToBackpack(rewardItem))
{
canFit = false;
break;
}
bool canFit = rewards.All(rewardItem => Player.AddToBackpack(rewardItem));
if (!canFit)
{

View file

@ -14,8 +14,7 @@ namespace Server.Engines.MLQuests
public static void EnsureExistence()
{
if (m_Instance == null)
m_Instance = new MLQuestPersistence();
m_Instance ??= new MLQuestPersistence();
}
public override void Serialize(GenericWriter writer)
@ -55,4 +54,4 @@ namespace Server.Engines.MLQuests
MLQuest.Deserialize(reader, version);
}
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Server.Commands;
using Server.Commands.Generic;
using Server.Engines.MLQuests.Gumps;
@ -213,7 +214,7 @@ namespace Server.Engines.MLQuests
return;
}
bool enable = e.Length == 1 ? e.GetBoolean(0) : true;
bool enable = e.Length != 1 || e.GetBoolean(0);
foreach (MLQuest quest in Quests.Values)
quest.SaveEnabled = enable;
@ -329,17 +330,8 @@ namespace Server.Engines.MLQuests
}
}
public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type)
{
MLQuestContext context = GetContext(pm);
if (context != null)
foreach (MLQuestInstance quest in context.QuestInstances)
if (!quest.ClaimReward && quest.AllowsQuestItem(item, type))
return true;
return false;
}
public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type) =>
GetContext(pm)?.QuestInstances.Any(quest => !quest.ClaimReward && quest.AllowsQuestItem(item, type)) == true;
private static void OnMarkQuestItem(PlayerMobile pm, Item item, Type type)
{
@ -563,8 +555,7 @@ namespace Server.Engines.MLQuests
* Save first quest that reaches the CanOffer call.
* If no quests are valid at all, return this quest for displaying the CanOffer error message.
*/
if (fallback == null)
fallback = quest;
fallback ??= quest;
if (quest.CanOffer(quester, pm, context, false))
m_EligiblePool.Add(quest);
@ -643,7 +634,7 @@ namespace Server.Engines.MLQuests
if (questType == null)
return null; // no longer a type
return FindQuest(questType);
return questType == null ? null : FindQuest(questType);
}
public static MLQuest FindQuest(Type questType)

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Engines.MLQuests.Definitions;
using Server.Engines.MLQuests.Gumps;
using Server.Items;
@ -135,20 +136,7 @@ namespace Server.Engines.MLQuests.Mobiles
{
MLQuestContext context = MLQuestSystem.GetContext(pm);
if (context == null)
return 0;
int result = 0;
foreach (Type type in Needed)
{
MLQuest quest = MLQuestSystem.FindQuest(type);
if (quest == null || context.HasDoneQuest(quest))
++result;
}
return result;
return context == null ? 0 : Needed.Select(MLQuestSystem.FindQuest).Count(quest => quest == null || context.HasDoneQuest(quest));
}
public virtual void OnComplete(PlayerMobile pm)

View file

@ -42,9 +42,7 @@ namespace Server.Engines.MLQuests.Mobiles
public override bool GetGender() => false;
public override void CheckMorph()
{
}
public override bool CheckMorph() => true;
public override void InitOutfit()
{
@ -53,22 +51,9 @@ namespace Server.Engines.MLQuests.Mobiles
HairHue = FacialHairHue = 0x8A7;
AddItem(new Sandals());
Item item;
item = new Cloak();
item.ItemID = 0x26AD;
item.Hue = 0x455;
AddItem(item);
item = new Robe();
item.ItemID = 0x26AE;
item.Hue = 0x4AB;
AddItem(item);
item = new Backpack();
item.Movable = false;
AddItem(item);
AddItem(new Cloak{ ItemID = 0x26AD, Hue = 0x455});
AddItem(new Robe {ItemID = 0x26AE, Hue = 0x4AB});
AddItem(new Backpack {Movable = false});
}
public override void OnDoubleClick(Mobile from)
@ -92,32 +77,23 @@ namespace Server.Engines.MLQuests.Mobiles
if (m_NextShout <= DateTime.UtcNow)
{
Packet shoutPacket = null;
foreach (NetState state in GetClientsInRange(12))
IPooledEnumerable eable = GetClientsInRange(12);
foreach (NetState state in eable)
{
Mobile m = state.Mobile;
if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this))
{
if (shoutPacket == null)
shoutPacket = Packet.Acquire(new MessageLocalized(Serial, Body, MessageType.Regular, 946, 3,
1078099, Name, "")); // Double Click On Me For Help!
state.Send(shoutPacket);
}
Packets.SendMessageLocalized(state, Serial, Body, MessageType.Regular, 946, 3,
1078099, Name); // Double Click On Me For Help!
}
Packet.Release(shoutPacket);
eable.Free();
m_NextShout = DateTime.UtcNow + m_ShoutDelay;
}
}
private void EndLock(Mobile m)
{
m.EndAction(this);
}
private void EndLock(Mobile m) => m.EndAction(this);
public override void Serialize(GenericWriter writer)
{
@ -135,4 +111,4 @@ namespace Server.Engines.MLQuests.Mobiles
Frozen = true;
}
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Linq;
using Server.Gumps;
using Server.Misc;
using Server.Mobiles;
@ -20,14 +21,13 @@ namespace Server.Engines.MLQuests.Objectives
MLQuestContext context = MLQuestSystem.GetContext(pm);
if (context != null)
foreach (MLQuestInstance instance in context.QuestInstances)
if (instance.Quest.IsEscort)
{
if (message)
MLQuestSystem.Tell(quester, pm, 500896); // I see you already have an escort.
if (context.QuestInstances.Any(instance => instance.Quest.IsEscort))
{
if (message)
MLQuestSystem.Tell(quester, pm, 500896); // I see you already have an escort.
return false;
}
return false;
}
DateTime nextEscort = pm.LastEscortTime + BaseEscortable.EscortDelay;

View file

@ -1,4 +1,5 @@
using System;
using System.Linq;
using Server.Gumps;
using Server.Mobiles;
@ -91,22 +92,21 @@ namespace Server.Engines.MLQuests.Objectives
{
int desired = Objective.DesiredAmount;
foreach (Type acceptedType in Objective.AcceptedTypes)
if (acceptedType.IsAssignableFrom(type))
{
if (Objective.Area?.Contains(mob) == false)
return false;
if (Objective.AcceptedTypes.Any(acceptedType => acceptedType.IsAssignableFrom(type)))
{
if (Objective.Area?.Contains(mob) == false)
return false;
PlayerMobile pm = Instance.Player;
PlayerMobile pm = Instance.Player;
if (++Slain >= desired)
pm.SendLocalizedMessage(1075050); // You have killed all the required quest creatures of this type.
else
pm.SendLocalizedMessage(1075051,
(desired - Slain).ToString()); // You have killed a quest creature. ~1_val~ more left.
if (++Slain >= desired)
pm.SendLocalizedMessage(1075050); // You have killed all the required quest creatures of this type.
else
pm.SendLocalizedMessage(1075051,
(desired - Slain).ToString()); // You have killed a quest creature. ~1_val~ more left.
return true;
}
return true;
}
return false;
}

View file

@ -1,4 +1,5 @@
using System;
using System.Linq;
namespace Server.Engines.MLQuests
{
@ -34,14 +35,7 @@ namespace Server.Engines.MLQuests
// Debug method
public void Validate()
{
bool found = false;
foreach (Region r in Region.Regions)
if (r.Name == RegionName && (ForceMap == null || r.Map == ForceMap))
{
found = true;
break;
}
bool found = Region.Regions.Any(r => r.Name == RegionName && (ForceMap == null || r.Map == ForceMap));
if (!found)
Console.WriteLine("Warning: QuestArea region '{0}' does not exist (ForceMap = {1})", RegionName,

View file

@ -0,0 +1,81 @@
using System.Collections.Generic;
namespace Server.Engines.MyRunUO
{
public class LayerComparer : IComparer<Item>
{
private static Layer PlateArms = (Layer)255;
private static Layer ChainTunic = (Layer)254;
private static Layer LeatherShorts = (Layer)253;
private static Layer[] m_DesiredLayerOrder =
{
Layer.Cloak,
Layer.Bracelet,
Layer.Ring,
Layer.Shirt,
Layer.Pants,
Layer.InnerLegs,
Layer.Shoes,
LeatherShorts,
Layer.Arms,
Layer.InnerTorso,
LeatherShorts,
PlateArms,
Layer.MiddleTorso,
Layer.OuterLegs,
Layer.Neck,
Layer.Waist,
Layer.Gloves,
Layer.OuterTorso,
Layer.OneHanded,
Layer.TwoHanded,
Layer.FacialHair,
Layer.Hair,
Layer.Helm,
Layer.Talisman
};
public static readonly IComparer<Item> Instance = new LayerComparer();
static LayerComparer()
{
TranslationTable = new int[256];
for (int i = 0; i < m_DesiredLayerOrder.Length; ++i)
TranslationTable[(int)m_DesiredLayerOrder[i]] = m_DesiredLayerOrder.Length - i;
}
public static int[] TranslationTable{ get; }
public int Compare(Item a, Item b)
{
if (a == null)
return b == null ? 0 : 1;
if (b == null)
return -1;
Layer aLayer = Fix(a.ItemID, a.Layer);
Layer bLayer = Fix(b.ItemID, b.Layer);
return TranslationTable[(int)bLayer] - TranslationTable[(int)aLayer];
}
public static bool IsValid(Item item) => TranslationTable[(int)item.Layer] > 0;
public Layer Fix(int itemID, Layer oldLayer)
{
if (itemID == 0x1410 || itemID == 0x1417) // platemail arms
return PlateArms;
if (itemID == 0x13BF || itemID == 0x13C4) // chainmail tunic
return ChainTunic;
if (itemID == 0x1C08 || itemID == 0x1C09 || itemID == 0x1C00 || itemID == 0x1C01) // leather skirt/shorts
return LeatherShorts;
return oldLayer;
}
}
}

View file

@ -1,77 +1,175 @@
using Server.Buffers;
using Server.Network;
namespace Server.Engines.PartySystem
{
public sealed class PartyEmptyList : Packet
public static class PartyPackets
{
public PartyEmptyList(Mobile m) : base(0xBF)
public static void SendPartyEmptyList(NetState ns, Mobile m)
{
EnsureCapacity(7);
if (ns == null)
return;
m_Stream.Write((short)0x0006);
m_Stream.Write((byte)0x02);
m_Stream.Write((byte)0);
m_Stream.Write(m.Serial);
SpanWriter writer = new SpanWriter(stackalloc byte[11]);
writer.Write((byte)0xBF); // Packet ID
writer.Write((short)11); // Dynamic Length
writer.Write((short)0x06);
writer.Write((byte)0x02);
writer.Position++; // Writer(0); // Number of members
writer.Write(m.Serial);
ns.Send(writer.Span);
}
}
public sealed class PartyMemberList : Packet
{
public PartyMemberList(Party p) : base(0xBF)
public static void SendPartyMemberList(NetState ns, Party p)
{
EnsureCapacity(7 + p.Count * 4);
if (ns == null)
return;
m_Stream.Write((short)0x0006);
m_Stream.Write((byte)0x01);
m_Stream.Write((byte)p.Count);
ushort length = (ushort)(7 + p.Count * 4);
SpanWriter writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xBF); // Packet ID
writer.Write(length); // Dynamic Length
writer.Write((short)0x06);
writer.Write((byte)0x01);
writer.Write((byte)p.Count);
for (int i = 0; i < p.Count; ++i)
m_Stream.Write(p[i].Mobile.Serial);
writer.Write(p[i].Mobile.Serial);
ns.Send(writer.Span);
}
}
public sealed class PartyRemoveMember : Packet
{
public PartyRemoveMember(Mobile removed, Party p) : base(0xBF)
public static void SendPartyRemoveMember(NetState ns, Mobile removed, Party p)
{
EnsureCapacity(11 + p.Count * 4);
if (ns == null)
return;
m_Stream.Write((short)0x0006);
m_Stream.Write((byte)0x02);
m_Stream.Write((byte)p.Count);
ushort length = (ushort)(11 + p.Count * 4);
m_Stream.Write(removed.Serial);
SpanWriter writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xBF); // Packet ID
writer.Write(length); // Dynamic Length
writer.Write((short)0x06);
writer.Write((byte)0x02);
writer.Write((byte)p.Count);
writer.Write(removed.Serial);
for (int i = 0; i < p.Count; ++i)
m_Stream.Write(p[i].Mobile.Serial);
}
}
writer.Write(p[i].Mobile.Serial);
public sealed class PartyTextMessage : Packet
{
public PartyTextMessage(bool toAll, Mobile from, string text) : base(0xBF)
ns.Send(writer.Span);
}
public static void SendPartyRemoveMemberToAll(Mobile removed, Party p)
{
if (text == null)
text = "";
EnsureCapacity(12 + text.Length * 2);
m_Stream.Write((short)0x0006);
m_Stream.Write((byte)(toAll ? 0x04 : 0x03));
m_Stream.Write(from.Serial);
m_Stream.WriteBigUniNull(text);
for (int i = 0; i < p.Members.Count; i++)
SendPartyRemoveMember(p[i].Mobile.NetState, removed, p);
}
}
public sealed class PartyInvitation : Packet
{
public PartyInvitation(Mobile leader) : base(0xBF)
public static void SendPartyTextMessage(NetState ns, bool toAll, Mobile from, string text)
{
EnsureCapacity(10);
if (ns == null)
return;
m_Stream.Write((short)0x0006);
m_Stream.Write((byte)0x07);
m_Stream.Write(leader.Serial);
ushort length = (ushort)(12 + text.Length * 2);
SpanWriter writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xBF); // Packet ID
writer.Write(length); // Dynamic Length
writer.Write((short)0x06);
writer.Write((byte)(toAll ? 0x04 : 0x03));
writer.Write(from.Serial);
writer.WriteBigUniNull(text);
ns.Send(writer.Span);
}
public static void SendPartyTextMessageToAll(Party p, bool toAll, Mobile from, string text)
{
for (int i = 0; i < p.Members.Count; ++i)
SendPartyTextMessage(p.Members[i].Mobile.NetState, toAll, from, text);
}
public static void SendPartyInvitation(NetState ns, Mobile leader)
{
if (ns == null)
return;
SpanWriter writer = new SpanWriter(stackalloc byte[10]);
writer.Write((byte)0xBF); // Packet ID
writer.Write((short)10); // Dynamic Length
writer.Write((short)0x06);
writer.Write((byte)0x07);
writer.Write(leader.Serial);
ns.Send(writer.Span);
}
public static void SendPartyMessageLocalizedToAll(Party p, Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "",
string args = "")
{
for (int i = 0; i < p.Members.Count; ++i)
Packets.SendMessageLocalized(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, number, name, args);
for (int i = 0; i < p.Listeners.Count; ++i)
{
Mobile mob = p.Listeners[i];
if (mob.Party != p)
Packets.SendMessageLocalized(mob.NetState, serial, graphic, type, hue, font, number, name, args);
}
}
public static void SendPartyMessageLocalizedAffixToAll(Party p, Serial serial, int graphic, MessageType type, int hue, int font, int number,
string name = "", AffixType affixType = AffixType.System, string affix = "", string args = "")
{
for (int i = 0; i < p.Members.Count; ++i)
Packets.SendMessageLocalizedAffix(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, number, name, affixType, affix, args);
for (int i = 0; i < p.Listeners.Count; ++i)
{
Mobile mob = p.Listeners[i];
if (mob.Party != p)
Packets.SendMessageLocalizedAffix(mob.NetState, serial, graphic, type, hue, font, number, name, affixType, affix, args);
}
}
public static void SendPartyUnicodeMessageToAll(Party p, Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name,
string text)
{
for (int i = 0; i < p.Members.Count; ++i)
Packets.SendUnicodeMessage(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, lang, name, text);
for (int i = 0; i < p.Listeners.Count; ++i)
{
Mobile mob = p.Listeners[i];
if (mob.Party != p)
Packets.SendUnicodeMessage(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, lang, name, text);
}
}
public static void SendPartyAsciiMessageToAll(Party p, Serial serial, int graphic, MessageType type, int hue, int font, string name, string text)
{
for (int i = 0; i < p.Members.Count; ++i)
Packets.SendAsciiMessage(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, name, text);
for (int i = 0; i < p.Listeners.Count; ++i)
{
Mobile mob = p.Listeners[i];
if (mob.Party != p)
Packets.SendAsciiMessage(p.Members[i].Mobile.NetState, serial, graphic, type, hue, font, name, text);
}
}
}
}
}

View file

@ -9,7 +9,6 @@ namespace Server.Engines.PartySystem
public class Party : IParty
{
public const int Capacity = 10;
private List<Mobile> m_Listeners; // staff listening
public Party(Mobile leader)
{
@ -17,7 +16,7 @@ namespace Server.Engines.PartySystem
Members = new List<PartyMemberInfo>();
Candidates = new List<Mobile>();
m_Listeners = new List<Mobile>();
Listeners = new List<Mobile>();
Members.Add(new PartyMemberInfo(leader));
}
@ -30,58 +29,32 @@ namespace Server.Engines.PartySystem
public List<Mobile> Candidates{ get; }
public List<Mobile> Listeners { get; } // staff listening
public PartyMemberInfo this[int index] => Members[index];
public PartyMemberInfo this[Mobile m]
{
get
{
for (int i = 0; i < Members.Count; ++i)
if (Members[i].Mobile == m)
return Members[i];
return null;
}
}
public PartyMemberInfo this[Mobile m] => Members.FirstOrDefault(t => t.Mobile == m);
public void OnStamChanged(Mobile m)
{
Packet p = null;
for (int i = 0; i < Members.Count; ++i)
{
Mobile c = Members[i].Mobile;
if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
{
if (p == null)
p = Packet.Acquire(new MobileStamN(m));
c.Send(p);
}
Packets.SendNormalizedMobileStam(c.NetState, c);
}
Packet.Release(p);
}
public void OnManaChanged(Mobile m)
{
Packet p = null;
for (int i = 0; i < Members.Count; ++i)
{
Mobile c = Members[i].Mobile;
if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
{
if (p == null)
p = Packet.Acquire(new MobileManaN(m));
c.Send(p);
}
Packets.SendNormalizedMobileMana(c.NetState, c);
}
Packet.Release(p);
}
public void OnStatsQuery(Mobile beholder, Mobile beheld)
@ -90,9 +63,9 @@ namespace Server.Engines.PartySystem
Utility.InUpdateRange(beholder, beheld))
{
if (!beholder.CanSee(beheld))
beholder.Send(new MobileStatusCompact(beheld.CanBeRenamedBy(beholder), beheld));
Packets.SendMobileStatusCompact(beholder.NetState, beheld, beheld.CanBeRenamedBy(beholder));
beholder.Send(new MobileAttributesN(beheld));
Packets.SendNormalizedMobileAttributes(beholder.NetState, beheld);
}
}
@ -121,14 +94,14 @@ namespace Server.Engines.PartySystem
{
from.SendMessage("They are not in a party.");
}
else if (p.m_Listeners.Contains(from))
else if (p.Listeners.Contains(from))
{
p.m_Listeners.Remove(from);
p.Listeners.Remove(from);
from.SendMessage("You are no longer listening to that party.");
}
else
{
p.m_Listeners.Add(from);
p.Listeners.Add(from);
from.SendMessage("You are now listening to that party.");
}
}
@ -184,35 +157,25 @@ namespace Server.Engines.PartySystem
Members.Add(new PartyMemberInfo(m));
m.Party = this;
Packet memberList = Packet.Acquire(new PartyMemberList(this));
Packet attrs = Packet.Acquire(new MobileAttributesN(m));
for (int i = 0; i < Members.Count; ++i)
{
Mobile f = Members[i].Mobile;
NetState ns = f.NetState;
f.Send(memberList);
PartyPackets.SendPartyMemberList(ns, this);
if (f != m)
{
f.Send(new MobileStatusCompact(m.CanBeRenamedBy(f), m));
f.Send(attrs);
m.Send(new MobileStatusCompact(f.CanBeRenamedBy(m), f));
m.Send(new MobileAttributesN(f));
Packets.SendMobileStatusCompact(ns, m, m.CanBeRenamedBy(f));
Packets.SendNormalizedMobileAttributes(ns, m);
Packets.SendMobileStatusCompact(ns, f, f.CanBeRenamedBy(m));
Packets.SendNormalizedMobileAttributes(ns, f);
}
}
Packet.Release(memberList);
Packet.Release(attrs);
}
}
public void OnAccept(Mobile from)
{
OnAccept(from, false);
}
public void OnAccept(Mobile from, bool force)
public void OnAccept(Mobile from, bool force = false)
{
Faction ourFaction = Faction.Find(Leader);
Faction theirFaction = Faction.Find(from);
@ -221,8 +184,8 @@ namespace Server.Engines.PartySystem
return;
// : joined the party.
SendToAll(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, 1008094, "",
AffixType.Prepend | AffixType.System, from.Name, ""));
PartyPackets.SendPartyMessageLocalizedAffixToAll(this, Serial.MinusOne, -1, MessageType.Label,
0x3B2, 3, 1008094, "",AffixType.Prepend | AffixType.System, from.Name);
from.SendLocalizedMessage(1005445); // You have been added to the party.
@ -238,14 +201,15 @@ namespace Server.Engines.PartySystem
from.SendLocalizedMessage(1008092); // You notify them that you do not wish to join the party.
Candidates.Remove(from);
from.Send(new PartyEmptyList(from));
PartyPackets.SendPartyEmptyList(from.NetState, from);
if (Candidates.Count == 0 && Members.Count <= 1)
{
for (int i = 0; i < Members.Count; ++i)
{
this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile));
this[i].Mobile.Party = null;
Mobile m = this[i].Mobile;
PartyPackets.SendPartyEmptyList(m.NetState, m);
m.Party = null;
}
Members.Clear();
@ -255,9 +219,7 @@ namespace Server.Engines.PartySystem
public void Remove(Mobile m)
{
if (m == Leader)
{
Disband();
}
else
{
for (int i = 0; i < Members.Count; ++i)
@ -266,19 +228,21 @@ namespace Server.Engines.PartySystem
Members.RemoveAt(i);
m.Party = null;
m.Send(new PartyEmptyList(m));
PartyPackets.SendPartyEmptyList(m.NetState, m);
m.SendLocalizedMessage(1005451); // You have been removed from the party.
SendToAll(new PartyRemoveMember(m, this));
SendToAll(1005452); // A player has been removed from your party.
PartyPackets.SendPartyRemoveMemberToAll(m, this);
// A player has been removed from your party.
PartyPackets.SendPartyMessageLocalizedToAll(this, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, 1005452, "System");
break;
}
if (Members.Count == 1)
{
SendToAll(1005450); // The last person has left the party...
// The last person has left the party...
PartyPackets.SendPartyMessageLocalizedToAll(this, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, 1005450, "System");
Disband();
}
}
@ -288,12 +252,14 @@ namespace Server.Engines.PartySystem
public void Disband()
{
SendToAll(1005449); // Your party has disbanded.
// Your party has disbanded.
PartyPackets.SendPartyMessageLocalizedToAll(this, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, 1005449, "System");
for (int i = 0; i < Members.Count; ++i)
{
this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile));
this[i].Mobile.Party = null;
Mobile m = this[i].Mobile;
PartyPackets.SendPartyEmptyList(m.NetState, m);
m.Party = null;
}
Members.Clear();
@ -320,82 +286,57 @@ namespace Server.Engines.PartySystem
p.Candidates.Add(target);
// : You are invited to join the party. Type /accept to join or /decline to decline the offer.
target.Send(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, 1008089, "",
AffixType.Prepend | AffixType.System, from.Name, ""));
Packets.SendMessageLocalizedAffix(target.NetState, Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, 1008089, "",
AffixType.Prepend | AffixType.System, from.Name);
from.SendLocalizedMessage(1008090); // You have invited them to join the party.
target.Send(new PartyInvitation(from));
PartyPackets.SendPartyInvitation(target.NetState, from);
target.Party = from;
DeclineTimer.Start(target, from);
}
public void SendToAll(int number)
{
SendToAll(number, "", 0x3B2);
}
public void SendToAll(int number, string args)
{
SendToAll(number, args, 0x3B2);
}
public void SendToAll(int number, string args, int hue)
{
SendToAll(new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args));
}
public void SendPublicMessage(Mobile from, string text)
{
SendToAll(new PartyTextMessage(true, from, text));
PartyPackets.SendPartyTextMessageToAll(this, true, from, text);
for (int i = 0; i < m_Listeners.Count; ++i)
for (int i = 0; i < Listeners.Count; ++i)
{
Mobile mob = m_Listeners[i];
Mobile mob = Listeners[i];
if (mob.Party != this)
m_Listeners[i].SendMessage("[{0}]: {1}", from.Name, text);
Listeners[i].SendMessage("[{0}]: {1}", from.Name, text);
}
SendToStaffMessage(from, "[Party]: {0}", text);
SendToStaffMessage(from, $"[Party]: {text}");
}
public void SendPrivateMessage(Mobile from, Mobile to, string text)
{
to.Send(new PartyTextMessage(false, from, text));
PartyPackets.SendPartyTextMessage(to.NetState, false, from, text);
for (int i = 0; i < m_Listeners.Count; ++i)
for (int i = 0; i < Listeners.Count; ++i)
{
Mobile mob = m_Listeners[i];
Mobile mob = Listeners[i];
if (mob.Party != this)
m_Listeners[i].SendMessage("[{0}]->[{1}]: {2}", from.Name, to.Name, text);
Listeners[i].SendMessage("[{0}]->[{1}]: {2}", from.Name, to.Name, text);
}
SendToStaffMessage(from, "[Party]->[{0}]: {1}", to.Name, text);
SendToStaffMessage(from, $"[Party]->[{to.Name}]: {text}");
}
private void SendToStaffMessage(Mobile from, string text)
{
Packet p = null;
foreach (NetState ns in from.GetClientsInRange(8))
{
Mobile mob = ns.Mobile;
if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel &&
mob.Party != this && !m_Listeners.Contains(mob))
{
if (p == null)
p = Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3,
from.Language, from.Name, text));
ns.Send(p);
}
mob.Party != this && !Listeners.Contains(mob))
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3, from.Language, from.Name, text);
}
Packet.Release(p);
}
private void SendToStaffMessage(Mobile from, string format, params object[] args)
@ -403,25 +344,6 @@ namespace Server.Engines.PartySystem
SendToStaffMessage(from, string.Format(format, args));
}
public void SendToAll(Packet p)
{
p.Acquire();
for (int i = 0; i < Members.Count; ++i)
Members[i].Mobile.Send(p);
if (p is MessageLocalized || p is MessageLocalizedAffix || p is UnicodeMessage || p is AsciiMessage)
for (int i = 0; i < m_Listeners.Count; ++i)
{
Mobile mob = m_Listeners[i];
if (mob.Party != this)
mob.Send(p);
}
p.Release();
}
private class RejoinTimer : Timer
{
private Mobile m_Mobile;
@ -436,11 +358,7 @@ namespace Server.Engines.PartySystem
return;
m_Mobile.SendLocalizedMessage(1005437); // You have rejoined the party.
m_Mobile.Send(new PartyMemberList(p));
Packet message = Packet.Acquire(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3,
1008087, "", AffixType.Prepend | AffixType.System, m_Mobile.Name, ""));
Packet attrs = Packet.Acquire(new MobileAttributesN(m_Mobile));
PartyPackets.SendPartyMemberList(m_Mobile.NetState, p);
foreach (PartyMemberInfo mi in p.Members)
{
@ -448,16 +366,15 @@ namespace Server.Engines.PartySystem
if (m != m_Mobile)
{
m.Send(message);
m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile));
m.Send(attrs);
m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m));
m_Mobile.Send(new MobileAttributesN(m));
NetState ns = m.NetState;
Packets.SendMessageLocalizedAffix(ns, Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3,
1008087, "", AffixType.Prepend | AffixType.System, m_Mobile.Name);
Packets.SendMobileStatusCompact(ns, m_Mobile, m_Mobile.CanBeRenamedBy(m));
Packets.SendNormalizedMobileAttributes(ns, m_Mobile);
Packets.SendMobileStatusCompact(ns, m, m.CanBeRenamedBy(m_Mobile));
Packets.SendNormalizedMobileAttributes(ns, m);
}
}
Packet.Release(message);
Packet.Release(attrs);
}
}
}

View file

@ -1,19 +1,17 @@
using System.Collections;
using Server.Mobiles;
using CalcMoves = Server.Movement.Movement;
using MoveImpl = Server.Movement.MovementImpl;
namespace Server.PathAlgorithms.FastAStar
namespace Server.PathAlgorithms
{
public struct PathNode
{
public int cost, total;
public int parent, next, prev;
public int z;
}
public class FastAStarAlgorithm : PathAlgorithm
{
public struct PathNode
{
public int cost, total;
public int parent, next, prev;
public int z;
}
private const int MaxDepth = 300;
private const int AreaSize = 38;
@ -134,18 +132,18 @@ namespace Server.PathAlgorithms.FastAStar
if (bc != null)
{
MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors;
MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles;
MovementImpl.AlwaysIgnoreDoors = bc.CanOpenDoors;
MovementImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles;
}
MoveImpl.Goal = goal;
MovementImpl.Goal = goal;
int[] vals = m_Successors;
int count = GetSuccessors(bestNode, m, map);
MoveImpl.AlwaysIgnoreDoors = false;
MoveImpl.IgnoreMovableImpassables = false;
MoveImpl.Goal = Point3D.Zero;
MovementImpl.AlwaysIgnoreDoors = false;
MovementImpl.IgnoreMovableImpassables = false;
MovementImpl.Goal = Point3D.Zero;
if (count == 0)
break;
@ -158,26 +156,26 @@ namespace Server.PathAlgorithms.FastAStar
if (wasTouched)
continue;
int newCost = m_Nodes[bestNode].cost + 1;
int newTotal = newCost + Heuristic(newNode % AreaSize, newNode / AreaSize % AreaSize,
m_Nodes[newNode].z);
if (m_Nodes[newNode].total <= newTotal)
continue;
m_Nodes[newNode].parent = bestNode;
m_Nodes[newNode].cost = newCost;
m_Nodes[newNode].total = newTotal;
if (m_OnOpen[newNode])
continue;
AddToChain(newNode);
if (newNode != destNode)
continue;
int pathCount = 0;
int parent = m_Nodes[newNode].parent;
@ -296,7 +294,7 @@ namespace Server.PathAlgorithms.FastAStar
if (x < 0 || x >= AreaSize || y < 0 || y >= AreaSize)
continue;
if (CalcMoves.CheckMovement(m, map, p3D, (Direction)i, out int z))
if (Movement.CheckMovement(m, map, p3D, (Direction)i, out int z))
{
int idx = GetIndex(x + m_xOffset, y + m_yOffset, z);
@ -311,4 +309,4 @@ namespace Server.PathAlgorithms.FastAStar
return count;
}
}
}
}

View file

@ -8,7 +8,7 @@ using Server.Mobiles;
#endregion
namespace Server.Movement
namespace Server
{
public class FastMovementImpl : IMovementImpl
{
@ -179,7 +179,7 @@ namespace Server.Movement
private static bool Check(
Map map,
Mobile m,
List<Item> items,
IReadOnlyCollection<Item> items,
int x,
int y,
int startTop,

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
namespace Server.Movement
namespace Server
{
public class MovementImpl : IMovementImpl
{
@ -316,7 +316,7 @@ namespace Server.Movement
return true;
}
private bool Check(Map map, Mobile m, List<Item> items, List<Mobile> mobiles, int x, int y, int startTop, int startZ,
private bool Check(Map map, Mobile m, List<Item> items, IReadOnlyList<Mobile> mobiles, int x, int y, int startTop, int startZ,
bool canSwim, bool cantWalk, out int newZ)
{
newZ = 0;
@ -500,7 +500,7 @@ namespace Server.Movement
!t.Alive || !m.Alive || t.IsDeadBondedPet || m.IsDeadBondedPet ||
t.Hidden && t.AccessLevel > AccessLevel.Player;
private void GetStartZ(Mobile m, Map map, Point3D loc, List<Item> itemList, out int zLow, out int zTop)
private void GetStartZ(Mobile m, Map map, Point3D loc, IReadOnlyList<Item> itemList, out int zLow, out int zTop)
{
int xCheck = loc.X, yCheck = loc.Y;

View file

@ -1,8 +1,6 @@
using System;
using Server.Items;
using Server.PathAlgorithms;
using Server.PathAlgorithms.FastAStar;
using Server.PathAlgorithms.SlowAStar;
using Server.Spells;
using Server.Targeting;
@ -84,7 +82,7 @@ namespace Server
for (int i = 0; i < path.Directions.Length; ++i)
{
Movement.Movement.Offset(path.Directions[i], ref x, ref y);
Movement.Offset(path.Directions[i], ref x, ref y);
new RecallRune().MoveToWorld(new Point3D(x, y, z + zOffset), from.Map);
}

View file

@ -2,7 +2,7 @@ namespace Server.PathAlgorithms
{
public abstract class PathAlgorithm
{
private static Direction[] m_CalcDirections = {
private static readonly Direction[] m_CalcDirections = {
Direction.Up,
Direction.North,
Direction.Right,
@ -29,4 +29,4 @@ namespace Server.PathAlgorithms
return m_CalcDirections[v];
}
}
}
}

View file

@ -1,5 +1,4 @@
using System;
using CalcMoves = Server.Movement.Movement;
namespace Server
{
@ -52,7 +51,7 @@ namespace Server
{
int x = p.X, y = p.Y;
CalcMoves.Offset(dirs[index], ref x, ref y);
Movement.Offset(dirs[index], ref x, ref y);
p.X = x;
p.Y = y;

View file

@ -1,20 +1,18 @@
using System;
using Server.Mobiles;
using CalcMoves = Server.Movement.Movement;
using MoveImpl = Server.Movement.MovementImpl;
namespace Server.PathAlgorithms.SlowAStar
namespace Server.PathAlgorithms
{
public struct PathNode
{
public int x, y, z;
public int g, h;
public int px, py, pz;
public int dir;
}
public class SlowAStarAlgorithm : PathAlgorithm
{
public struct PathNode
{
public int x, y, z;
public int g, h;
public int px, py, pz;
public int dir;
}
private const int MaxDepth = 300;
private const int MaxNodes = MaxDepth * 16;
public static PathAlgorithm Instance = new SlowAStarAlgorithm();
@ -148,11 +146,11 @@ namespace Server.PathAlgorithms.SlowAStar
if (bc != null)
{
MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors;
MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles;
MovementImpl.AlwaysIgnoreDoors = bc.CanOpenDoors;
MovementImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles;
}
MoveImpl.Goal = goal;
MovementImpl.Goal = goal;
int x;
int y;
@ -162,7 +160,6 @@ namespace Server.PathAlgorithms.SlowAStar
switch (i)
{
default:
case 0:
x = 0;
y = -1;
break;
@ -196,7 +193,7 @@ namespace Server.PathAlgorithms.SlowAStar
break;
}
if (CalcMoves.CheckMovement(m, map, new Point3D(curNode.x, curNode.y, curNode.z), (Direction)i, out z))
if (Movement.CheckMovement(m, map, new Point3D(curNode.x, curNode.y, curNode.z), (Direction)i, out z))
{
successors[sucCount].x = x + curNode.x;
successors[sucCount].y = y + curNode.y;
@ -204,9 +201,9 @@ namespace Server.PathAlgorithms.SlowAStar
}
}
MoveImpl.AlwaysIgnoreDoors = false;
MoveImpl.IgnoreMovableImpassables = false;
MoveImpl.Goal = Point3D.Zero;
MovementImpl.AlwaysIgnoreDoors = false;
MovementImpl.IgnoreMovableImpassables = false;
MovementImpl.Goal = Point3D.Zero;
if (sucCount == 0 || ++depth > MaxDepth)
break;
@ -272,4 +269,4 @@ namespace Server.PathAlgorithms.SlowAStar
return null;
}
}
}
}

View file

@ -75,7 +75,7 @@ namespace Server.Engines.Plants
}
case 2: // Help
{
from.Send(new DisplayHelpTopic(71, true)); // EMPTYING THE BOWL
ContentPackets.SendDisplayHelpTopic(from.NetState, 17, true); // EMPTYING THE BOWL
from.SendGump(new EmptyTheBowlGump(m_Plant));

View file

@ -264,9 +264,7 @@ namespace Server.Engines.Plants
case 1: // Reproduction menu
{
if (m_Plant.PlantStatus > PlantStatus.BowlOfDirt)
{
from.SendGump(new ReproductionGump(m_Plant));
}
else
{
from.SendLocalizedMessage(1061885); // You need to plant a seed in the bowl first.
@ -278,32 +276,28 @@ namespace Server.Engines.Plants
}
case 2: // Infestation
{
from.Send(new DisplayHelpTopic(54, true)); // INFESTATION LEVEL
ContentPackets.SendDisplayHelpTopic(from.NetState, 54, true); // INFESTATION LEVEL
from.SendGump(new MainPlantGump(m_Plant));
break;
}
case 3: // Fungus
{
from.Send(new DisplayHelpTopic(56, true)); // FUNGUS LEVEL
ContentPackets.SendDisplayHelpTopic(from.NetState, 56, true); // FUNGUS LEVEL
from.SendGump(new MainPlantGump(m_Plant));
break;
}
case 4: // Poison
{
from.Send(new DisplayHelpTopic(58, true)); // POISON LEVEL
ContentPackets.SendDisplayHelpTopic(from.NetState, 58, true); // POISON LEVEL
from.SendGump(new MainPlantGump(m_Plant));
break;
}
case 5: // Disease
{
from.Send(new DisplayHelpTopic(60, true)); // DISEASE LEVEL
ContentPackets.SendDisplayHelpTopic(from.NetState, 60, true); // DISEASE LEVEL
from.SendGump(new MainPlantGump(m_Plant));
break;
@ -320,9 +314,7 @@ namespace Server.Engines.Plants
$"#{m_Plant.GetLocalizedPlantStatus()}"); // Target the container you wish to use to water the ~1_val~.
}
else
{
m_Plant.Pour(from, bev);
}
from.SendGump(new MainPlantGump(m_Plant));
@ -354,7 +346,7 @@ namespace Server.Engines.Plants
}
case 11: // Help
{
from.Send(new DisplayHelpTopic(48, true)); // PLANT GROWING
ContentPackets.SendDisplayHelpTopic(from.NetState, 48, true); // PLANT GROWING
from.SendGump(new MainPlantGump(m_Plant));
@ -374,9 +366,7 @@ namespace Server.Engines.Plants
Item item = GetPotion(from, effects);
if (item != null)
{
m_Plant.Pour(from, item);
}
else
{
if (m_Plant.ApplyPotion(effects[0], true, out int message))

View file

@ -1,15 +0,0 @@
namespace Server.Network
{
public class DisplayHelpTopic : Packet
{
public DisplayHelpTopic(int topicID, bool display) : base(0xBF)
{
EnsureCapacity(11);
m_Stream.Write((short)0x17);
m_Stream.Write((byte)1);
m_Stream.Write(topicID);
m_Stream.Write(display);
}
}
}

View file

@ -84,8 +84,7 @@ namespace Server.Engines.Plants
}
else
{
if (PlantSystem == null)
PlantSystem = new PlantSystem(this, false);
PlantSystem ??= new PlantSystem(this, false);
int hits = (int)(PlantSystem.MaxHits * ratio);

View file

@ -1,4 +1,5 @@
using System;
using System.Linq;
using Server.Items;
namespace Server.Engines.Plants
@ -31,15 +32,9 @@ namespace Server.Engines.Plants
public Type ResourceType{ get; }
public static PlantResourceInfo GetInfo(PlantType plantType, PlantHue plantHue)
{
foreach (PlantResourceInfo info in m_ResourceList)
if (info.PlantType == plantType && info.PlantHue == plantHue)
return info;
return null;
}
public static PlantResourceInfo GetInfo(PlantType plantType, PlantHue plantHue) =>
m_ResourceList.FirstOrDefault(info => info.PlantType == plantType && info.PlantHue == plantHue);
public Item CreateResource() => (Item)Activator.CreateInstance(ResourceType);
}
}
}

View file

@ -383,6 +383,7 @@ namespace Server.Engines.Plants
return 1060827; // soft
if (Water <= 3)
return 1060828; // squishy
return 1060829; // sopping wet
}

View file

@ -261,21 +261,13 @@ namespace Server.Engines.Plants
double rand = Utility.RandomDouble();
if (rand < 0.5 / exp4)
return PlantType.CommonGreenBonsai;
if (rand < 1.0 / exp4)
return PlantType.CommonPinkBonsai;
if (rand < (k1 * 0.5 + 1.0) / exp4)
return PlantType.UncommonGreenBonsai;
if (rand < exp1 / exp4)
return PlantType.UncommonPinkBonsai;
if (rand < (k2 * 0.5 + exp1) / exp4)
return PlantType.RareGreenBonsai;
if (rand < exp2 / exp4)
return PlantType.RarePinkBonsai;
if (rand < exp3 / exp4)
return PlantType.ExceptionalBonsai;
return PlantType.ExoticBonsai;
return rand < 0.5 / exp4 ? PlantType.CommonGreenBonsai :
rand < 1.0 / exp4 ? PlantType.CommonPinkBonsai :
rand < (k1 * 0.5 + 1.0) / exp4 ? PlantType.UncommonGreenBonsai :
rand < exp1 / exp4 ? PlantType.UncommonPinkBonsai :
rand < (k2 * 0.5 + exp1) / exp4 ? PlantType.RareGreenBonsai :
rand < exp2 / exp4 ? PlantType.RarePinkBonsai :
rand < exp3 / exp4 ? PlantType.ExceptionalBonsai : PlantType.ExoticBonsai;
}
public static bool IsCrossable(PlantType plantType) => GetInfo(plantType).Crossable;
@ -356,4 +348,4 @@ namespace Server.Engines.Plants
return hueInfo.IsBright() ? 1113493 : 1113492; // ~1_amount~ [bright] ~2_color~ ~3_type~ seeds
}
}
}
}

View file

@ -14,50 +14,30 @@ namespace Server.Engines.Plants
from.InRange(m_Plant.GetWorldLocation(), 3))
{
if (!m_Plant.IsUsableBy(from))
{
m_Plant.LabelTo(from,
1061856); // You must have the item in your backpack or locked down in order to use it.
}
else if (!m_Plant.IsCrossable)
{
m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant!
}
else if (!m_Plant.PlantSystem.PollenProducing)
{
m_Plant.LabelTo(from, 1053051); // You cannot gather pollen from a plant in this stage of development!
}
else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy)
{
m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant!
}
else
{
if (!(targeted is PlantItem targ) || targ.PlantStatus >= PlantStatus.DecorativePlant ||
targ.PlantStatus <= PlantStatus.BowlOfDirt)
{
m_Plant.LabelTo(from, 1053070); // You can only pollinate other specially grown plants!
}
else if (!targ.IsUsableBy(from))
{
targ.LabelTo(from,
1061856); // You must have the item in your backpack or locked down in order to use it.
}
else if (!targ.IsCrossable)
{
targ.LabelTo(from, 1053073); // You cannot cross-pollinate with a mutated plant!
}
else if (!targ.PlantSystem.PollenProducing)
{
targ.LabelTo(from, 1053074); // This plant is not in the flowering stage. You cannot pollinate it!
}
else if (targ.PlantSystem.Health < PlantHealth.Healthy)
{
targ.LabelTo(from, 1053075); // You cannot pollinate an unhealthy plant!
}
else if (targ.PlantSystem.Pollinated)
{
targ.LabelTo(from, 1053072); // This plant has already been pollinated!
}
else if (targ == m_Plant)
{
targ.PlantSystem.Pollinated = true;
@ -85,4 +65,4 @@ namespace Server.Engines.Plants
m_Plant.IsUsableBy(from)) from.SendGump(new ReproductionGump(m_Plant));
}
}
}
}

View file

@ -138,24 +138,21 @@ namespace Server.Engines.Plants
}
case 3: // Pollination
{
from.Send(new DisplayHelpTopic(67, true)); // POLLINATION STATE
ContentPackets.SendDisplayHelpTopic(from.NetState, 67, true); // POLLINATION STATE
from.SendGump(new ReproductionGump(m_Plant));
break;
}
case 4: // Resources
{
from.Send(new DisplayHelpTopic(69, true)); // RESOURCE PRODUCTION
ContentPackets.SendDisplayHelpTopic(from.NetState, 69, true); // RESOURCE PRODUCTION
from.SendGump(new ReproductionGump(m_Plant));
break;
}
case 5: // Seeds
{
from.Send(new DisplayHelpTopic(68, true)); // SEED PRODUCTION
ContentPackets.SendDisplayHelpTopic(from.NetState, 68, true); // SEED PRODUCTION
from.SendGump(new ReproductionGump(m_Plant));
break;
@ -200,9 +197,7 @@ namespace Server.Engines.Plants
m_Plant.LabelTo(from, 1053055); // Mutated plants do not produce resources!
}
else if (system.AvailableResources == 0)
{
m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather!
}
else
{
Item resource = resInfo.CreateResource();
@ -229,13 +224,9 @@ namespace Server.Engines.Plants
PlantSystem system = m_Plant.PlantSystem;
if (!m_Plant.Reproduces)
{
m_Plant.LabelTo(from, 1053060); // Mutated plants do not produce seeds!
}
else if (system.AvailableSeeds == 0)
{
m_Plant.LabelTo(from, 1053061); // This plant has no seeds to gather!
}
else
{
Seed seed = new Seed(system.SeedType, system.SeedHue, true);

View file

@ -64,7 +64,7 @@ namespace Server.Engines.Plants
}
case 2: // Help
{
from.Send(new DisplayHelpTopic(70, true)); // DECORATIVE MODE
ContentPackets.SendDisplayHelpTopic(from.NetState, 70, true); // DECORATIVE MODE
from.SendGump(new SetToDecorativeGump(m_Plant));

View file

@ -167,11 +167,10 @@ namespace Server.Engines.Quests.Collector
{
if (m_Quantity < m_Completed)
{
if (!IsChildOf(from.Backpack))
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x2C, 3, 500309, "",
"")); // Nothing Happens.
else
if (IsChildOf(from.Backpack))
from.Target = new InternalTarget(this);
else
Packets.SendMessageLocalized(from.NetState, Serial, ItemID, MessageType.Regular, 0x2C, 3, 500309); // Nothing Happens.
}
}
@ -245,15 +244,15 @@ namespace Server.Engines.Quests.Collector
if (targObsidian.Quantity >= m_Completed)
targObsidian.StatueName = RandomName(from);
from.Send(new AsciiMessage(targObsidian.Serial, targObsidian.ItemID, MessageType.Regular, 0x59, 3,
m_Obsidian.Name, "Something Happened."));
Packets.SendAsciiMessage(from.NetState, targObsidian.Serial, targObsidian.ItemID, MessageType.Regular, 0x59, 3,
m_Obsidian.Name, "Something Happened.");
return;
}
from.Send(new MessageLocalized(m_Obsidian.Serial, m_Obsidian.ItemID, MessageType.Regular, 0x2C, 3, 500309,
m_Obsidian.Name, "")); // Nothing Happens.
Packets.SendMessageLocalized(from.NetState, m_Obsidian.Serial, m_Obsidian.ItemID, MessageType.Regular, 0x2C, 3, 500309,
m_Obsidian.Name); // Nothing Happens.
}
}
}
}
}

View file

@ -359,4 +359,4 @@ namespace Server.Engines.Quests.Collector
{
public override object Message => 1055136;
}
}
}

View file

@ -99,11 +99,10 @@ namespace Server.Items
else if (from.Map == Map.Ilshenar)
{
#if false
banks = m_IlshenarBanks;
moongates = PMList.Ilshenar;
banks = m_IlshenarBanks;
moongates = PMList.Ilshenar;
#else
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, 1061684, "",
"")); // The magic of the sextant fails...
Packets.SendMessageLocalized(from.NetState, Serial, ItemID, MessageType.Label, 0x482, 3, 1061684); // The magic of the sextant fails...
return;
#endif
}
@ -154,7 +153,7 @@ namespace Server.Items
else
moonMsg = 1048018; // You are next to a Moongate at the moment.
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg, "", ""));
Packets.SendMessageLocalized(from.NetState, Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg);
int bankMsg;
if (bankDistance == double.MaxValue)
@ -166,7 +165,7 @@ namespace Server.Items
else
bankMsg = 1048019; // You are next to a Bank at the moment.
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg, "", ""));
Packets.SendMessageLocalized(from.NetState, Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg);
}
public override void Serialize(GenericWriter writer)
@ -183,4 +182,4 @@ namespace Server.Items
int version = reader.ReadInt();
}
}
}
}

View file

@ -44,9 +44,7 @@ namespace Server.Engines.Quests
switch (encoding)
{
default:
{
return null;
}
case 0x01: // indexed
{
int index = reader.ReadEncodedInt();
@ -75,9 +73,7 @@ namespace Server.Engines.Quests
switch (encoding)
{
default:
{
return null;
}
case 0x01:
{
Type type = ReadType(QuestSystem.QuestTypes, reader);
@ -94,9 +90,7 @@ namespace Server.Engines.Quests
public static void Serialize(QuestSystem qs, GenericWriter writer)
{
if (qs == null)
{
writer.WriteEncodedInt(0x00);
}
else
{
writer.WriteEncodedInt(0x01);
@ -114,9 +108,7 @@ namespace Server.Engines.Quests
switch (encoding)
{
default:
{
return null;
}
case 0x01:
{
Type type = ReadType(referenceTable, reader);
@ -133,9 +125,7 @@ namespace Server.Engines.Quests
public static void Serialize(Type[] referenceTable, QuestObjective obj, GenericWriter writer)
{
if (obj == null)
{
writer.WriteEncodedInt(0x00);
}
else
{
writer.WriteEncodedInt(0x01);
@ -153,9 +143,7 @@ namespace Server.Engines.Quests
switch (encoding)
{
default:
{
return null;
}
case 0x01:
{
Type type = ReadType(referenceTable, reader);
@ -172,9 +160,7 @@ namespace Server.Engines.Quests
public static void Serialize(Type[] referenceTable, QuestConversation conv, GenericWriter writer)
{
if (conv == null)
{
writer.WriteEncodedInt(0x00);
}
else
{
writer.WriteEncodedInt(0x01);

View file

@ -259,7 +259,7 @@ namespace Server.Engines.Quests
From.SendGump(new QuestObjectivesGump(Objectives));
QuestObjective last = Objectives[Objectives.Count - 1];
QuestObjective last = Objectives[^1];
if (last.Info != null)
From.SendGump(new QuestItemInfoGump(last.Info));
@ -276,7 +276,7 @@ namespace Server.Engines.Quests
From.SendGump(new QuestConversationsGump(Conversations));
QuestConversation last = Conversations[Conversations.Count - 1];
QuestConversation last = Conversations[^1];
if (last.Info != null)
From.SendGump(new QuestItemInfoGump(last.Info));

Some files were not shown because too many files have changed in this diff Show more