fix: Codegens familiars (#1473)

This commit is contained in:
Kamron Batman 2023-08-25 20:51:38 -07:00 committed by GitHub
parent 06309d9d59
commit 877595c513
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 508 additions and 586 deletions

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.BaseFamiliar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.DarkWolfFamiliar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.DeathAdder"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.HordeMinionFamiliar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.ShadowWispFamiliar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Mobiles.VampireBatFamiliar"
}

View file

@ -1,208 +1,190 @@
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.ContextMenus;
using Server.Items;
namespace Server.Mobiles
namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public abstract partial class BaseFamiliar : BaseCreature
{
public abstract class BaseFamiliar : BaseCreature
private bool m_LastHidden;
public BaseFamiliar() : base(AIType.AI_Melee)
{
private bool m_LastHidden;
SetSpeed(0.1, 0.11);
}
public BaseFamiliar() : base(AIType.AI_Melee)
public override bool BardImmune => true;
public override Poison PoisonImmune => Poison.Lethal;
public override bool Commandable => false;
public override bool IgnoreMobiles => true;
public override bool PlayerRangeSensitive => false;
public virtual void RangeCheck()
{
if (Deleted || ControlMaster?.Deleted != false)
{
SetSpeed(0.1, 0.11);
return;
}
public BaseFamiliar(Serial serial) : base(serial)
var range = RangeHome - 2;
if (InRange(ControlMaster.Location, RangeHome))
{
return;
}
public override bool BardImmune => true;
public override Poison PoisonImmune => Poison.Lethal;
public override bool Commandable => false;
public override bool IgnoreMobiles => true;
var master = ControlMaster;
public override bool PlayerRangeSensitive => false;
var m_Loc = Point3D.Zero;
public virtual void RangeCheck()
if (Map != master.Map)
{
if (Deleted || ControlMaster?.Deleted != false)
{
return;
}
var range = RangeHome - 2;
if (InRange(ControlMaster.Location, RangeHome))
{
return;
}
var master = ControlMaster;
var m_Loc = Point3D.Zero;
if (Map != master.Map)
{
return;
}
var x = X > master.X ? master.X + range : master.X - range;
var y = Y > master.Y ? master.Y + range : master.Y - range;
for (var i = 0; i < 10; i++)
{
m_Loc.X = x + Utility.RandomMinMax(-1, 1);
m_Loc.Y = y + Utility.RandomMinMax(-1, 1);
m_Loc.Z = Map.GetAverageZ(m_Loc.X, m_Loc.Y);
if (Map.CanSpawnMobile(m_Loc))
{
break;
}
m_Loc = master.Location;
}
if (!Deleted)
{
SetLocation(m_Loc, true);
}
return;
}
public override void OnThink()
var x = X > master.X ? master.X + range : master.X - range;
var y = Y > master.Y ? master.Y + range : master.Y - range;
for (var i = 0; i < 10; i++)
{
var master = ControlMaster;
m_Loc.X = x + Utility.RandomMinMax(-1, 1);
m_Loc.Y = y + Utility.RandomMinMax(-1, 1);
if (Deleted)
m_Loc.Z = Map.GetAverageZ(m_Loc.X, m_Loc.Y);
if (Map.CanSpawnMobile(m_Loc))
{
return;
break;
}
if (master?.Deleted != false)
{
DropPackContents();
EndRelease(null);
return;
}
RangeCheck();
if (m_LastHidden != master.Hidden)
{
Hidden = m_LastHidden = master.Hidden;
}
if (AIObject?.WalkMobileRange(master, 5, true, 1, 1) == true)
{
Warmode = master.Warmode;
Combatant = master.Combatant;
CurrentSpeed = 0.10;
}
else
{
Warmode = false;
FocusMob = Combatant = null;
CurrentSpeed = 0.01;
}
m_Loc = master.Location;
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
if (!Deleted)
{
base.GetContextMenuEntries(from, list);
SetLocation(m_Loc, true);
}
}
if (from.Alive && Controlled && from == ControlMaster && from.InRange(this, 14))
{
list.Add(new ReleaseEntry(from, this));
}
public override void OnThink()
{
var master = ControlMaster;
if (Deleted)
{
return;
}
public virtual void BeginRelease(Mobile from)
{
if (!Deleted && Controlled && from == ControlMaster && from.CheckAlive())
{
EndRelease(from);
}
}
public virtual void EndRelease(Mobile from)
{
if (from?.CheckAlive() != false && !Deleted && Controlled && from == ControlMaster)
{
Effects.SendLocationParticles(
EffectItem.Create(Location, Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
2100,
3,
5042,
0
);
PlaySound(0x201);
Delete();
}
}
public virtual void DropPackContents()
{
var map = Map;
var pack = Backpack;
if (map != null && map != Map.Internal && pack != null)
{
var list = new List<Item>(pack.Items);
for (var i = 0; i < list.Count; ++i)
{
list[i].MoveToWorld(Location, map);
}
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
ValidationQueue<BaseFamiliar>.Add(this);
}
public void Validate()
if (master?.Deleted != false)
{
DropPackContents();
Delete();
EndRelease(null);
return;
}
private class ReleaseEntry : ContextMenuEntry
RangeCheck();
if (m_LastHidden != master.Hidden)
{
private readonly BaseFamiliar m_Familiar;
private readonly Mobile m_From;
Hidden = m_LastHidden = master.Hidden;
}
public ReleaseEntry(Mobile from, BaseFamiliar familiar) : base(6118, 14)
if (AIObject?.WalkMobileRange(master, 5, true, 1, 1) == true)
{
Warmode = master.Warmode;
Combatant = master.Combatant;
CurrentSpeed = 0.10;
}
else
{
Warmode = false;
FocusMob = Combatant = null;
CurrentSpeed = 0.01;
}
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (from.Alive && Controlled && from == ControlMaster && from.InRange(this, 14))
{
list.Add(new ReleaseEntry(from, this));
}
}
public virtual void BeginRelease(Mobile from)
{
if (!Deleted && Controlled && from == ControlMaster && from.CheckAlive())
{
EndRelease(from);
}
}
public virtual void EndRelease(Mobile from)
{
if (from?.CheckAlive() != false && !Deleted && Controlled && from == ControlMaster)
{
Effects.SendLocationParticles(
EffectItem.Create(Location, Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
2100,
3,
5042,
0
);
PlaySound(0x201);
Delete();
}
}
public virtual void DropPackContents()
{
var map = Map;
var pack = Backpack;
if (map != null && map != Map.Internal && pack != null)
{
var list = new List<Item>(pack.Items);
for (var i = 0; i < list.Count; ++i)
{
m_From = from;
m_Familiar = familiar;
list[i].MoveToWorld(Location, map);
}
}
}
public override void OnClick()
[AfterDeserialization(false)]
private void AfterDeserialization()
{
DropPackContents();
Delete();
}
private class ReleaseEntry : ContextMenuEntry
{
private readonly BaseFamiliar m_Familiar;
private readonly Mobile m_From;
public ReleaseEntry(Mobile from, BaseFamiliar familiar) : base(6118, 14)
{
m_From = from;
m_Familiar = familiar;
}
public override void OnClick()
{
if (!m_Familiar.Deleted && m_Familiar.Controlled && m_From == m_Familiar.ControlMaster &&
m_From.CheckAlive())
{
if (!m_Familiar.Deleted && m_Familiar.Controlled && m_From == m_Familiar.ControlMaster &&
m_From.CheckAlive())
{
m_Familiar.BeginRelease(m_From);
}
m_Familiar.BeginRelease(m_From);
}
}
}

View file

@ -1,79 +1,62 @@
using System;
using ModernUO.Serialization;
namespace Server.Mobiles
namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class DarkWolfFamiliar : BaseFamiliar
{
public class DarkWolfFamiliar : BaseFamiliar
private DateTime m_NextRestore;
public DarkWolfFamiliar()
{
private DateTime m_NextRestore;
Body = 99;
Hue = 0x901;
BaseSoundID = 0xE5;
public DarkWolfFamiliar()
SetStr(100);
SetDex(90);
SetInt(90);
SetHits(60);
SetStam(90);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 40, 50);
SetResistance(ResistanceType.Fire, 25, 40);
SetResistance(ResistanceType.Cold, 25, 40);
SetResistance(ResistanceType.Poison, 25, 40);
SetResistance(ResistanceType.Energy, 25, 40);
SetSkill(SkillName.Wrestling, 85.1, 90.0);
SetSkill(SkillName.Tactics, 50.0);
ControlSlots = 1;
}
public override string CorpseName => "a dark wolf corpse";
public override string DefaultName => "a dark wolf";
public override void OnThink()
{
base.OnThink();
if (Core.Now < m_NextRestore)
{
Body = 99;
Hue = 0x901;
BaseSoundID = 0xE5;
SetStr(100);
SetDex(90);
SetInt(90);
SetHits(60);
SetStam(90);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 40, 50);
SetResistance(ResistanceType.Fire, 25, 40);
SetResistance(ResistanceType.Cold, 25, 40);
SetResistance(ResistanceType.Poison, 25, 40);
SetResistance(ResistanceType.Energy, 25, 40);
SetSkill(SkillName.Wrestling, 85.1, 90.0);
SetSkill(SkillName.Tactics, 50.0);
ControlSlots = 1;
return;
}
public DarkWolfFamiliar(Serial serial) : base(serial)
m_NextRestore = Core.Now + TimeSpan.FromSeconds(2.0);
var caster = ControlMaster ?? SummonMaster;
if (caster != null)
{
}
public override string CorpseName => "a dark wolf corpse";
public override string DefaultName => "a dark wolf";
public override void OnThink()
{
base.OnThink();
if (Core.Now < m_NextRestore)
{
return;
}
m_NextRestore = Core.Now + TimeSpan.FromSeconds(2.0);
var caster = ControlMaster ?? SummonMaster;
if (caster != null)
{
++caster.Stam;
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
++caster.Stam;
}
}
}

View file

@ -1,56 +1,44 @@
namespace Server.Mobiles
using ModernUO.Serialization;
namespace Server.Mobiles;
[SerializationGenerator(0)]
public partial class DeathAdder : BaseFamiliar
{
public class DeathAdder : BaseFamiliar
public DeathAdder()
{
public DeathAdder()
{
Body = 0x15;
Hue = 0x455;
BaseSoundID = 219;
Body = 0x15;
Hue = 0x455;
BaseSoundID = 219;
SetStr(70);
SetDex(150);
SetInt(100);
SetStr(70);
SetDex(150);
SetInt(100);
SetHits(50);
SetStam(150);
SetMana(0);
SetHits(50);
SetStam(150);
SetMana(0);
SetDamage(1, 4);
SetDamageType(ResistanceType.Physical, 100);
SetDamage(1, 4);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 10);
SetResistance(ResistanceType.Poison, 100);
SetResistance(ResistanceType.Physical, 10);
SetResistance(ResistanceType.Poison, 100);
SetSkill(SkillName.Wrestling, 90.0);
SetSkill(SkillName.Tactics, 50.0);
SetSkill(SkillName.MagicResist, 100.0);
SetSkill(SkillName.Poisoning, 150.0);
SetSkill(SkillName.Wrestling, 90.0);
SetSkill(SkillName.Tactics, 50.0);
SetSkill(SkillName.MagicResist, 100.0);
SetSkill(SkillName.Poisoning, 150.0);
ControlSlots = 1;
}
public DeathAdder(Serial serial) : base(serial)
{
}
public override string CorpseName => "a death adder corpse";
public override string DefaultName => "a death adder";
public override Poison HitPoison => Utility.RandomDouble() < 0.8 ? Poison.Greater : Poison.Deadly;
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadEncodedInt();
}
ControlSlots = 1;
}
public DeathAdder(Serial serial) : base(serial)
{
}
public override string CorpseName => "a death adder corpse";
public override string DefaultName => "a death adder";
public override Poison HitPoison => Utility.RandomDouble() < 0.8 ? Poison.Greater : Poison.Deadly;
}

View file

@ -1,208 +1,191 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Collections;
using Server.ContextMenus;
using Server.Gumps;
using Server.Items;
namespace Server.Mobiles
namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class HordeMinionFamiliar : BaseFamiliar
{
public class HordeMinionFamiliar : BaseFamiliar
private DateTime m_NextPickup;
public HordeMinionFamiliar()
{
private DateTime m_NextPickup;
Body = 776;
BaseSoundID = 0x39D;
public HordeMinionFamiliar()
SetStr(100);
SetDex(110);
SetInt(100);
SetHits(70);
SetStam(110);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Fire, 50, 55);
SetResistance(ResistanceType.Poison, 25, 30);
SetResistance(ResistanceType.Energy, 25, 30);
SetSkill(SkillName.Wrestling, 70.1, 75.0);
SetSkill(SkillName.Tactics, 50.0);
ControlSlots = 1;
var pack = Backpack;
pack?.Delete();
pack = new Backpack();
pack.Movable = false;
pack.Weight = 13.0;
AddItem(pack);
}
public override string CorpseName => "a horde minion corpse";
public override bool DisplayWeight => true;
public override string DefaultName => "a horde minion";
public override void OnThink()
{
base.OnThink();
if (Core.Now < m_NextPickup)
{
Body = 776;
BaseSoundID = 0x39D;
SetStr(100);
SetDex(110);
SetInt(100);
SetHits(70);
SetStam(110);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Fire, 50, 55);
SetResistance(ResistanceType.Poison, 25, 30);
SetResistance(ResistanceType.Energy, 25, 30);
SetSkill(SkillName.Wrestling, 70.1, 75.0);
SetSkill(SkillName.Tactics, 50.0);
ControlSlots = 1;
var pack = Backpack;
pack?.Delete();
pack = new Backpack();
pack.Movable = false;
pack.Weight = 13.0;
AddItem(pack);
return;
}
public HordeMinionFamiliar(Serial serial) : base(serial)
m_NextPickup = Core.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10));
var pack = Backpack;
if (pack == null)
{
return;
}
public override string CorpseName => "a horde minion corpse";
public override bool DisplayWeight => true;
public override string DefaultName => "a horde minion";
public override void OnThink()
var eable = GetItemsInRange(2);
using var queue = PooledRefQueue<Item>.Create();
foreach (var item in eable)
{
base.OnThink();
if (item.Movable && item.Stackable)
{
queue.Enqueue(item);
}
}
if (Core.Now < m_NextPickup)
eable.Free();
var pickedUp = 3;
while (pickedUp > 0 && queue.Count > 0)
{
var item = queue.Dequeue();
if (!pack.CheckHold(this, item, false, true))
{
return;
}
m_NextPickup = Core.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10));
NextActionTime = Core.TickCount;
var pack = Backpack;
Lift(item, item.Amount, out var rejected, out var _);
if (pack == null)
if (rejected)
{
return;
continue;
}
var eable = GetItemsInRange(2);
using var queue = PooledRefQueue<Item>.Create();
foreach (var item in eable)
{
if (item.Movable && item.Stackable)
{
queue.Enqueue(item);
}
}
Drop(this, Point3D.Zero);
pickedUp--;
}
}
eable.Free();
private void ConfirmRelease_Callback(Mobile from, bool okay)
{
if (okay)
{
EndRelease(from);
}
}
var pickedUp = 3;
public override void BeginRelease(Mobile from)
{
if (Backpack?.Items.Count > 0)
{
from.SendGump(
new WarningGump(1060635, 30720, 1061672, 32512, 420, 280, okay => ConfirmRelease_Callback(from, okay))
);
}
else
{
EndRelease(from);
}
}
while (pickedUp > 0 && queue.Count > 0)
{
var item = queue.Dequeue();
if (!pack.CheckHold(this, item, false, true))
{
return;
}
NextActionTime = Core.TickCount;
Lift(item, item.Amount, out var rejected, out var _);
if (rejected)
{
continue;
}
Drop(this, Point3D.Zero);
pickedUp--;
}
public override bool OnBeforeDeath()
{
if (!base.OnBeforeDeath())
{
return false;
}
private void ConfirmRelease_Callback(Mobile from, bool okay)
PackAnimal.CombineBackpacks(this);
return true;
}
public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse;
public override bool IsSnoop(Mobile from)
{
if (PackAnimal.CheckAccess(this, from))
{
if (okay)
{
EndRelease(from);
}
return false;
}
public override void BeginRelease(Mobile from)
return base.IsSnoop(from);
}
public override bool OnDragDrop(Mobile from, Item item)
{
if (CheckFeed(from, item))
{
if (Backpack?.Items.Count > 0)
{
from.SendGump(
new WarningGump(1060635, 30720, 1061672, 32512, 420, 280, okay => ConfirmRelease_Callback(from, okay))
);
}
else
{
EndRelease(from);
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
public override bool OnBeforeDeath()
{
if (!base.OnBeforeDeath())
{
return false;
}
PackAnimal.CombineBackpacks(this);
return true;
}
public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse;
public override bool IsSnoop(Mobile from)
if (PackAnimal.CheckAccess(this, from))
{
if (PackAnimal.CheckAccess(this, from))
{
return false;
}
return base.IsSnoop(from);
AddToBackpack(item);
return true;
}
public override bool OnDragDrop(Mobile from, Item item)
{
if (CheckFeed(from, item))
{
return true;
}
return base.OnDragDrop(from, item);
}
if (PackAnimal.CheckAccess(this, from))
{
AddToBackpack(item);
return true;
}
public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from);
return base.OnDragDrop(from, item);
}
public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from);
public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from);
public override void OnDoubleClick(Mobile from)
{
PackAnimal.TryPackOpen(this, from);
}
public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from);
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
public override void OnDoubleClick(Mobile from)
{
PackAnimal.TryPackOpen(this, from);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
PackAnimal.GetContextMenuEntries(this, from, list);
}
PackAnimal.GetContextMenuEntries(this, from, list);
}
}

View file

@ -1,121 +1,104 @@
using System;
using ModernUO.Serialization;
using Server.Collections;
namespace Server.Mobiles
namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class ShadowWispFamiliar : BaseFamiliar
{
public class ShadowWispFamiliar : BaseFamiliar
private DateTime m_NextFlare;
public ShadowWispFamiliar()
{
private DateTime m_NextFlare;
Body = 165;
Hue = 0x901;
BaseSoundID = 466;
public ShadowWispFamiliar()
SetStr(50);
SetDex(60);
SetInt(100);
SetHits(50);
SetStam(60);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Energy, 100);
SetResistance(ResistanceType.Physical, 10, 15);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Cold, 10, 15);
SetResistance(ResistanceType.Poison, 10, 15);
SetResistance(ResistanceType.Energy, 99);
SetSkill(SkillName.Wrestling, 40.0);
SetSkill(SkillName.Tactics, 40.0);
ControlSlots = 1;
}
public override string CorpseName => "a shadow wisp corpse";
public override string DefaultName => "a shadow wisp";
public override void OnThink()
{
base.OnThink();
if (Core.Now < m_NextFlare)
{
Body = 165;
Hue = 0x901;
BaseSoundID = 466;
SetStr(50);
SetDex(60);
SetInt(100);
SetHits(50);
SetStam(60);
SetMana(0);
SetDamage(5, 10);
SetDamageType(ResistanceType.Energy, 100);
SetResistance(ResistanceType.Physical, 10, 15);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Cold, 10, 15);
SetResistance(ResistanceType.Poison, 10, 15);
SetResistance(ResistanceType.Energy, 99);
SetSkill(SkillName.Wrestling, 40.0);
SetSkill(SkillName.Tactics, 40.0);
ControlSlots = 1;
return;
}
public ShadowWispFamiliar(Serial serial) : base(serial)
m_NextFlare = Core.Now + TimeSpan.FromSeconds(5.0 + 25.0 * Utility.RandomDouble());
FixedEffect(0x37C4, 1, 12, 1109, 6);
PlaySound(0x1D3);
Timer.StartTimer(TimeSpan.FromSeconds(0.5), Flare);
}
private void Flare()
{
var caster = ControlMaster ?? SummonMaster;
if (caster == null)
{
return;
}
public override string CorpseName => "a shadow wisp corpse";
public override string DefaultName => "a shadow wisp";
public override void OnThink()
var eable = GetMobilesInRange(5);
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var m in eable)
{
base.OnThink();
if (Core.Now < m_NextFlare)
if (m.Player && m.Alive && !m.IsDeadBondedPet && m.Karma <= 0 && m.AccessLevel < AccessLevel.Counselor)
{
return;
}
m_NextFlare = Core.Now + TimeSpan.FromSeconds(5.0 + 25.0 * Utility.RandomDouble());
FixedEffect(0x37C4, 1, 12, 1109, 6);
PlaySound(0x1D3);
Timer.StartTimer(TimeSpan.FromSeconds(0.5), Flare);
}
private void Flare()
{
var caster = ControlMaster ?? SummonMaster;
if (caster == null)
{
return;
}
var eable = GetMobilesInRange(5);
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var m in eable)
{
if (m.Player && m.Alive && !m.IsDeadBondedPet && m.Karma <= 0 && m.AccessLevel < AccessLevel.Counselor)
{
queue.Enqueue(m);
}
}
eable.Free();
while (queue.Count > 0)
{
var m = queue.Dequeue();
var friendly = true;
for (var j = 0; friendly && j < caster.Aggressors.Count; ++j)
{
friendly = caster.Aggressors[j].Attacker != m;
}
for (var j = 0; friendly && j < caster.Aggressed.Count; ++j)
{
friendly = caster.Aggressed[j].Defender != m;
}
if (friendly)
{
m.FixedEffect(0x37C4, 1, 12, 1109, 3); // At player
m.Mana += 1 - m.Karma / 1000;
}
queue.Enqueue(m);
}
}
eable.Free();
public override void Serialize(IGenericWriter writer)
while (queue.Count > 0)
{
base.Serialize(writer);
var m = queue.Dequeue();
var friendly = true;
writer.Write(0);
}
for (var j = 0; friendly && j < caster.Aggressors.Count; ++j)
{
friendly = caster.Aggressors[j].Attacker != m;
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
for (var j = 0; friendly && j < caster.Aggressed.Count; ++j)
{
friendly = caster.Aggressed[j].Defender != m;
}
var version = reader.ReadInt();
if (friendly)
{
m.FixedEffect(0x37C4, 1, 12, 1109, 3); // At player
m.Mana += 1 - m.Karma / 1000;
}
}
}
}

View file

@ -1,55 +1,39 @@
namespace Server.Mobiles
using ModernUO.Serialization;
namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class VampireBatFamiliar : BaseFamiliar
{
public class VampireBatFamiliar : BaseFamiliar
public VampireBatFamiliar()
{
public VampireBatFamiliar()
{
Body = 317;
BaseSoundID = 0x270;
Body = 317;
BaseSoundID = 0x270;
SetStr(120);
SetDex(120);
SetInt(100);
SetStr(120);
SetDex(120);
SetInt(100);
SetHits(90);
SetStam(120);
SetMana(0);
SetHits(90);
SetStam(120);
SetMana(0);
SetDamage(5, 10);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 10, 15);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Cold, 10, 15);
SetResistance(ResistanceType.Poison, 10, 15);
SetResistance(ResistanceType.Energy, 10, 15);
SetResistance(ResistanceType.Physical, 10, 15);
SetResistance(ResistanceType.Fire, 10, 15);
SetResistance(ResistanceType.Cold, 10, 15);
SetResistance(ResistanceType.Poison, 10, 15);
SetResistance(ResistanceType.Energy, 10, 15);
SetSkill(SkillName.Wrestling, 95.1, 100.0);
SetSkill(SkillName.Tactics, 50.0);
SetSkill(SkillName.Wrestling, 95.1, 100.0);
SetSkill(SkillName.Tactics, 50.0);
ControlSlots = 1;
}
public VampireBatFamiliar(Serial serial) : base(serial)
{
}
public override string CorpseName => "a vampire bat corpse";
public override string DefaultName => "a vampire bat";
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
ControlSlots = 1;
}
public override string CorpseName => "a vampire bat corpse";
public override string DefaultName => "a vampire bat";
}

View file

@ -257,20 +257,15 @@ namespace Server.Mobiles
{
}
[AfterDeserialization]
[AfterDeserialization(false)]
private void AfterDeserialize()
{
if (_morphedInto != null)
{
ValidationQueue<Changeling>.Add(this);
Revert();
}
}
public void Validate()
{
Revert();
}
[SerializationGenerator(0, false)]
public partial class ClonedItem : Item
{