fix: Overhauls champion titles & codegen champion system (#1430)
## MAJOR CHANGE Added a champion title system to facilitate the existing champion titles. This should make it easier to extend or create other related game content. Champion titles will be saved in a folder called _ChampionTitles_. ### Motivation The motivation to refactor was two-folder, but mostly related to performance in two ways. First, every player had a ChampionTitleInfo object with an array of ChamptionTitleInfo. We want to eliminate the need for this information unless a player actually uses it. This should save a considerable amount of memory. Second, to facilitate the atrophy mechanic, the champion titles would run atrophy post-world save, adding to the time that the server is frozen. Eliminating this post-world save side effect unlocks our ability to further optimize the world save process since there are no direct side effects. ### Bugs fixed - [X] Fixed titles getting cut off on the paperdoll - [X] Fixed champion title not displaying overhead (OPL) ### Screenshots <img width="216" alt="image" src="https://github.com/modernuo/ModernUO/assets/3953314/8916f895-8d68-4fb0-892e-108a0c43be90">
This commit is contained in:
parent
4dddc8d3f1
commit
51ecee6caa
44 changed files with 3028 additions and 2785 deletions
|
|
@ -13,56 +13,31 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using ModernUO.Serialization;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0, false)]
|
||||
public partial class ChampionAltar : PentagramAddon
|
||||
{
|
||||
public class ChampionAltar : PentagramAddon
|
||||
[SerializableField(0, setter: "private")]
|
||||
private ChampionSpawn _spawn;
|
||||
|
||||
public ChampionAltar(ChampionSpawn spawn) => _spawn = spawn;
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
public ChampionSpawn Spawn { get; private set; }
|
||||
base.OnAfterDelete();
|
||||
Spawn?.Delete();
|
||||
}
|
||||
|
||||
public ChampionAltar(ChampionSpawn spawn) => Spawn = spawn;
|
||||
|
||||
public override void OnAfterDelete()
|
||||
[AfterDeserialization(false)]
|
||||
private void AfterDeserialization()
|
||||
{
|
||||
if (Spawn == null)
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
Spawn?.Delete();
|
||||
}
|
||||
|
||||
public ChampionAltar(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(Spawn);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Spawn = reader.ReadEntity<ChampionSpawn>();
|
||||
|
||||
if (Spawn == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,95 +13,70 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using ModernUO.Serialization;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0, false)]
|
||||
public partial class ChampionPlatform : BaseAddon
|
||||
{
|
||||
public class ChampionPlatform : BaseAddon
|
||||
[SerializableField(0, setter: "private")]
|
||||
private ChampionSpawn _spawn;
|
||||
|
||||
public ChampionPlatform(ChampionSpawn spawn)
|
||||
{
|
||||
public ChampionSpawn Spawn { get; private set; }
|
||||
_spawn = spawn;
|
||||
|
||||
public ChampionPlatform(ChampionSpawn spawn)
|
||||
for (var x = -2; x <= 2; ++x)
|
||||
{
|
||||
Spawn = spawn;
|
||||
|
||||
for (var x = -2; x <= 2; ++x)
|
||||
for (var y = -2; y <= 2; ++y)
|
||||
{
|
||||
for (var y = -2; y <= 2; ++y)
|
||||
{
|
||||
AddComponent(0x750, x, y, -5);
|
||||
}
|
||||
AddComponent(0x750, x, y, -5);
|
||||
}
|
||||
}
|
||||
|
||||
for (var x = -1; x <= 1; ++x)
|
||||
for (var x = -1; x <= 1; ++x)
|
||||
{
|
||||
for (var y = -1; y <= 1; ++y)
|
||||
{
|
||||
for (var y = -1; y <= 1; ++y)
|
||||
{
|
||||
AddComponent(0x750, x, y, 0);
|
||||
}
|
||||
AddComponent(0x750, x, y, 0);
|
||||
}
|
||||
|
||||
for (var i = -1; i <= 1; ++i)
|
||||
{
|
||||
AddComponent(0x751, i, 2, 0);
|
||||
AddComponent(0x752, 2, i, 0);
|
||||
|
||||
AddComponent(0x753, i, -2, 0);
|
||||
AddComponent(0x754, -2, i, 0);
|
||||
}
|
||||
|
||||
AddComponent(0x759, -2, -2, 0);
|
||||
AddComponent(0x75A, 2, 2, 0);
|
||||
AddComponent(0x75B, -2, 2, 0);
|
||||
AddComponent(0x75C, 2, -2, 0);
|
||||
}
|
||||
|
||||
public void AddComponent(int id, int x, int y, int z)
|
||||
for (var i = -1; i <= 1; ++i)
|
||||
{
|
||||
AddonComponent ac = new AddonComponent(id) { Hue = 0x497 };
|
||||
AddComponent(ac, x, y, z);
|
||||
AddComponent(0x751, i, 2, 0);
|
||||
AddComponent(0x752, 2, i, 0);
|
||||
|
||||
AddComponent(0x753, i, -2, 0);
|
||||
AddComponent(0x754, -2, i, 0);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
AddComponent(0x759, -2, -2, 0);
|
||||
AddComponent(0x75A, 2, 2, 0);
|
||||
AddComponent(0x75B, -2, 2, 0);
|
||||
AddComponent(0x75C, 2, -2, 0);
|
||||
}
|
||||
|
||||
public void AddComponent(int id, int x, int y, int z)
|
||||
{
|
||||
AddonComponent ac = new AddonComponent(id) { Hue = 0x497 };
|
||||
AddComponent(ac, x, y, z);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
Spawn?.Delete();
|
||||
}
|
||||
|
||||
[AfterDeserialization(false)]
|
||||
private void AfterDeserialization()
|
||||
{
|
||||
if (Spawn == null)
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
Spawn?.Delete();
|
||||
}
|
||||
|
||||
public ChampionPlatform(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(Spawn);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Spawn = reader.ReadEntity<ChampionSpawn>();
|
||||
|
||||
if (Spawn == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,86 +13,41 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using ModernUO.Serialization;
|
||||
using Server.Engines.CannedEvil;
|
||||
|
||||
namespace Server.Items
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(2, false)]
|
||||
public partial class ChampionSkull : Item
|
||||
{
|
||||
public class ChampionSkull : Item
|
||||
[InvalidateProperties]
|
||||
[SerializableField(0)]
|
||||
[SerializedCommandProperty(AccessLevel.GameMaster)]
|
||||
private ChampionSkullType _type;
|
||||
|
||||
public override int LabelNumber => 1049479 + (int)_type;
|
||||
|
||||
[Constructible]
|
||||
public ChampionSkull(ChampionSkullType type) : base(0x1AE1)
|
||||
{
|
||||
private ChampionSkullType m_Type;
|
||||
_type = type;
|
||||
LootType = LootType.Cursed;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ChampionSkullType Type
|
||||
// TODO: All hue values
|
||||
Hue = type switch
|
||||
{
|
||||
get => m_Type;
|
||||
set
|
||||
{
|
||||
m_Type = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
ChampionSkullType.Power => 0x159,
|
||||
ChampionSkullType.Venom => 0x172,
|
||||
ChampionSkullType.Greed => 0x1EE,
|
||||
ChampionSkullType.Death => 0x025,
|
||||
ChampionSkullType.Pain => 0x035,
|
||||
_ => Hue
|
||||
};
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049479 + (int)m_Type;
|
||||
|
||||
[Constructible]
|
||||
public ChampionSkull(ChampionSkullType type) : base(0x1AE1)
|
||||
{
|
||||
m_Type = type;
|
||||
LootType = LootType.Cursed;
|
||||
|
||||
// TODO: All hue values
|
||||
Hue = type switch
|
||||
{
|
||||
ChampionSkullType.Power => 0x159,
|
||||
ChampionSkullType.Venom => 0x172,
|
||||
ChampionSkullType.Greed => 0x1EE,
|
||||
ChampionSkullType.Death => 0x025,
|
||||
ChampionSkullType.Pain => 0x035,
|
||||
_ => Hue
|
||||
};
|
||||
}
|
||||
|
||||
public ChampionSkull(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(1); // version
|
||||
|
||||
writer.Write((int)m_Type);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
case 0:
|
||||
{
|
||||
m_Type = (ChampionSkullType)reader.ReadInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (version == 0)
|
||||
{
|
||||
if (LootType != LootType.Cursed)
|
||||
{
|
||||
LootType = LootType.Cursed;
|
||||
}
|
||||
|
||||
if (Insured)
|
||||
{
|
||||
Insured = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Deserialize(IGenericReader reader, int version)
|
||||
{
|
||||
_type = (ChampionSkullType)reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,194 +13,156 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using ModernUO.Serialization;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(1, false)]
|
||||
public partial class ChampionSkullBrazier : AddonComponent
|
||||
{
|
||||
public class ChampionSkullBrazier : AddonComponent
|
||||
[InvalidateProperties]
|
||||
[SerializableField(0)]
|
||||
[SerializedCommandProperty(AccessLevel.GameMaster)]
|
||||
private ChampionSkullType _type;
|
||||
|
||||
[InvalidateProperties]
|
||||
[SerializableField(1)]
|
||||
[SerializedCommandProperty(AccessLevel.GameMaster)]
|
||||
private ChampionSkullPlatform _platform;
|
||||
|
||||
[SerializableProperty(2)]
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Item Skull
|
||||
{
|
||||
private ChampionSkullType m_Type;
|
||||
private Item m_Skull;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ChampionSkullPlatform Platform { get; private set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public ChampionSkullType Type
|
||||
get => _skull;
|
||||
set
|
||||
{
|
||||
get => m_Type;
|
||||
set
|
||||
{
|
||||
m_Type = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
_skull = value;
|
||||
this.MarkDirty();
|
||||
_platform?.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049489 + (int)_type;
|
||||
|
||||
public ChampionSkullBrazier(ChampionSkullPlatform platform, ChampionSkullType type) : base(0x19BB)
|
||||
{
|
||||
Hue = 0x455;
|
||||
Light = LightType.Circle300;
|
||||
|
||||
_platform = platform;
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
_platform?.Validate();
|
||||
BeginSacrifice(from);
|
||||
}
|
||||
|
||||
public void BeginSacrifice(Mobile from)
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Item Skull
|
||||
if (_skull is { Deleted: true })
|
||||
{
|
||||
get => m_Skull;
|
||||
set
|
||||
{
|
||||
m_Skull = value;
|
||||
Platform?.Validate();
|
||||
}
|
||||
Skull = null;
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049489 + (int)m_Type;
|
||||
|
||||
public ChampionSkullBrazier(ChampionSkullPlatform platform, ChampionSkullType type) : base(0x19BB)
|
||||
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
|
||||
{
|
||||
Hue = 0x455;
|
||||
Light = LightType.Circle300;
|
||||
from.SendLocalizedMessage(500446); // That is too far away.
|
||||
}
|
||||
else if (!Harrower.CanSpawn)
|
||||
{
|
||||
from.SendMessage("The harrower has already been spawned.");
|
||||
}
|
||||
else if (_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!
|
||||
}
|
||||
}
|
||||
|
||||
Platform = platform;
|
||||
m_Type = type;
|
||||
public void EndSacrifice(Mobile from, ChampionSkull skull)
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public ChampionSkullBrazier(Serial serial) : base(serial)
|
||||
if (_skull is { Deleted: true })
|
||||
{
|
||||
Skull = null;
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
if (from.Map != Map || !from.InRange(GetWorldLocation(), 3))
|
||||
{
|
||||
Platform?.Validate();
|
||||
|
||||
BeginSacrifice(from);
|
||||
from.SendLocalizedMessage(500446); // That is too far away.
|
||||
}
|
||||
|
||||
public void BeginSacrifice(Mobile from)
|
||||
else if (!Harrower.CanSpawn)
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Skull is { Deleted: true })
|
||||
{
|
||||
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!
|
||||
}
|
||||
from.SendMessage("The harrower has already been spawned.");
|
||||
}
|
||||
|
||||
public void EndSacrifice(Mobile from, ChampionSkull skull)
|
||||
else if (skull == null)
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Skull is { Deleted: true })
|
||||
{
|
||||
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!
|
||||
}
|
||||
else if (m_Skull != null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
skull.Movable = false;
|
||||
skull.MoveToWorld(GetWorldTop(), Map);
|
||||
|
||||
Skull = skull;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendLocalizedMessageTo(from, 1049488); // That is not my champions awakening skull!
|
||||
}
|
||||
SendLocalizedMessageTo(from, 1049488); // That is not my champions awakening skull!
|
||||
}
|
||||
|
||||
private class SacrificeTarget : Target
|
||||
else if (_skull != null)
|
||||
{
|
||||
private readonly ChampionSkullBrazier m_Brazier;
|
||||
|
||||
public SacrificeTarget(ChampionSkullBrazier brazier) : base(12, false, TargetFlags.None) =>
|
||||
m_Brazier = brazier;
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted) =>
|
||||
m_Brazier.EndSacrifice(from, targeted as ChampionSkull);
|
||||
SendLocalizedMessageTo(from, 1049487); // I already have my champions awakening skull!
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
else if (!skull.IsChildOf(from.Backpack))
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write((int)m_Type);
|
||||
writer.Write(Platform);
|
||||
writer.Write(m_Skull);
|
||||
from.SendLocalizedMessage(1049486); // You can only sacrifice items that are in your backpack!
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
else if (skull.Type == Type)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
skull.Movable = false;
|
||||
skull.MoveToWorld(GetWorldTop(), Map);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
Skull = skull;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendLocalizedMessageTo(from, 1049488); // That is not my champions awakening skull!
|
||||
}
|
||||
}
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Type = (ChampionSkullType)reader.ReadInt();
|
||||
Platform = reader.ReadEntity<ChampionSkullPlatform>();
|
||||
m_Skull = reader.ReadEntity<Item>();
|
||||
private class SacrificeTarget : Target
|
||||
{
|
||||
private readonly ChampionSkullBrazier _brazier;
|
||||
|
||||
if (Platform == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
public SacrificeTarget(ChampionSkullBrazier brazier) : base(12, false, TargetFlags.None) =>
|
||||
_brazier = brazier;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
protected override void OnTarget(Mobile from, object targeted) =>
|
||||
_brazier.EndSacrifice(from, targeted as ChampionSkull);
|
||||
}
|
||||
|
||||
if (Hue == 0x497)
|
||||
{
|
||||
Hue = 0x455;
|
||||
}
|
||||
private void Deserialize(IGenericReader reader, int version)
|
||||
{
|
||||
_type = (ChampionSkullType)reader.ReadInt();
|
||||
_platform = reader.ReadEntity<ChampionSkullPlatform>();
|
||||
_skull = reader.ReadEntity<Item>();
|
||||
}
|
||||
|
||||
if (Light != LightType.Circle300)
|
||||
{
|
||||
Light = LightType.Circle300;
|
||||
}
|
||||
[AfterDeserialization(false)]
|
||||
private void AfterDeserialization()
|
||||
{
|
||||
if (_platform == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,127 +13,104 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using ModernUO.Serialization;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0, false)]
|
||||
public partial class ChampionSkullPlatform : BaseAddon
|
||||
{
|
||||
public class ChampionSkullPlatform : BaseAddon
|
||||
[SerializableField(0)]
|
||||
private ChampionSkullBrazier _power;
|
||||
|
||||
[SerializableField(1)]
|
||||
private ChampionSkullBrazier _enlightenment;
|
||||
|
||||
[SerializableField(2)]
|
||||
private ChampionSkullBrazier _venom;
|
||||
|
||||
[SerializableField(3)]
|
||||
private ChampionSkullBrazier _pain;
|
||||
|
||||
[SerializableField(4)]
|
||||
private ChampionSkullBrazier _greed;
|
||||
|
||||
[SerializableField(5)]
|
||||
private ChampionSkullBrazier _death;
|
||||
|
||||
[Constructible]
|
||||
public ChampionSkullPlatform()
|
||||
{
|
||||
private ChampionSkullBrazier m_Power, m_Enlightenment, m_Venom, m_Pain, m_Greed, m_Death;
|
||||
AddComponent(new AddonComponent(0x71A), -1, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 1, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), -1, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), 1, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), -1, 1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, 1, -1);
|
||||
AddComponent(new AddonComponent(0x71B), 1, 1, -1);
|
||||
|
||||
[Constructible]
|
||||
public ChampionSkullPlatform()
|
||||
AddComponent(new AddonComponent(0x50F), 0, -1, 4);
|
||||
AddComponent(_power = new ChampionSkullBrazier(this, ChampionSkullType.Power), 0, -1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 1, -1, 4);
|
||||
AddComponent(_enlightenment = new ChampionSkullBrazier(this, ChampionSkullType.Enlightenment), 1, -1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), -1, 0, 4);
|
||||
AddComponent(_venom = new ChampionSkullBrazier(this, ChampionSkullType.Venom), -1, 0, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 1, 0, 4);
|
||||
AddComponent(_pain = new ChampionSkullBrazier(this, ChampionSkullType.Pain), 1, 0, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), -1, 1, 4);
|
||||
AddComponent(_greed = new ChampionSkullBrazier(this, ChampionSkullType.Greed), -1, 1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 0, 1, 4);
|
||||
AddComponent(_death = new ChampionSkullBrazier(this, ChampionSkullType.Death), 0, 1, 5);
|
||||
|
||||
AddonComponent comp = new LocalizedAddonComponent(0x20D2, 1049495) { Hue = 0x482 };
|
||||
AddComponent(comp, 0, 0, 5);
|
||||
|
||||
comp = new LocalizedAddonComponent(0x0BCF, 1049496) { Hue = 0x482 };
|
||||
AddComponent(comp, 0, 2, -7);
|
||||
|
||||
comp = new LocalizedAddonComponent(0x0BD0, 1049497) { Hue = 0x482 };
|
||||
AddComponent(comp, 2, 0, -7);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (Validate(_power) && Validate(_enlightenment) && Validate(_venom) && Validate(_pain) &&
|
||||
Validate(_greed) && Validate(_death))
|
||||
{
|
||||
AddComponent(new AddonComponent(0x71A), -1, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 1, -1, -1);
|
||||
AddComponent(new AddonComponent(0x709), -1, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), 1, 0, -1);
|
||||
AddComponent(new AddonComponent(0x709), -1, 1, -1);
|
||||
AddComponent(new AddonComponent(0x709), 0, 1, -1);
|
||||
AddComponent(new AddonComponent(0x71B), 1, 1, -1);
|
||||
Mobile harrower = Harrower.Spawn(new Point3D(X, Y, Z + 6), Map);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 0, -1, 4);
|
||||
AddComponent(m_Power = new ChampionSkullBrazier(this, ChampionSkullType.Power), 0, -1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 1, -1, 4);
|
||||
AddComponent(m_Enlightenment = new ChampionSkullBrazier(this, ChampionSkullType.Enlightenment), 1, -1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), -1, 0, 4);
|
||||
AddComponent(m_Venom = new ChampionSkullBrazier(this, ChampionSkullType.Venom), -1, 0, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 1, 0, 4);
|
||||
AddComponent(m_Pain = new ChampionSkullBrazier(this, ChampionSkullType.Pain), 1, 0, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), -1, 1, 4);
|
||||
AddComponent(m_Greed = new ChampionSkullBrazier(this, ChampionSkullType.Greed), -1, 1, 5);
|
||||
|
||||
AddComponent(new AddonComponent(0x50F), 0, 1, 4);
|
||||
AddComponent(m_Death = new ChampionSkullBrazier(this, ChampionSkullType.Death), 0, 1, 5);
|
||||
|
||||
AddonComponent comp = new LocalizedAddonComponent(0x20D2, 1049495) { Hue = 0x482 };
|
||||
AddComponent(comp, 0, 0, 5);
|
||||
|
||||
comp = new LocalizedAddonComponent(0x0BCF, 1049496) { Hue = 0x482 };
|
||||
AddComponent(comp, 0, 2, -7);
|
||||
|
||||
comp = new LocalizedAddonComponent(0x0BD0, 1049497) { Hue = 0x482 };
|
||||
AddComponent(comp, 2, 0, -7);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (Validate(m_Power) && Validate(m_Enlightenment) && Validate(m_Venom) && Validate(m_Pain) &&
|
||||
Validate(m_Greed) && Validate(m_Death))
|
||||
if (harrower == null)
|
||||
{
|
||||
Mobile harrower = Harrower.Spawn(new Point3D(X, Y, Z + 6), Map);
|
||||
|
||||
if (harrower == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Clear(m_Power);
|
||||
Clear(m_Enlightenment);
|
||||
Clear(m_Venom);
|
||||
Clear(m_Pain);
|
||||
Clear(m_Greed);
|
||||
Clear(m_Death);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear(ChampionSkullBrazier brazier)
|
||||
{
|
||||
if (brazier != null)
|
||||
{
|
||||
Effects.SendBoltEffect(brazier);
|
||||
|
||||
brazier.Skull?.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Validate(ChampionSkullBrazier brazier) => brazier is { Skull: { Deleted: false } };
|
||||
|
||||
public ChampionSkullPlatform(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Power);
|
||||
writer.Write(m_Enlightenment);
|
||||
writer.Write(m_Venom);
|
||||
writer.Write(m_Pain);
|
||||
writer.Write(m_Greed);
|
||||
writer.Write(m_Death);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Power = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
m_Enlightenment = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
m_Venom = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
m_Pain = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
m_Greed = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
m_Death = reader.ReadEntity<ChampionSkullBrazier>();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
Clear(_power);
|
||||
Clear(_enlightenment);
|
||||
Clear(_venom);
|
||||
Clear(_pain);
|
||||
Clear(_greed);
|
||||
Clear(_death);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear(ChampionSkullBrazier brazier)
|
||||
{
|
||||
if (brazier != null)
|
||||
{
|
||||
Effects.SendBoltEffect(brazier);
|
||||
|
||||
brazier.Skull?.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Validate(ChampionSkullBrazier brazier) => brazier is { Skull: { Deleted: false } };
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
150
Projects/UOContent/Engines/CannedEvil/ChampionSpawnInfo.cs
Normal file
150
Projects/UOContent/Engines/CannedEvil/ChampionSpawnInfo.cs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
public enum ChampionSpawnType
|
||||
{
|
||||
Abyss,
|
||||
Arachnid,
|
||||
ColdBlood,
|
||||
ForestLord,
|
||||
VerminHorde,
|
||||
UnholyTerror,
|
||||
SleepingDragon,
|
||||
Glade,
|
||||
Corrupt,
|
||||
// Unliving,
|
||||
// Pit,
|
||||
// DragonTurtle,
|
||||
// Khaldun
|
||||
}
|
||||
|
||||
public class ChampionSpawnInfo
|
||||
{
|
||||
public ChampionSpawnType Type { get; }
|
||||
|
||||
public Type Champion { get; }
|
||||
|
||||
public Type[][] SpawnTypes { get; }
|
||||
|
||||
public TextDefinition[] LevelNames { get; }
|
||||
|
||||
public ChampionSpawnInfo(ChampionSpawnType type, Type champion, TextDefinition[] levelNames, Type[][] spawnTypes)
|
||||
{
|
||||
Type = type;
|
||||
Champion = champion;
|
||||
LevelNames = levelNames;
|
||||
SpawnTypes = spawnTypes;
|
||||
}
|
||||
|
||||
// After updating this table, make sure to update ChampionTitleContext.
|
||||
public static ChampionSpawnInfo[] Table { get; } = {
|
||||
new(ChampionSpawnType.Abyss, typeof(Semidar), new TextDefinition[]{ 1113118, 1113107, 1113096 }, new[]
|
||||
{
|
||||
new[]{ typeof(GreaterMongbat), typeof(Imp) }, // Level 1
|
||||
new[]{ typeof(Gargoyle), typeof(Harpy) }, // Level 2
|
||||
new[]{ typeof(FireGargoyle), typeof(StoneGargoyle) }, // Level 3
|
||||
new[]{ typeof(Daemon), typeof(Succubus) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.Arachnid, typeof(Mephitis), new TextDefinition[]{ 1113117, 1113106, 1113095 }, new[]
|
||||
{
|
||||
new[]{ typeof(Scorpion), typeof(GiantSpider) }, // Level 1
|
||||
new[]{ typeof(TerathanDrone), typeof(TerathanWarrior) }, // Level 2
|
||||
new[]{ typeof(DreadSpider), typeof(TerathanMatriarch) }, // Level 3
|
||||
new[]{ typeof(PoisonElemental), typeof(TerathanAvenger) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.ColdBlood, typeof(Rikktor), new TextDefinition[]{ 1113115, 1113104, 1113093 }, new[]
|
||||
{
|
||||
new[]{ typeof(Lizardman), typeof(GiantSerpent) }, // Level 1
|
||||
new[]{ typeof(LavaLizard), typeof(OphidianWarrior) }, // Level 2
|
||||
new[]{ typeof(Drake), typeof(OphidianArchmage) }, // Level 3
|
||||
new[]{ typeof(Dragon), typeof(OphidianKnight) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.ForestLord, typeof(LordOaks), new TextDefinition[]{ 1113116, 1113105, 1113094 }, new[]
|
||||
{
|
||||
new[]{ typeof(Pixie), typeof(ShadowWisp) }, // Level 1
|
||||
new[]{ typeof(Kirin), typeof(Wisp) }, // Level 2
|
||||
new[]{ typeof(Centaur), typeof(Unicorn) }, // Level 3
|
||||
new[]{ typeof(EtherealWarrior), typeof(SerpentineDragon) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.VerminHorde, typeof(Barracoon), new TextDefinition[]{ 1113119, 1113108, 1113097 }, new[]
|
||||
{
|
||||
new[]{ typeof(GiantRat), typeof(Slime) }, // Level 1
|
||||
new[]{ typeof(DireWolf), typeof(Ratman) }, // Level 2
|
||||
new[]{ typeof(HellHound), typeof(RatmanMage) }, // Level 3
|
||||
new[]{ typeof(RatmanArcher), typeof(SilverSerpent) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.UnholyTerror, typeof(Neira), new TextDefinition[]{ 1113120, 1113109, 1113098 }, new[]
|
||||
{
|
||||
Core.AOS ? // Level 1
|
||||
new[]{ typeof(Bogle), typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) }
|
||||
: new[]{ typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) },
|
||||
|
||||
new[]{ typeof(BoneMagi), typeof(Mummy), typeof(SkeletalMage) }, // Level 2
|
||||
new[]{ typeof(BoneKnight), typeof(Lich), typeof(SkeletalKnight) }, // Level 3
|
||||
new[]{ typeof(LichLord), typeof(RottingCorpse) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.SleepingDragon, typeof(Serado), new TextDefinition[]{ 1113121, 1113110, 1113099 }, new[]
|
||||
{
|
||||
new[]{ typeof(DeathwatchBeetleHatchling), typeof(Lizardman) }, // Level 1
|
||||
new[]{ typeof(DeathwatchBeetle), typeof(Kappa) }, // Level 2
|
||||
new[]{ typeof(LesserHiryu), typeof(RevenantLion) }, // Level 3
|
||||
new[]{ typeof(Hiryu), typeof(Oni) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.Glade, typeof(Twaulo), new TextDefinition[]{ 1113123, 1113112, 1113101 }, new[]
|
||||
{
|
||||
new[]{ typeof(Pixie), typeof(ShadowWisp) }, // Level 1
|
||||
new[]{ typeof(Centaur), typeof(MLDryad) }, // Level 2
|
||||
new[]{ typeof(Satyr), typeof(CuSidhe) }, // Level 3
|
||||
new[]{ typeof(FeralTreefellow), typeof(RagingGrizzlyBear) } // Level 4
|
||||
}),
|
||||
new(ChampionSpawnType.Corrupt, typeof(Ilhenir), new TextDefinition[]{ 1113122, 1113111, 1113100 }, new[]
|
||||
{
|
||||
new[]{ typeof(PlagueSpawn), typeof(Bogling) }, // Level 1
|
||||
new[]{ typeof(PlagueBeast), typeof(BogThing) }, // Level 2
|
||||
new[]{ typeof(PlagueBeastLord), typeof(InterredGrizzle) }, // Level 3
|
||||
new[]{ typeof(FetidEssence), typeof(PestilentBandage) } // Level 4
|
||||
}),
|
||||
// new(ChampionSpawnType.Unliving, typeof(PrimevalLich), new TextDefinition[]{ 1113124, 1113113, 1113102 }, new[]
|
||||
// {
|
||||
// new[]{ typeof(GoreFiend), typeof(VampireBat) },
|
||||
// new[]{ typeof(FleshGolem), typeof(DarkWisp) },
|
||||
// new[]{ typeof(UndeadGargoyle), typeof(Wight) },
|
||||
// new[]{ typeof(SkeletalDrake), typeof(DreamWraith) }
|
||||
// }),
|
||||
// new(ChampionSpawnType.Pit, typeof(AbyssalInfernal), new TextDefinition[]{ 1113125, 1113114, 1113103 }, new[]
|
||||
// {
|
||||
// new[]{ typeof(HordeMinion), typeof(ChaosDaemon) },
|
||||
// new[]{ typeof(StoneHarpy), typeof(ArcaneDaemon) },
|
||||
// new[]{ typeof(PitFiend), typeof(Moloch) },
|
||||
// new[]{ typeof(ArchDaemon), typeof(AbyssalAbomination) }
|
||||
// }),
|
||||
// new(ChampionSpawnType.Valley, typeof(DragonTurtle), new TextDefinition[]{ "Explorer", "Huntsman", "Msafiri" }, new[]
|
||||
// {
|
||||
// new[]{ typeof(MyrmidexDrone), typeof(MyrmidexLarvae) },
|
||||
// new[]{ typeof(SilverbackGorilla), typeof(WildTiger) },
|
||||
// new[]{ typeof(GreaterPhoenix ), typeof(Infernus) },
|
||||
// new[]{ typeof(Dimetrosaur), typeof(Allosaurus) }
|
||||
// }),
|
||||
// new(ChampionSpawnType.Khaldun, typeof(KhalAnkur), new TextDefinition[]{ "Banisher", "Enforcer", "Eradicator" }, new[]
|
||||
// {
|
||||
// new[]{ typeof(SkelementalKnight), typeof(KhaldunBlood) },
|
||||
// new[]{ typeof(SkelementalMage), typeof(Viscera) },
|
||||
// new[]{ typeof(CultistAmbusher), typeof(ShadowFiend) },
|
||||
// new[]{ typeof(KhalAnkurWarriors) }
|
||||
// })
|
||||
};
|
||||
|
||||
public static ChampionSpawnInfo GetInfo(ChampionSpawnType type)
|
||||
{
|
||||
var v = (int)type;
|
||||
|
||||
if (v < 0 || v >= Table.Length)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
|
||||
return Table[v];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: ChampionSpawnType.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
{
|
||||
public enum ChampionSpawnType
|
||||
{
|
||||
Abyss,
|
||||
Arachnid,
|
||||
ColdBlood,
|
||||
ForestLord,
|
||||
VerminHorde,
|
||||
UnholyTerror,
|
||||
SleepingDragon,
|
||||
Glade,
|
||||
Pestilence,
|
||||
Graveyard
|
||||
}
|
||||
|
||||
public class ChampionSpawnInfo
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public Type Champion { get; }
|
||||
|
||||
public Type[][] SpawnTypes { get; }
|
||||
|
||||
public string[] LevelNames { get; }
|
||||
|
||||
public ChampionSpawnInfo(string name, Type champion, string[] levelNames, Type[][] spawnTypes)
|
||||
{
|
||||
Name = name;
|
||||
Champion = champion;
|
||||
LevelNames = levelNames;
|
||||
SpawnTypes = spawnTypes;
|
||||
}
|
||||
|
||||
public static ChampionSpawnInfo[] Table { get; } = {
|
||||
new("Abyss", typeof(Semidar), new[]{ "Foe", "Assassin", "Conqueror" }, new[]
|
||||
{
|
||||
new[]{ typeof(GreaterMongbat), typeof(Imp) }, // Level 1
|
||||
new[]{ typeof(Gargoyle), typeof(Harpy) }, // Level 2
|
||||
new[]{ typeof(FireGargoyle), typeof(StoneGargoyle) }, // Level 3
|
||||
new[]{ typeof(Daemon), typeof(Succubus) } // Level 4
|
||||
}),
|
||||
new("Arachnid", typeof(Mephitis), new[]{ "Bane", "Killer", "Vanquisher" }, new[]
|
||||
{
|
||||
new[]{ typeof(Scorpion), typeof(GiantSpider) }, // Level 1
|
||||
new[]{ typeof(TerathanDrone), typeof(TerathanWarrior) }, // Level 2
|
||||
new[]{ typeof(DreadSpider), typeof(TerathanMatriarch) }, // Level 3
|
||||
new[]{ typeof(PoisonElemental), typeof(TerathanAvenger) } // Level 4
|
||||
}),
|
||||
new("Cold Blood", typeof(Rikktor), new[]{ "Blight", "Slayer", "Destroyer" }, new[]
|
||||
{
|
||||
new[]{ typeof(Lizardman), typeof(GiantSerpent) }, // Level 1
|
||||
new[]{ typeof(LavaLizard), typeof(OphidianWarrior) }, // Level 2
|
||||
new[]{ typeof(Drake), typeof(OphidianArchmage) }, // Level 3
|
||||
new[]{ typeof(Dragon), typeof(OphidianKnight) } // Level 4
|
||||
}),
|
||||
new("Forest Lord", typeof(LordOaks), new[]{ "Enemy", "Curse", "Slaughterer" }, new[]
|
||||
{
|
||||
new[]{ typeof(Pixie), typeof(ShadowWisp) }, // Level 1
|
||||
new[]{ typeof(Kirin), typeof(Wisp) }, // Level 2
|
||||
new[]{ typeof(Centaur), typeof(Unicorn) }, // Level 3
|
||||
new[]{ typeof(EtherealWarrior), typeof(SerpentineDragon) } // Level 4
|
||||
}),
|
||||
new("Vermin Horde", typeof(Barracoon), new[]{ "Adversary", "Subjugator", "Eradicator" }, new[]
|
||||
{
|
||||
new[]{ typeof(GiantRat), typeof(Slime) }, // Level 1
|
||||
new[]{ typeof(DireWolf), typeof(Ratman) }, // Level 2
|
||||
new[]{ typeof(HellHound), typeof(RatmanMage) }, // Level 3
|
||||
new[]{ typeof(RatmanArcher), typeof(SilverSerpent) } // Level 4
|
||||
}),
|
||||
new("Unholy Terror", typeof(Neira), new[]{ "Scourge", "Punisher", "Nemesis" }, new[]
|
||||
{
|
||||
Core.AOS ? // Level 1
|
||||
new[]{ typeof(Bogle), typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) }
|
||||
: new[]{ typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) },
|
||||
|
||||
new[]{ typeof(BoneMagi), typeof(Mummy), typeof(SkeletalMage) }, // Level 2
|
||||
new[]{ typeof(BoneKnight), typeof(Lich), typeof(SkeletalKnight) }, // Level 3
|
||||
new[]{ typeof(LichLord), typeof(RottingCorpse) } // Level 4
|
||||
}),
|
||||
new("Sleeping Dragon", typeof(Serado), new[]{ "Rival", "Challenger", "Antagonist" } , new[]
|
||||
{
|
||||
new[]{ typeof(DeathwatchBeetleHatchling), typeof(Lizardman) }, // Level 1
|
||||
new[]{ typeof(DeathwatchBeetle), typeof(Kappa) }, // Level 2
|
||||
new[]{ typeof(LesserHiryu), typeof(RevenantLion) }, // Level 3
|
||||
new[]{ typeof(Hiryu), typeof(Oni) } // Level 4
|
||||
}),
|
||||
new("Glade", typeof(Twaulo), new[]{ "Banisher", "Enforcer", "Eradicator" } , new[]
|
||||
{
|
||||
new[]{ typeof(Pixie), typeof(ShadowWisp) }, // Level 1
|
||||
new[]{ typeof(Centaur), typeof(MLDryad) }, // Level 2
|
||||
new[]{ typeof(Satyr), typeof(CuSidhe) }, // Level 3
|
||||
new[]{ typeof(FeralTreefellow), typeof(RagingGrizzlyBear) } // Level 4
|
||||
}),
|
||||
new("The Corrupt", typeof(Ilhenir), new[]{ "Cleanser", "Expunger", "Depurator" } , new[]
|
||||
{
|
||||
new[]{ typeof(PlagueSpawn), typeof(Bogling) }, // Level 1
|
||||
new[]{ typeof(PlagueBeast), typeof(BogThing) }, // Level 2
|
||||
new[]{ typeof(PlagueBeastLord), typeof(InterredGrizzle) }, // Level 3
|
||||
new[]{ typeof(FetidEssence), typeof(PestilentBandage) } // Level 4
|
||||
}),
|
||||
};
|
||||
|
||||
public static ChampionSpawnInfo GetInfo(ChampionSpawnType type)
|
||||
{
|
||||
var v = (int)type;
|
||||
|
||||
if (v < 0 || v >= Table.Length)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
|
||||
return Table[v];
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Projects/UOContent/Engines/CannedEvil/ChampionTitle.cs
Normal file
30
Projects/UOContent/Engines/CannedEvil/ChampionTitle.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class ChampionTitle
|
||||
{
|
||||
[EncodedInt]
|
||||
[SerializableField(0)]
|
||||
private int _value;
|
||||
|
||||
// TODO: Change to delta time
|
||||
[SerializableField(1)]
|
||||
private DateTime _lastDecay;
|
||||
|
||||
public bool Atrophy(int value)
|
||||
{
|
||||
var before = Value;
|
||||
|
||||
Value -= Math.Min(value, before);
|
||||
|
||||
if (before != Value)
|
||||
{
|
||||
LastDecay = Core.Now;
|
||||
}
|
||||
|
||||
return Value > 0;
|
||||
}
|
||||
}
|
||||
379
Projects/UOContent/Engines/CannedEvil/ChampionTitleContext.cs
Normal file
379
Projects/UOContent/Engines/CannedEvil/ChampionTitleContext.cs
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[PropertyObject]
|
||||
[SerializationGenerator(1)]
|
||||
public partial class ChampionTitleContext
|
||||
{
|
||||
private const int LossAmount = 90;
|
||||
private static readonly TimeSpan LossDelay = TimeSpan.FromDays(1.0);
|
||||
|
||||
[SerializableField(0)]
|
||||
[SerializedCommandProperty(AccessLevel.GameMaster)]
|
||||
private int _harrower;
|
||||
|
||||
private PlayerMobile _player;
|
||||
|
||||
public PlayerMobile Player => _player;
|
||||
|
||||
public ChampionTitleContext(PlayerMobile player) => _player = player;
|
||||
|
||||
// Visible to PublicMobile for migrations
|
||||
internal void Deserialize(IGenericReader reader, int version)
|
||||
{
|
||||
_harrower = reader.ReadEncodedInt();
|
||||
|
||||
var length = reader.ReadEncodedInt();
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the list/enum for ChampionSpawnInfo changes, then this has to change for migrations
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var type = (ChampionSpawnType)i;
|
||||
ref var title = ref GetTitleValueRef(type);
|
||||
|
||||
if (Unsafe.IsNullRef(ref title))
|
||||
{
|
||||
throw new NotImplementedException($"Cannot find ChampionSpawnType value {type}.");
|
||||
}
|
||||
|
||||
title = new ChampionTitle();
|
||||
title.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
|
||||
[SerializableField(1)]
|
||||
private ChampionTitle _abyss;
|
||||
|
||||
[SerializableFieldSaveFlag(1)]
|
||||
private bool ShouldSerializeAbyss() => _abyss != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int AbyssValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Abyss)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.Abyss, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime AbyssLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Abyss)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.Abyss, value);
|
||||
}
|
||||
|
||||
[SerializableField(2)]
|
||||
private ChampionTitle _arachnid;
|
||||
|
||||
[SerializableFieldSaveFlag(2)]
|
||||
private bool ShouldSerializeArachnid() => _arachnid != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int ArachnidValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Arachnid)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.Arachnid, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime ArachnidLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Arachnid)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.Arachnid, value);
|
||||
}
|
||||
|
||||
[SerializableField(3)]
|
||||
private ChampionTitle _coldBlood;
|
||||
|
||||
[SerializableFieldSaveFlag(3)]
|
||||
private bool ShouldSerializeColdBlood() => _coldBlood != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int ColdBloodValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.ColdBlood)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.ColdBlood, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime ColdBloodLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.ColdBlood)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.ColdBlood, value);
|
||||
}
|
||||
|
||||
[SerializableField(4)]
|
||||
private ChampionTitle _forestLord;
|
||||
|
||||
[SerializableFieldSaveFlag(4)]
|
||||
private bool ShouldSerializeForestLord() => _forestLord != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int ForestLordValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.ForestLord)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.ForestLord, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime ForestLordLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.ForestLord)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.ForestLord, value);
|
||||
}
|
||||
|
||||
[SerializableField(5)]
|
||||
private ChampionTitle _verminHorde;
|
||||
|
||||
[SerializableFieldSaveFlag(5)]
|
||||
private bool ShouldSerializeVerminHorde() => _verminHorde != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int VerminHordeValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.VerminHorde)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.VerminHorde, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime VerminHordeLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.VerminHorde)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.VerminHorde, value);
|
||||
}
|
||||
|
||||
[SerializableField(6)]
|
||||
private ChampionTitle _unholyTerror;
|
||||
|
||||
[SerializableFieldSaveFlag(6)]
|
||||
private bool ShouldSerializeUnholyTerror() => _unholyTerror != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int UnholyTerrorValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.UnholyTerror)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.UnholyTerror, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime UnholyTerrorLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.UnholyTerror)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.UnholyTerror, value);
|
||||
}
|
||||
|
||||
[SerializableField(7)]
|
||||
private ChampionTitle _sleepingDragon;
|
||||
|
||||
[SerializableFieldSaveFlag(7)]
|
||||
private bool ShouldSerializeSleepingDragon() => _sleepingDragon != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int SleepingDragonValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.SleepingDragon)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.SleepingDragon, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime SleepingDragonLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.SleepingDragon)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.SleepingDragon, value);
|
||||
}
|
||||
|
||||
[SerializableField(8)]
|
||||
private ChampionTitle _corrupt;
|
||||
|
||||
[SerializableFieldSaveFlag(8)]
|
||||
private bool ShouldSerializeCorrupt() => _corrupt != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int CorruptValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Corrupt)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.Corrupt, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime CorruptLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Corrupt)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.Corrupt, value);
|
||||
}
|
||||
|
||||
[SerializableField(9)]
|
||||
private ChampionTitle _glade;
|
||||
|
||||
[SerializableFieldSaveFlag(9)]
|
||||
private bool ShouldSerializeGlade() => _glade != null;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int GladeValue
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Glade)?.Value ?? 0;
|
||||
set => SetValue(ChampionSpawnType.Glade, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime GladeLastDecay
|
||||
{
|
||||
get => GetTitle(ChampionSpawnType.Glade)?.LastDecay ?? DateTime.MinValue;
|
||||
set => SetLastDecay(ChampionSpawnType.Glade, value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ChampionTitle GetTitle(ChampionSpawnType type) => GetTitleValueRef(type);
|
||||
|
||||
// Get a pointer to the title so we can manipulate it internally such as nullifying it.
|
||||
// Using this technique instead of an array decouples the context from changes to ChampionSpawnInfo.Table indexes
|
||||
private ref ChampionTitle GetTitleValueRef(ChampionSpawnType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ChampionSpawnType.Abyss:
|
||||
{
|
||||
return ref _abyss;
|
||||
}
|
||||
case ChampionSpawnType.Arachnid:
|
||||
{
|
||||
return ref _arachnid;
|
||||
}
|
||||
case ChampionSpawnType.ColdBlood:
|
||||
{
|
||||
return ref _coldBlood;
|
||||
}
|
||||
case ChampionSpawnType.ForestLord:
|
||||
{
|
||||
return ref _forestLord;
|
||||
}
|
||||
case ChampionSpawnType.VerminHorde:
|
||||
{
|
||||
return ref _verminHorde;
|
||||
}
|
||||
case ChampionSpawnType.UnholyTerror:
|
||||
{
|
||||
return ref _unholyTerror;
|
||||
}
|
||||
case ChampionSpawnType.SleepingDragon:
|
||||
{
|
||||
return ref _sleepingDragon;
|
||||
}
|
||||
case ChampionSpawnType.Glade:
|
||||
{
|
||||
return ref _glade;
|
||||
}
|
||||
case ChampionSpawnType.Corrupt:
|
||||
{
|
||||
return ref _corrupt;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return ref Unsafe.NullRef<ChampionTitle>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChampionTitle TryGetOrCreateTitle(ChampionSpawnType type)
|
||||
{
|
||||
ref var title = ref GetTitleValueRef(type);
|
||||
if (Unsafe.IsNullRef(ref title))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return title ??= new ChampionTitle();
|
||||
}
|
||||
|
||||
public void SetValue(ChampionSpawnType type, int value)
|
||||
{
|
||||
ref var title = ref GetTitleValueRef(type);
|
||||
if (Unsafe.IsNullRef(ref title))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (title != null)
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
title = null;
|
||||
|
||||
_player.InvalidateProperties();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
title = new ChampionTitle();
|
||||
}
|
||||
|
||||
title.Value = value;
|
||||
title.LastDecay = Core.Now;
|
||||
_player.InvalidateProperties();
|
||||
}
|
||||
|
||||
public void SetLastDecay(ChampionSpawnType type, DateTime value)
|
||||
{
|
||||
var title = TryGetOrCreateTitle(type);
|
||||
if (title != null)
|
||||
{
|
||||
title.LastDecay = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Award(ChampionSpawnType type, int value)
|
||||
{
|
||||
var title = TryGetOrCreateTitle(type);
|
||||
if (title == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
title.Value += value;
|
||||
if (title.LastDecay == DateTime.MinValue)
|
||||
{
|
||||
title.LastDecay = Core.Now;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckAtrophy()
|
||||
{
|
||||
var valuesUsed = _harrower > 0;
|
||||
|
||||
for (var i = 0; i < ChampionSpawnInfo.Table.Length; i++)
|
||||
{
|
||||
ref var title = ref GetTitleValueRef(ChampionSpawnInfo.Table[i].Type);
|
||||
if (Unsafe.IsNullRef(ref title))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var decay = title.LastDecay;
|
||||
if (decay > DateTime.MinValue && decay + LossDelay < Core.Now)
|
||||
{
|
||||
// Use bitwise-or to force-execute the Atrophy function
|
||||
var isUsed = title.Atrophy(LossAmount);
|
||||
|
||||
if (!isUsed)
|
||||
{
|
||||
title = null;
|
||||
}
|
||||
|
||||
valuesUsed |= isUsed;
|
||||
}
|
||||
}
|
||||
|
||||
return valuesUsed;
|
||||
}
|
||||
|
||||
public override string ToString() => "...";
|
||||
}
|
||||
172
Projects/UOContent/Engines/CannedEvil/ChampionTitleSystem.cs
Normal file
172
Projects/UOContent/Engines/CannedEvil/ChampionTitleSystem.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server.Collections;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
public static class ChampionTitleSystem
|
||||
{
|
||||
// All of the players with murders
|
||||
private static readonly Dictionary<PlayerMobile, ChampionTitleContext> _championTitleContexts = new();
|
||||
|
||||
private static readonly Timer _championTitleTimer = new ChampionTitleTimer();
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
GenericPersistence.Register("ChampionTitles", Serialize, Deserialize);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.PlayerDeleted += OnPlayerDeleted;
|
||||
|
||||
_championTitleTimer.Start();
|
||||
}
|
||||
|
||||
private static void OnPlayerDeleted(Mobile m)
|
||||
{
|
||||
if (m is PlayerMobile pm)
|
||||
{
|
||||
_championTitleContexts.Remove(pm);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Deserialize(IGenericReader reader)
|
||||
{
|
||||
var version = reader.ReadEncodedInt();
|
||||
|
||||
var count = reader.ReadEncodedInt();
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var context = new ChampionTitleContext(reader.ReadEntity<PlayerMobile>());
|
||||
context.Deserialize(reader);
|
||||
|
||||
_championTitleContexts.Add(context.Player, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Serialize(IGenericWriter writer)
|
||||
{
|
||||
writer.WriteEncodedInt(0); // version
|
||||
|
||||
writer.WriteEncodedInt(_championTitleContexts.Count);
|
||||
foreach (var (m, context) in _championTitleContexts)
|
||||
{
|
||||
writer.Write(m);
|
||||
context.Serialize(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetChampionTitleContext(this PlayerMobile player, out ChampionTitleContext context) =>
|
||||
_championTitleContexts.TryGetValue(player, out context);
|
||||
|
||||
public static ChampionTitleContext GetOrCreateChampionTitleContext(this PlayerMobile player)
|
||||
{
|
||||
ref var context = ref CollectionsMarshal.GetValueRefOrAddDefault(_championTitleContexts, player, out var exists);
|
||||
if (!exists)
|
||||
{
|
||||
context = new ChampionTitleContext(player);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
// Called when killing a harrower. Will give a minimum of 1 point.
|
||||
public static void AwardHarrowerTitle(PlayerMobile pm)
|
||||
{
|
||||
var context = pm.GetOrCreateChampionTitleContext();
|
||||
|
||||
var count = 1;
|
||||
for (var i = 0; i < ChampionSpawnInfo.Table.Length; i++)
|
||||
{
|
||||
var title = context.GetTitle(ChampionSpawnInfo.Table[i].Type);
|
||||
if (title?.Value > 900)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
context.Harrower = Math.Max(count, context.Harrower); // Harrower titles never decay.
|
||||
}
|
||||
|
||||
public static int GetChampionTitleLabel(this PlayerMobile player)
|
||||
{
|
||||
if (!player.GetChampionTitleContext(out var context))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (context.Harrower > 0)
|
||||
{
|
||||
return 1113082 + Math.Min(context.Harrower, 10);
|
||||
}
|
||||
|
||||
var highestValue = 0;
|
||||
var highestType = 0;
|
||||
|
||||
for (var i = 0; i < ChampionSpawnInfo.Table.Length; i++)
|
||||
{
|
||||
var t = context.GetTitle(ChampionSpawnInfo.Table[i].Type);
|
||||
if (t == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var v = t.Value;
|
||||
|
||||
if (v > highestValue)
|
||||
{
|
||||
highestValue = v;
|
||||
highestType = i;
|
||||
}
|
||||
}
|
||||
|
||||
var offset = highestValue switch
|
||||
{
|
||||
> 800 => 3,
|
||||
> 300 => highestValue / 300,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
var champInfo = ChampionSpawnInfo.Table[highestType];
|
||||
var championLevelName = champInfo.LevelNames[Math.Min(offset, champInfo.LevelNames.Length) - 1];
|
||||
return championLevelName.Number;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private class ChampionTitleTimer : Timer
|
||||
{
|
||||
public ChampionTitleTimer() : base(TimeSpan.FromMinutes(5.0), TimeSpan.FromMinutes(5.0))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (_championTitleContexts.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var queue = PooledRefQueue<Mobile>.Create();
|
||||
|
||||
foreach (var context in _championTitleContexts.Values)
|
||||
{
|
||||
if (!context.CheckAtrophy())
|
||||
{
|
||||
queue.Enqueue(context.Player);
|
||||
}
|
||||
}
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
_championTitleContexts.Remove((PlayerMobile)queue.Dequeue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,42 +13,30 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class DungeonChampionSpawn : ChampionSpawn
|
||||
{
|
||||
public class DungeonChampionSpawn : ChampionSpawn
|
||||
[Constructible]
|
||||
public DungeonChampionSpawn()
|
||||
{
|
||||
[Constructible]
|
||||
public DungeonChampionSpawn()
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public DungeonChampionSpawn(Serial serial) : base(serial)
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
public DungeonChampionSpawn(Serial serial)
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public override bool ProximitySpawn => true;
|
||||
public override bool AlwaysActive => false;
|
||||
public override bool ProximitySpawn => true;
|
||||
public override bool AlwaysActive => false;
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); //version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,60 +1,32 @@
|
|||
namespace Server.Items
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(0, false)]
|
||||
public partial class HarrowerGate : Moongate
|
||||
{
|
||||
public class HarrowerGate : Moongate
|
||||
[SerializableField(0)]
|
||||
private Mobile _harrower;
|
||||
|
||||
public HarrowerGate(Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap) : base(targLoc, targMap)
|
||||
{
|
||||
private Mobile m_Harrower;
|
||||
_harrower = harrower;
|
||||
|
||||
public HarrowerGate(Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap) : base(targLoc, targMap)
|
||||
Dispellable = false;
|
||||
ItemID = 0x1FD4;
|
||||
Light = LightType.Circle300;
|
||||
|
||||
MoveToWorld(loc, map);
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049498; // dark moongate
|
||||
|
||||
[AfterDeserialization(false)]
|
||||
private void AfterDeserialization()
|
||||
{
|
||||
if (_harrower == null)
|
||||
{
|
||||
m_Harrower = harrower;
|
||||
|
||||
Dispellable = false;
|
||||
ItemID = 0x1FD4;
|
||||
Light = LightType.Circle300;
|
||||
|
||||
MoveToWorld(loc, map);
|
||||
}
|
||||
|
||||
public HarrowerGate(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049498; // dark moongate
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Harrower);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Harrower = reader.ReadEntity<Mobile>();
|
||||
|
||||
if (m_Harrower == null)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Light != LightType.Circle300)
|
||||
{
|
||||
Light = LightType.Circle300;
|
||||
}
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,43 +13,31 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class LLChampionSpawn : ChampionSpawn
|
||||
{
|
||||
public class LLChampionSpawn : ChampionSpawn
|
||||
public override bool HasStarRoomGate => false;
|
||||
|
||||
[Constructible]
|
||||
public LLChampionSpawn()
|
||||
{
|
||||
public override bool HasStarRoomGate => false;
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public LLChampionSpawn()
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
public LLChampionSpawn(Serial serial)
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public LLChampionSpawn(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
public override bool AlwaysActive => false;
|
||||
|
||||
public override bool AlwaysActive => false;
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); //version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +1,68 @@
|
|||
using System;
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(1, false)]
|
||||
public partial class StarRoomGate : Moongate
|
||||
{
|
||||
public class StarRoomGate : Moongate
|
||||
private static TimeSpan GateDuration = TimeSpan.FromMinutes(2.0);
|
||||
|
||||
[SerializableField(0)]
|
||||
private bool _decays;
|
||||
|
||||
[DeltaDateTime]
|
||||
[SerializableField(1)]
|
||||
private DateTime _decayTime;
|
||||
|
||||
private Timer _timer;
|
||||
|
||||
[Constructible]
|
||||
public StarRoomGate(Point3D loc, Map map, bool decays) : this(decays)
|
||||
{
|
||||
private bool m_Decays;
|
||||
private DateTime m_DecayTime;
|
||||
private Timer m_Timer;
|
||||
MoveToWorld(loc, map);
|
||||
Effects.PlaySound(loc, map, 0x20E);
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public StarRoomGate(Point3D loc, Map map, bool decays) : this(decays)
|
||||
[Constructible]
|
||||
public StarRoomGate(bool decays = false) : base(new Point3D(5143, 1774, 0), Map.Felucca)
|
||||
{
|
||||
Dispellable = false;
|
||||
ItemID = 0x1FD4;
|
||||
|
||||
if (decays)
|
||||
{
|
||||
MoveToWorld(loc, map);
|
||||
Effects.PlaySound(loc, map, 0x20E);
|
||||
_decays = true;
|
||||
_decayTime = Core.Now + GateDuration;
|
||||
|
||||
_timer = Timer.DelayCall(GateDuration, Delete);
|
||||
}
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public StarRoomGate(bool decays = false) : base(new Point3D(5143, 1774, 0), Map.Felucca)
|
||||
public override int LabelNumber => 1049498; // dark moongate
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
_timer?.Stop();
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
private void Deserialize(IGenericReader reader, int version)
|
||||
{
|
||||
_decays = reader.ReadBool();
|
||||
|
||||
if (_decays)
|
||||
{
|
||||
Dispellable = false;
|
||||
ItemID = 0x1FD4;
|
||||
|
||||
if (decays)
|
||||
{
|
||||
m_Decays = true;
|
||||
m_DecayTime = Core.Now + TimeSpan.FromMinutes(2.0);
|
||||
|
||||
m_Timer = new InternalTimer(this, m_DecayTime);
|
||||
m_Timer.Start();
|
||||
}
|
||||
_decayTime = reader.ReadDeltaTime();
|
||||
}
|
||||
}
|
||||
|
||||
public StarRoomGate(Serial serial) : base(serial)
|
||||
[AfterDeserialization]
|
||||
private void AfterDeserialization()
|
||||
{
|
||||
if (_decays)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1049498; // dark moongate
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
m_Timer?.Stop();
|
||||
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Decays);
|
||||
|
||||
if (m_Decays)
|
||||
{
|
||||
writer.WriteDeltaTime(m_DecayTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Decays = reader.ReadBool();
|
||||
|
||||
if (m_Decays)
|
||||
{
|
||||
m_DecayTime = reader.ReadDeltaTime();
|
||||
|
||||
m_Timer = new InternalTimer(this, m_DecayTime);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private readonly Item m_Item;
|
||||
|
||||
public InternalTimer(Item item, DateTime end) : base(end - Core.Now) => m_Item = item;
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Item.Delete();
|
||||
}
|
||||
_timer = Timer.DelayCall(_decayTime - Core.Now, Delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ public static class ValorVirtue
|
|||
}
|
||||
else if (idol.Spawn.Active)
|
||||
{
|
||||
if (idol.Spawn.Champion != null) // TODO: Message?
|
||||
if (idol.Spawn.Champion != null)
|
||||
{
|
||||
return;
|
||||
from.SendLocalizedMessage(1112470); // You may not use Valor on this Champion Idol. The Champion has already spawned.
|
||||
}
|
||||
|
||||
int needed, consumed;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue