fix: Fixes buffs don't start/stop properly. Streamlines constructor and Add/Remove buffs. (#2082)

This commit is contained in:
mark1145 2025-01-25 13:20:23 +11:00 committed by GitHub
parent c8f13b2933
commit d5160bd6db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 651 additions and 616 deletions

View file

@ -1,5 +1,6 @@
using System;
using Server;
using Server.Engines.BuffIcons;
using Server.Network;
using Server.Tests;
using Server.Tests.Network;
@ -14,29 +15,29 @@ public class BuffIconPacketTests
[InlineData(0x2048u, BuffIcon.Disguised, 500102, 300203, null, 9000)]
public void TestAddBuffIcon(uint mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, string args, int ts)
{
var timeSpan = new TimeSpan(ts);
var expected = new AddBuffPacket(
(Serial)mob, iconID, titleCliloc, secondaryCliloc, args, timeSpan
).Compile();
var timeSpan = new TimeSpan(ts);
var expected = new AddBuffPacket(
(Serial)mob, iconID, titleCliloc, secondaryCliloc, args, timeSpan
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendAddBuffPacket((Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendAddBuffPacket((Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}
[Fact]
public void TestRemoveBuffIcon()
{
Serial m = (Serial)0x1024;
var buffIcon = BuffIcon.Disguised;
var expected = new RemoveBuffPacket(m, buffIcon).Compile();
Serial m = (Serial)0x1024;
var buffIcon = BuffIcon.Disguised;
var expected = new RemoveBuffPacket(m, buffIcon).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRemoveBuffPacket(m, buffIcon);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRemoveBuffPacket(m, buffIcon);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using Server.Engines.BuffIcons;
namespace Server.Network
{
@ -11,9 +12,7 @@ namespace Server.Network
info.TitleCliloc,
info.SecondaryCliloc,
info.Args,
info.TimeStart != 0 ?
TimeSpan.FromMilliseconds(info.TimeStart + (long)info.TimeLength.TotalMilliseconds - Core.TickCount) :
TimeSpan.Zero
info.Duration
)
{
}

View file

@ -0,0 +1,192 @@
namespace Server.Engines.BuffIcons;
public enum BuffIcon : short
{
DismountPrevention = 0x3E9,
NoRearm = 0x3EA,
//Currently, no 0x3EB or 0x3EC
NightSight = 0x3ED, //*
DeathStrike,
EvilOmen,
HonoredDebuff,
AchievePerfection,
DivineFury, //*
EnemyOfOne, //*
HidingAndOrStealth, //*
ActiveMeditation, //*
BloodOathCaster, //*
BloodOathCurse, //*
CorpseSkin, //*
Mindrot, //*
PainSpike, //*
Strangle,
GiftOfRenewal, //*
AttuneWeapon, //*
Thunderstorm, //*
EssenceOfWind, //*
EtherealVoyage, //*
GiftOfLife, //*
ArcaneEmpowerment, //*
MortalStrike,
ReactiveArmor, //*
Protection, //*
ArchProtection,
MagicReflection, //*
Incognito, //*
Disguised,
AnimalForm,
Polymorph,
Invisibility, //*
Paralyze, //*
Poison,
Bleed,
Clumsy, //*
FeebleMind, //*
Weaken, //*
Curse, //*
MassCurse,
Agility, //*
Cunning, //*
Strength, //*
Bless, //*
Sleep,
StoneForm,
SpellPlague,
Berserk,
MassSleep,
Fly,
Inspire,
Invigorate,
Resilience,
Perseverance,
TribulationTarget,
DespairTarget,
FishPie = 0x426,
HitLowerAttack,
HitLowerDefense,
DualWield,
Block,
DefenseMastery,
DespairCaster,
Healing,
SpellFocusingBuff,
SpellFocusingDebuff,
RageFocusingDebuff,
RageFocusingBuff,
Warding,
TribulationCaster,
ForceArrow,
Disarm,
Surge,
Feint,
TalonStrike,
PsychicAttack,
ConsecrateWeapon,
GrapesOfWrath,
EnemyOfOneDebuff,
HorrificBeast,
LichForm,
VampiricEmbrace,
CurseWeapon,
ReaperForm,
ImmolatingWeapon,
Enchant,
HonorableExecution,
Confidence,
Evasion,
CounterAttack,
LightningStrike,
MomentumStrike,
OrangePetals,
RoseOfTrinsic,
PoisonImmunity,
Veterinary,
Perfection,
Honored,
ManaPhase,
FanDancerFanFire,
Rage,
Webbing,
MedusaStone,
TrueFear,
AuraOfNausea,
HowlOfCacophony,
GazeDespair,
HiryuPhysicalResistance,
RuneBeetleCorruption,
BloodwormAnemia,
RotwormBloodDisease,
SkillUseDelay,
FactionStatLoss,
HeatOfBattleStatus,
CriminalStatus,
ArmorPierce,
SplinteringEffect,
SwingSpeedDebuff,
WraithForm,
CityTradeDeal = 0x466,
HumilityDebuff = 0x467,
Spirituality,
Humility,
// Skill Masteries
Rampage,
Stagger, // Debuff
Toughness,
Thrust,
Pierce, // Debuff
PlayingTheOdds,
FocusedEye,
Onslaught, // Debuff
ElementalFury,
ElementalFuryDebuff, // Debuff
CalledShot,
Knockout,
SavingThrow,
Conduit,
EtherealBurst,
MysticWeapon,
ManaShield,
AnticipateHit,
Warcry,
Shadow,
WhiteTigerForm,
Bodyguard,
HeightenedSenses,
Tolerance,
DeathRay,
DeathRayDebuff,
Intuition,
EnchantedSummoning,
ShieldBash,
Whispering,
CombatTraining,
InjectedStrikeDebuff,
InjectedStrike,
UnknownTomato,
PlayingTheOddsDebuff,
DragonTurtleDebuff,
Boarding,
Potency,
ThrustDebuff,
FistsOfFury, // 1169
BarrabHemolymphConcentrate,
JukariBurnPoiltice,
KurakAmbushersEssence,
BarakoDraftOfMight,
UraliTranceTonic,
SakkhraProphylaxis, // 1175
Sparks,
Swarm,
BoneBreaker,
Unknown2,
SwarmImmune,
BoneBreakerImmune,
UnknownGoblin,
UnknownRedDrop,
UnknownStar,
FeintDebuff,
CaddelliteInfused,
PotionGloriousFortune,
MysticalPolymorphTotem,
UnknownDebuff,
}

View file

@ -1,6 +1,7 @@
using System.Buffers;
using Server.Network;
namespace Server.Network;
namespace Server.Engines.BuffIcons;
public static class BuffIconPackets
{

View file

@ -0,0 +1,66 @@
using System;
using ModernUO.CodeGeneratedEvents;
using Server.Mobiles;
namespace Server.Engines.BuffIcons;
public class BuffInfo
{
private TimerExecutionToken _timerToken;
public BuffInfo(
BuffIcon iconID, int titleCliloc, TimeSpan duration = default, TextDefinition args = null,
bool retainThroughDeath = false
) : this(iconID, titleCliloc, titleCliloc + 1, duration, args, retainThroughDeath)
{
}
public BuffInfo(
BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan duration = default, TextDefinition args = null,
bool retainThroughDeath = false
)
{
ID = iconID;
TitleCliloc = titleCliloc;
SecondaryCliloc = secondaryCliloc;
Duration = duration;
Args = args;
RetainThroughDeath = retainThroughDeath;
}
public static bool Enabled { get; private set; }
public BuffIcon ID { get; }
public int TitleCliloc { get; }
public int SecondaryCliloc { get; }
public DateTime StartTime { get; private set; }
public TimeSpan Duration { get; }
public bool RetainThroughDeath { get; }
public TextDefinition Args { get; }
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("buffIcons.enable", Core.ML);
}
public void StartTimer(PlayerMobile m)
{
if (Duration != TimeSpan.Zero)
{
StartTime = Core.Now;
var id = ID;
Timer.StartTimer(Duration, () => m.RemoveBuff(id), out _timerToken);
}
}
public void StopTimer()
{
_timerToken.Cancel();
}
}

View file

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Items;
@ -57,8 +59,11 @@ public partial class InvisibilityPotion : BasePotion
m.Hidden = true;
BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825)); // Invisibility/Invisible
if (m is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.HidingAndOrStealth);
pm.AddBuff(new BuffInfo(BuffIcon.Invisibility, 1075825)); // Invisibility/Invisible
}
RemoveTimer(m);

View file

@ -1,5 +1,6 @@
using System;
using ModernUO.Serialization;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Spells.Fifth;
using Server.Spells.First;
@ -973,126 +974,140 @@ public partial class BaseTalisman : Item, IAosItem
switch (m_Talisman.Removal)
{
case TalismanRemoval.Curse:
target.PlaySound(0xF6);
target.PlaySound(0x1F7);
target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
IEntity mfrom = new Entity(
Serial.Zero,
new Point3D(target.X, target.Y, target.Z - 10),
from.Map
);
IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map);
Effects.SendMovingParticles(
mfrom,
mto,
0x2255,
1,
0,
false,
false,
13,
3,
9501,
1,
0,
EffectLayer.Head,
0x100
);
var mod = target.GetStatMod("[Magic] Str Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Str Curse");
target.PlaySound(0xF6);
target.PlaySound(0x1F7);
target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
IEntity mfrom = new Entity(
Serial.Zero,
new Point3D(target.X, target.Y, target.Z - 10),
from.Map
);
IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map);
Effects.SendMovingParticles(
mfrom,
mto,
0x2255,
1,
0,
false,
false,
13,
3,
9501,
1,
0,
EffectLayer.Head,
0x100
);
var mod = target.GetStatMod("[Magic] Str Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Str Curse");
}
mod = target.GetStatMod("[Magic] Dex Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Dex Curse");
}
mod = target.GetStatMod("[Magic] Int Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Int Curse");
}
target.Paralyzed = false;
EvilOmenSpell.EndEffect(target);
StrangleSpell.RemoveCurse(target);
CorpseSkinSpell.RemoveCurse(target);
CurseSpell.RemoveEffect(target);
if (target is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.Clumsy);
pm.RemoveBuff(BuffIcon.FeebleMind);
pm.RemoveBuff(BuffIcon.Weaken);
pm.RemoveBuff(BuffIcon.MassCurse);
}
target.SendLocalizedMessage(1072408); // Any curses on you have been lifted
if (target != from)
{
from.SendLocalizedMessage(1072409); // Your targets curses have been lifted
}
break;
}
mod = target.GetStatMod("[Magic] Dex Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Dex Curse");
}
mod = target.GetStatMod("[Magic] Int Curse");
if (mod?.Offset < 0)
{
target.RemoveStatMod("[Magic] Int Curse");
}
target.Paralyzed = false;
EvilOmenSpell.EndEffect(target);
StrangleSpell.RemoveCurse(target);
CorpseSkinSpell.RemoveCurse(target);
CurseSpell.RemoveEffect(target);
BuffInfo.RemoveBuff(target, BuffIcon.Clumsy);
BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind);
BuffInfo.RemoveBuff(target, BuffIcon.Weaken);
BuffInfo.RemoveBuff(target, BuffIcon.MassCurse);
target.SendLocalizedMessage(1072408); // Any curses on you have been lifted
if (target != from)
{
from.SendLocalizedMessage(1072409); // Your targets curses have been lifted
}
break;
case TalismanRemoval.Damage:
target.PlaySound(0x201);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
0x834,
0,
0x13B2,
0
);
BleedAttack.EndBleed(target, true);
MortalStrike.EndWound(target);
BuffInfo.RemoveBuff(target, BuffIcon.Bleed);
BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike);
target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed!
if (target != from)
{
from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed!
}
target.PlaySound(0x201);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
0x834,
0,
0x13B2,
0
);
break;
BleedAttack.EndBleed(target, true);
MortalStrike.EndWound(target);
if (target is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.Bleed);
pm.RemoveBuff(BuffIcon.MortalStrike);
}
target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed!
if (target != from)
{
from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed!
}
break;
}
case TalismanRemoval.Ward:
target.PlaySound(0x201);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
0x834,
0,
0x13B2,
0
);
MagicReflectSpell.EndReflect(target);
ReactiveArmorSpell.EndArmor(target);
ProtectionSpell.EndProtection(target);
target.SendLocalizedMessage(1072402); // Your wards have been removed!
if (target != from)
{
from.SendLocalizedMessage(1072403); // Your target's wards have been removed!
}
target.PlaySound(0x201);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
0x3728,
1,
13,
0x834,
0,
0x13B2,
0
);
break;
MagicReflectSpell.EndReflect(target);
ReactiveArmorSpell.EndArmor(target);
ProtectionSpell.EndProtection(target);
target.SendLocalizedMessage(1072402); // Your wards have been removed!
if (target != from)
{
from.SendLocalizedMessage(1072403); // Your target's wards have been removed!
}
break;
}
case TalismanRemoval.Wildfire:
// TODO
break;
{
// TODO
break;
}
}
m_Talisman.OnAfterUse(from);

View file

@ -1,4 +1,6 @@
using System;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Items
{
@ -69,7 +71,7 @@ namespace Server.Items
pack.DropItem(toDisarm);
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.NoRearm, 1075637, BlockEquipDuration, defender));
(defender as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.NoRearm, 1075637, BlockEquipDuration));
BaseWeapon.BlockEquip(defender, BlockEquipDuration);
}

View file

@ -1,6 +1,8 @@
using Server.Spells;
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Items
{
@ -38,8 +40,9 @@ namespace Server.Items
{
info.Timer.IncreaseExpiration();
BuffInfo.RemoveBuff(defender, BuffIcon.ForceArrow);
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, info.DefenseChanceMalus.ToString()));
(defender as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, args: info.DefenseChanceMalus.ToString())
);
}
if (defender.Spell is Spell spell && spell.IsCasting)
@ -64,7 +67,9 @@ namespace Server.Items
_table.Add(attacker, new List<ForceArrowInfo> { info });
}
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, info.DefenseChanceMalus.ToString()));
(defender as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, args: info.DefenseChanceMalus.ToString())
);
}
public static void EndForceArrow(ForceArrowInfo info)
@ -81,7 +86,7 @@ namespace Server.Items
_table.Remove(attacker);
}
BuffInfo.RemoveBuff(info.Defender, BuffIcon.ForceArrow);
(info.Defender as PlayerMobile)?.RemoveBuff(BuffIcon.ForceArrow);
}
public static bool HasForceArrow(Mobile attacker, Mobile defender)

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Items
{
@ -38,10 +40,14 @@ namespace Server.Items
Registry.Add(defender, timer);
}
BuffInfo.RemoveBuff(defender, BuffIcon.PsychicAttack);
string args = $"{timer.SpellDamageMalus}\t{timer.ManaCostMalus}";
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.PsychicAttack, 1151296, 1151297, args));
(defender as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.PsychicAttack,
1151296,
1151297,
args: $"{timer.SpellDamageMalus}\t{timer.ManaCostMalus}"
)
);
}
public static void RemoveEffects(Mobile defender)
@ -51,7 +57,7 @@ namespace Server.Items
return;
}
BuffInfo.RemoveBuff(defender, BuffIcon.PsychicAttack);
(defender as PlayerMobile)?.RemoveBuff(BuffIcon.PsychicAttack);
Registry.Remove(defender);

View file

@ -1,335 +0,0 @@
using System;
using ModernUO.CodeGeneratedEvents;
using Server.Mobiles;
using Server.Network;
namespace Server
{
public class BuffInfo
{
private TimerExecutionToken _timerToken;
public BuffInfo(BuffIcon iconID, int titleCliloc) : this(iconID, titleCliloc, titleCliloc + 1)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc)
{
ID = iconID;
TitleCliloc = titleCliloc;
SecondaryCliloc = secondaryCliloc;
}
public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m)
: this(iconID, titleCliloc, titleCliloc + 1, length, m)
{
}
// Only the timed one needs the Mobile to know when to automagically remove it.
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m)
: this(iconID, titleCliloc, secondaryCliloc)
{
TimeLength = length;
TimeStart = Core.TickCount;
Timer.StartTimer(length, () => RemoveBuff(m, this), out _timerToken);
}
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args)
: this(iconID, titleCliloc, titleCliloc + 1, args)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args)
: this(iconID, titleCliloc, secondaryCliloc) =>
Args = args;
public BuffInfo(BuffIcon iconID, int titleCliloc, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, retainThroughDeath)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, bool retainThroughDeath)
: this(iconID, titleCliloc, secondaryCliloc) =>
RetainThroughDeath = retainThroughDeath;
public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args, bool retainThroughDeath)
: this(iconID, titleCliloc, titleCliloc + 1, args, retainThroughDeath)
{
}
public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, bool retainThroughDeath)
: this(iconID, titleCliloc, secondaryCliloc, args) =>
RetainThroughDeath = retainThroughDeath;
public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args)
: this(iconID, titleCliloc, titleCliloc + 1, length, m, args)
{
}
public BuffInfo(
BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m,
TextDefinition args
) : this(iconID, titleCliloc, secondaryCliloc, length, m) => Args = args;
public BuffInfo(
BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args,
bool retainThroughDeath
) : this(iconID, titleCliloc, titleCliloc + 1, length, m, args, retainThroughDeath)
{
}
public BuffInfo(
BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m,
TextDefinition args, bool retainThroughDeath
) : this(iconID, titleCliloc, secondaryCliloc, length, m)
{
Args = args;
RetainThroughDeath = retainThroughDeath;
}
public static bool Enabled { get; private set; }
public BuffIcon ID { get; }
public int TitleCliloc { get; }
public int SecondaryCliloc { get; }
public TimeSpan TimeLength { get; }
public long TimeStart { get; }
public bool RetainThroughDeath { get; }
public TextDefinition Args { get; }
public static void Configure()
{
Enabled = ServerConfiguration.GetOrUpdateSetting("buffIcons.enable", Core.ML);
}
[OnEvent(nameof(PlayerMobile.PlayerLoginEvent))]
public static void OnLogin(PlayerMobile pm)
{
if (!Enabled)
{
return;
}
pm.ResendBuffs();
}
public static void AddBuff(Mobile m, BuffInfo b)
{
(m as PlayerMobile)?.AddBuff(b);
}
public static void RemoveBuff(Mobile m, BuffInfo b)
{
if (b == null)
{
return;
}
b._timerToken.Cancel();
(m as PlayerMobile)?.RemoveBuff(b.ID);
}
public static void RemoveBuff(Mobile m, BuffIcon b)
{
(m as PlayerMobile)?.RemoveBuff(b);
}
}
public enum BuffIcon : short
{
DismountPrevention = 0x3E9,
NoRearm = 0x3EA,
//Currently, no 0x3EB or 0x3EC
NightSight = 0x3ED, //*
DeathStrike,
EvilOmen,
HonoredDebuff,
AchievePerfection,
DivineFury, //*
EnemyOfOne, //*
HidingAndOrStealth, //*
ActiveMeditation, //*
BloodOathCaster, //*
BloodOathCurse, //*
CorpseSkin, //*
Mindrot, //*
PainSpike, //*
Strangle,
GiftOfRenewal, //*
AttuneWeapon, //*
Thunderstorm, //*
EssenceOfWind, //*
EtherealVoyage, //*
GiftOfLife, //*
ArcaneEmpowerment, //*
MortalStrike,
ReactiveArmor, //*
Protection, //*
ArchProtection,
MagicReflection, //*
Incognito, //*
Disguised,
AnimalForm,
Polymorph,
Invisibility, //*
Paralyze, //*
Poison,
Bleed,
Clumsy, //*
FeebleMind, //*
Weaken, //*
Curse, //*
MassCurse,
Agility, //*
Cunning, //*
Strength, //*
Bless, //*
Sleep,
StoneForm,
SpellPlague,
Berserk,
MassSleep,
Fly,
Inspire,
Invigorate,
Resilience,
Perseverance,
TribulationTarget,
DespairTarget,
FishPie = 0x426,
HitLowerAttack,
HitLowerDefense,
DualWield,
Block,
DefenseMastery,
DespairCaster,
Healing,
SpellFocusingBuff,
SpellFocusingDebuff,
RageFocusingDebuff,
RageFocusingBuff,
Warding,
TribulationCaster,
ForceArrow,
Disarm,
Surge,
Feint,
TalonStrike,
PsychicAttack,
ConsecrateWeapon,
GrapesOfWrath,
EnemyOfOneDebuff,
HorrificBeast,
LichForm,
VampiricEmbrace,
CurseWeapon,
ReaperForm,
ImmolatingWeapon,
Enchant,
HonorableExecution,
Confidence,
Evasion,
CounterAttack,
LightningStrike,
MomentumStrike,
OrangePetals,
RoseOfTrinsic,
PoisonImmunity,
Veterinary,
Perfection,
Honored,
ManaPhase,
FanDancerFanFire,
Rage,
Webbing,
MedusaStone,
TrueFear,
AuraOfNausea,
HowlOfCacophony,
GazeDespair,
HiryuPhysicalResistance,
RuneBeetleCorruption,
BloodwormAnemia,
RotwormBloodDisease,
SkillUseDelay,
FactionStatLoss,
HeatOfBattleStatus,
CriminalStatus,
ArmorPierce,
SplinteringEffect,
SwingSpeedDebuff,
WraithForm,
CityTradeDeal = 0x466,
HumilityDebuff = 0x467,
Spirituality,
Humility,
// Skill Masteries
Rampage,
Stagger, // Debuff
Toughness,
Thrust,
Pierce, // Debuff
PlayingTheOdds,
FocusedEye,
Onslaught, // Debuff
ElementalFury,
ElementalFuryDebuff, // Debuff
CalledShot,
Knockout,
SavingThrow,
Conduit,
EtherealBurst,
MysticWeapon,
ManaShield,
AnticipateHit,
Warcry,
Shadow,
WhiteTigerForm,
Bodyguard,
HeightenedSenses,
Tolerance,
DeathRay,
DeathRayDebuff,
Intuition,
EnchantedSummoning,
ShieldBash,
Whispering,
CombatTraining,
InjectedStrikeDebuff,
InjectedStrike,
UnknownTomato,
PlayingTheOddsDebuff,
DragonTurtleDebuff,
Boarding,
Potency,
ThrustDebuff,
FistsOfFury, // 1169
BarrabHemolymphConcentrate,
JukariBurnPoiltice,
KurakAmbushersEssence,
BarakoDraftOfMight,
UraliTranceTonic,
SakkhraProphylaxis, // 1175
Sparks,
Swarm,
BoneBreaker,
Unknown2,
SwarmImmune,
BoneBreakerImmune,
UnknownGoblin,
UnknownRedDrop,
UnknownStar,
FeintDebuff,
CaddelliteInfused,
PotionGloriousFortune,
MysticalPolymorphTotem,
UnknownDebuff,
}
}

View file

@ -1,5 +1,6 @@
using System;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Items;
using Server.Mobiles;
using Server.Network;
@ -120,7 +121,7 @@ namespace Server
{
m_Owner.EndAction<LightCycle>();
m_Owner.LightLevel = 0;
BuffInfo.RemoveBuff(m_Owner, BuffIcon.NightSight);
(m_Owner as PlayerMobile)?.RemoveBuff(BuffIcon.NightSight);
}
}
}

View file

@ -4,6 +4,7 @@ using ModernUO.CodeGeneratedEvents;
using Server.Accounting;
using Server.Collections;
using Server.ContextMenus;
using Server.Engines.BuffIcons;
using Server.Engines.BulkOrders;
using Server.Engines.CannedEvil;
using Server.Engines.ConPVP;
@ -752,7 +753,7 @@ namespace Server.Mobiles
Freeze(TimeSpan.FromSeconds(1));
Animate(61, 10, 1, true, false, 0);
Flying = false;
BuffInfo.RemoveBuff(this, BuffIcon.Fly);
RemoveBuff(BuffIcon.Fly);
SendMessage("You have landed.");
BaseMount.Dismount(this);
@ -810,7 +811,7 @@ namespace Server.Mobiles
else
{
Flying = false;
BuffInfo.RemoveBuff(this, BuffIcon.Fly);
RemoveBuff(BuffIcon.Fly);
}
}
}
@ -1216,7 +1217,7 @@ namespace Server.Mobiles
if (!Meditating)
{
BuffInfo.RemoveBuff(this, BuffIcon.ActiveMeditation);
RemoveBuff(BuffIcon.ActiveMeditation);
}
}
@ -1264,6 +1265,7 @@ namespace Server.Mobiles
VirtueSystem.CheckAtrophies(from);
from.ClaimAutoStabledPets();
AnimalForm.GetContext(from)?.Timer.Start();
from.ResendBuffs();
}
private class ServerLockdownNoticeGump : StaticNoticeGump<ServerLockdownNoticeGump>
@ -1601,7 +1603,7 @@ namespace Server.Mobiles
else // if (!InvisibilitySpell.HasTimer( this ))
{
// Hidden/Stealthing & You Are Hidden
BuffInfo.AddBuff(this, new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655));
AddBuff(new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655));
}
}
@ -2548,7 +2550,7 @@ namespace Server.Mobiles
if (Flying)
{
Flying = false;
BuffInfo.RemoveBuff(this, BuffIcon.Fly);
RemoveBuff(BuffIcon.Fly);
}
if (PermaFlags.Count > 0)
@ -2635,19 +2637,19 @@ namespace Server.Mobiles
if (m_BuffTable != null)
{
using var queue = PooledRefQueue<BuffInfo>.Create();
using var queue = PooledRefQueue<BuffIcon>.Create();
foreach (var buff in m_BuffTable.Values)
{
if (!buff.RetainThroughDeath)
{
queue.Enqueue(buff);
queue.Enqueue(buff.ID);
}
}
while (queue.Count > 0)
{
BuffInfo.RemoveBuff(this, queue.Dequeue());
RemoveBuff(queue.Dequeue());
}
}
@ -4476,22 +4478,24 @@ namespace Server.Mobiles
return;
}
// Synchronize the buff icon as close to _on the second_ as we can.
var msecs = buffInfo.TimeLength.Milliseconds;
if (msecs >= 8)
var duration = Utility.Max(buffInfo.Duration - (Core.Now - buffInfo.StartTime), TimeSpan.Zero).TotalSeconds;
var rounded = Math.Round(duration);
var offset = duration - rounded;
if (offset > 0)
{
Timer.DelayCall(TimeSpan.FromMilliseconds(msecs), () =>
{
// They are still online, we still have the buff icon in the table, and it is the same buff icon
if (NetState != null && m_BuffTable?.GetValueOrDefault(buffInfo.ID) == buffInfo)
Timer.DelayCall(TimeSpan.FromSeconds(offset), () =>
{
SendAddBuffPacket(buffInfo, (long)buffInfo.TimeLength.TotalMilliseconds - msecs);
// They are still online, we still have the buff icon in the table, and it is the same buff icon
if (NetState != null && m_BuffTable?.GetValueOrDefault(buffInfo.ID) == buffInfo)
{
SendAddBuffPacket(buffInfo, (long)rounded);
}
}
});
);
}
else
else // Round up, will be removed a little bit early by the server
{
SendAddBuffPacket(buffInfo, (long)buffInfo.TimeLength.TotalMilliseconds);
SendAddBuffPacket(buffInfo, (long)rounded);
}
}
@ -4525,7 +4529,8 @@ namespace Server.Mobiles
return;
}
BuffInfo.RemoveBuff(this, b); // Check, stop old timer, & subsequently remove the old one.
RemoveBuff(b.ID); // Check, stop old timer, & subsequently remove the old one.
b.StartTimer(this);
m_BuffTable ??= new Dictionary<BuffIcon, BuffInfo>();
m_BuffTable.Add(b.ID, b);
@ -4535,11 +4540,13 @@ namespace Server.Mobiles
public void RemoveBuff(BuffIcon b)
{
if (m_BuffTable?.Remove(b) != true)
if (m_BuffTable?.Remove(b, out var buffInfo) != true)
{
return;
}
buffInfo.StopTimer();
if (NetState?.BuffIcon == true)
{
NetState.SendRemoveBuffPacket(Serial, b);

View file

@ -1,6 +1,8 @@
using System;
using Server.Engines.BuffIcons;
using Server.Items;
using Server.Misc;
using Server.Mobiles;
namespace Server.SkillHandlers
{
@ -79,7 +81,7 @@ namespace Server.SkillHandlers
m.SendLocalizedMessage(501851); // You enter a meditative trance.
m.Meditating = true;
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.ActiveMeditation, 1075657));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.ActiveMeditation, 1075657));
if (m.Player || m.Body.IsHuman)
{

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Bushido;
@ -69,13 +71,19 @@ public class Confidence : SamuraiSpell
if (Core.HS)
{
var bushido = m.Skills.Bushido.Fixed;
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Confidence, 1060596, 1153809, TimeSpan.FromSeconds(30), m,
$"{bushido / 120}\t{bushido / 50}\t{"100"}"
));
(m as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.Confidence,
1060596,
1153809,
TimeSpan.FromSeconds(30),
$"{bushido / 120}\t{bushido / 50}\t{"100"}"
)
);
}
else
{
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Confidence, 1060596, TimeSpan.FromSeconds(30), m));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Confidence, 1060596, TimeSpan.FromSeconds(30)));
}
}
@ -97,7 +105,7 @@ public class Confidence : SamuraiSpell
if (StopConfidenceTimer(m))
{
OnEffectEnd(m, typeof(Confidence));
BuffInfo.RemoveBuff(m, BuffIcon.Confidence);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.Confidence);
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Bushido;
@ -42,14 +44,12 @@ public class HonorableExecution : SamuraiMove
timer = new HonorableExecutionTimer(attacker, swingBonus);
BuffInfo.AddBuff(
attacker,
(attacker as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.HonorableExecution,
1060595,
1153807,
TimeSpan.FromSeconds(20.0),
attacker,
$"{swingBonus}"
)
);
@ -76,23 +76,20 @@ public class HonorableExecution : SamuraiMove
if (Core.HS)
{
BuffInfo.AddBuff(
attacker,
(attacker as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.HonorableExecution,
1060595,
1153808,
TimeSpan.FromSeconds(7.0),
attacker,
$"{resSpells}\t{40}\t{40}\t{40}\t{40}\t{40}"
)
);
}
else
{
BuffInfo.AddBuff(
attacker,
new BuffInfo(BuffIcon.HonorableExecution, 1060595, TimeSpan.FromSeconds(7.0), attacker)
(attacker as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.HonorableExecution, 1060595, TimeSpan.FromSeconds(7.0))
);
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Chivalry;
@ -52,24 +54,19 @@ public class DivineFurySpell : PaladinSpell
if (Core.HS) // Publish 71 with boost
{
BuffInfo.AddBuff(
Caster,
(Caster as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.DivineFury,
1060589,
1150218,
delay,
Caster,
$"{timer.AttackBonus}\t{timer.DamageBonus}\t{timer.WeaponSpeed}\t{timer.DefendMalus}"
)
);
}
else
{
BuffInfo.AddBuff(
Caster,
new BuffInfo(BuffIcon.DivineFury, 1060589, 1075634, delay, Caster)
);
(Caster as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.DivineFury, 1060589, 1075634, delay));
}
}
@ -116,7 +113,7 @@ public class DivineFurySpell : PaladinSpell
RemoveTimer(m);
m.Delta(MobileDelta.WeaponDamage);
m.PlaySound(0xF8);
BuffInfo.RemoveBuff(m, BuffIcon.DivineFury);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.DivineFury);
}
public static bool UnderEffect(Mobile m) => _table.ContainsKey(m);

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Chivalry
@ -49,9 +50,8 @@ namespace Server.Spells.Chivalry
mobile.EnemyOfOneType = null;
mobile.WaitingForEnemy = true;
BuffInfo.AddBuff(
mobile,
new BuffInfo(BuffIcon.EnemyOfOne, 1075653, 1044111, TimeSpan.FromMinutes(delay), mobile)
mobile.AddBuff(
new BuffInfo(BuffIcon.EnemyOfOne, 1075653, 1044111, TimeSpan.FromMinutes(delay))
);
}
}

View file

@ -1,5 +1,6 @@
using System;
using Server.Collections;
using Server.Engines.BuffIcons;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
@ -142,14 +143,17 @@ namespace Server.Spells.Chivalry
sendEffect = SpellPlagueSpell.RemoveEffect(m) || sendEffect;
// TODO: Move these into their respective end effect methods
BuffInfo.RemoveBuff(m, BuffIcon.Clumsy);
BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind);
BuffInfo.RemoveBuff(m, BuffIcon.Weaken);
BuffInfo.RemoveBuff(m, BuffIcon.Curse);
BuffInfo.RemoveBuff(m, BuffIcon.MassCurse);
BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike);
BuffInfo.RemoveBuff(m, BuffIcon.Strangle);
BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen);
if (m is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.Clumsy);
pm.RemoveBuff(BuffIcon.FeebleMind);
pm.RemoveBuff(BuffIcon.Weaken);
pm.RemoveBuff(BuffIcon.Curse);
pm.RemoveBuff(BuffIcon.MassCurse);
pm.RemoveBuff(BuffIcon.MortalStrike);
pm.RemoveBuff(BuffIcon.Strangle);
pm.RemoveBuff(BuffIcon.EvilOmen);
}
if (sendEffect)
{

View file

@ -1,6 +1,8 @@
using System;
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Items;
using Server.Mobiles;
using Server.Spells.Fourth;
using Server.Spells.Mysticism;
using Server.Spells.Necromancy;
@ -109,15 +111,17 @@ namespace Server.Spells.Chivalry
BloodOathSpell.RemoveCurse(m);
SpellPlagueSpell.RemoveEffect(m);
// TODO: Move these into their respective end effect methods
BuffInfo.RemoveBuff(m, BuffIcon.Clumsy);
BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind);
BuffInfo.RemoveBuff(m, BuffIcon.Weaken);
BuffInfo.RemoveBuff(m, BuffIcon.Curse);
BuffInfo.RemoveBuff(m, BuffIcon.MassCurse);
BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike);
BuffInfo.RemoveBuff(m, BuffIcon.Strangle);
BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen);
if (m is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.Clumsy);
pm.RemoveBuff(BuffIcon.FeebleMind);
pm.RemoveBuff(BuffIcon.Weaken);
pm.RemoveBuff(BuffIcon.Curse);
pm.RemoveBuff(BuffIcon.MassCurse);
pm.RemoveBuff(BuffIcon.MortalStrike);
pm.RemoveBuff(BuffIcon.Strangle);
pm.RemoveBuff(BuffIcon.EvilOmen);
}
}
else
{

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Factions;
using Server.Items;
using Server.Mobiles;
@ -114,7 +115,7 @@ namespace Server.Spells.Fifth
Timer.StartTimer(duration, () => EndIncognito(Caster), out var timerToken);
_table[Caster] = timerToken;
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Incognito, 1075819, duration, Caster));
pm?.AddBuff(new BuffInfo(BuffIcon.Incognito, 1075819, duration));
}
else
{
@ -139,7 +140,7 @@ namespace Server.Spells.Fifth
timerToken.Cancel();
}
BuffInfo.RemoveBuff(m, BuffIcon.Incognito);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.Incognito);
}
public static void EndIncognito(Mobile m)

View file

@ -1,5 +1,6 @@
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Fifth
@ -70,7 +71,7 @@ namespace Server.Spells.Fifth
Caster.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(Caster, BuffIcon.MagicReflection);
(Caster as PlayerMobile)?.RemoveBuff(BuffIcon.MagicReflection);
}
else
{
@ -98,7 +99,9 @@ namespace Server.Spells.Fifth
var buffFormat = $"{physiMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}";
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.MagicReflection, 1075817, buffFormat, true));
(Caster as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.MagicReflection, 1075817, args: buffFormat, retainThroughDeath: true)
);
}
}
}
@ -147,7 +150,7 @@ namespace Server.Spells.Fifth
m.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(m, BuffIcon.MagicReflection);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.MagicReflection);
}
}
}

View file

@ -1,3 +1,5 @@
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.First
@ -39,7 +41,7 @@ namespace Server.Spells.First
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Clumsy, 1075831, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Clumsy, 1075831, length, percentage.ToString()));
HarmfulSpell(m);
}

View file

@ -1,3 +1,5 @@
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.First
@ -41,7 +43,7 @@ namespace Server.Spells.First
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.FeebleMind, 1075833, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.FeebleMind, 1075833, length, percentage.ToString()));
HarmfulSpell(m);
}

View file

@ -1,4 +1,6 @@
using System;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.First;
@ -46,7 +48,7 @@ public class NightSightSpell : MagerySpell, ITargetingSpell<Mobile>
m.PlaySound(0x1E3);
// Night Sight/You ignore lighting effects
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.NightSight, 1075643));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.NightSight, 1075643));
}
else if (m == Caster)
{

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.First
@ -72,7 +73,7 @@ namespace Server.Spells.First
Caster.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor);
(Caster as PlayerMobile)?.RemoveBuff(BuffIcon.ReactiveArmor);
}
else
{
@ -102,7 +103,7 @@ namespace Server.Spells.First
var physresist = 15 + (int)(Caster.Skills.Inscribe.Value / 20);
var args = $"{physresist}\t{5}\t{5}\t{5}\t{5}";
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.ReactiveArmor, 1075812, 1075813, args));
(Caster as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.ReactiveArmor, 1075812, 1075813, args: args));
}
}
@ -157,7 +158,7 @@ namespace Server.Spells.First
m.RemoveResistanceMod(mods[i]);
}
BuffInfo.RemoveBuff(m, BuffIcon.ReactiveArmor);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.ReactiveArmor);
}
}
}

View file

@ -1,3 +1,5 @@
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.First
@ -39,7 +41,7 @@ namespace Server.Spells.First
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Weaken, 1075837, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Weaken, 1075837, length, percentage.ToString()));
HarmfulSpell(m);
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Fourth
@ -80,7 +82,7 @@ namespace Server.Spells.Fourth
var percentage = (int)(SpellHelper.GetOffsetScalar(caster, m, true) * 100);
var args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}";
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, duration, m, args));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Curse, 1075835, 1075836, duration, args));
return true;
}

View file

@ -1,4 +1,6 @@
using System;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells
{
@ -55,11 +57,10 @@ namespace Server.Spells
public override void OnCast()
{
Caster.Flying = false;
BuffInfo.RemoveBuff(Caster, BuffIcon.Fly);
Caster.Animate(60, 10, 1, true, false, 0);
Caster.SendLocalizedMessage(1112567); // You are flying.
Caster.Flying = true;
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Fly, 1112567));
(Caster as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Fly, 1112567));
FinishSequence();
}
}

View file

@ -4,6 +4,8 @@ using Server.Spells.Fourth;
using Server.Spells.Necromancy;
using Server.Targeting;
using Server.Collections;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Mysticism;
@ -198,15 +200,18 @@ public class CleansingWindsSpell : MysticSpell, ITargetingSpell<Mobile>
curseLevel += 2;
}
BuffInfo.RemoveBuff(m, BuffIcon.Clumsy);
BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind);
BuffInfo.RemoveBuff(m, BuffIcon.Weaken);
BuffInfo.RemoveBuff(m, BuffIcon.Curse);
BuffInfo.RemoveBuff(m, BuffIcon.MassCurse);
BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike);
BuffInfo.RemoveBuff(m, BuffIcon.CorpseSkin);
BuffInfo.RemoveBuff(m, BuffIcon.Strangle);
BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen);
if (m is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.Clumsy);
pm.RemoveBuff(BuffIcon.FeebleMind);
pm.RemoveBuff(BuffIcon.Weaken);
pm.RemoveBuff(BuffIcon.Curse);
pm.RemoveBuff(BuffIcon.MassCurse);
pm.RemoveBuff(BuffIcon.MortalStrike);
pm.RemoveBuff(BuffIcon.CorpseSkin);
pm.RemoveBuff(BuffIcon.Strangle);
pm.RemoveBuff(BuffIcon.EvilOmen);
}
return curseLevel;
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
@ -78,7 +79,7 @@ public class SpellPlagueSpell : MysticSpell, ITargetingSpell<Mobile>
if (_table.Remove(m, out var timer))
{
timer.Stop();
BuffInfo.RemoveBuff(m, BuffIcon.SpellPlague);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.SpellPlague);
return true;
}
@ -129,9 +130,8 @@ public class SpellPlagueSpell : MysticSpell, ITargetingSpell<Mobile>
public void StartPlague()
{
BuffInfo.AddBuff(
_target,
new BuffInfo(BuffIcon.SpellPlague, 1031690, 1080167, TimeSpan.FromSeconds(8.5), _target)
(_target as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.SpellPlague, 1031690, 1080167, TimeSpan.FromSeconds(8.5))
);
_nextExplosion = Core.Now + TimeSpan.FromSeconds(1);
@ -184,7 +184,7 @@ public class SpellPlagueSpell : MysticSpell, ITargetingSpell<Mobile>
else
{
_table.Remove(_target);
BuffInfo.RemoveBuff(_target, BuffIcon.SpellPlague);
(_target as PlayerMobile)?.RemoveBuff(BuffIcon.SpellPlague);
}
_next = null;

View file

@ -1,5 +1,6 @@
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Factions;
using Server.Mobiles;
using Server.Spells.Fifth;
@ -118,14 +119,12 @@ namespace Server.Spells.Mysticism
var damageBonus = (int)((GetBaseSkill(Caster) + GetDamageSkill(Caster)) / 12.0);
var resistCap = (int)((GetBaseSkill(Caster) + GetDamageSkill(Caster)) / 48.0);
BuffInfo.AddBuff(
Caster,
(Caster as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.StoneForm,
1080145,
1080146,
$"-10\t-2\t{offset}\t{resistCap}\t{damageBonus}",
false
args: $"-10\t-2\t{offset}\t{resistCap}\t{damageBonus}"
)
);
}
@ -151,7 +150,7 @@ namespace Server.Spells.Mysticism
m.BodyMod = 0;
m.HueMod = -1;
BuffInfo.RemoveBuff(m, BuffIcon.StoneForm);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.StoneForm);
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
@ -86,8 +87,8 @@ public class BloodOathSpell : NecromancerSpell, ITargetingSpell<Mobile>
var timer = new ExpireTimer(Caster, m, duration);
timer.Start();
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.BloodOathCaster, 1075659, duration, Caster, m.Name));
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.BloodOathCurse, 1075661, duration, m, Caster.Name));
(Caster as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.BloodOathCaster, 1075659, duration, m.Name));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.BloodOathCurse, 1075661, duration, Caster.Name));
_table[m] = timer;
HarmfulSpell(m);
@ -119,8 +120,8 @@ public class BloodOathSpell : NecromancerSpell, ITargetingSpell<Mobile>
timer.Stop();
BuffInfo.RemoveBuff(caster, BuffIcon.BloodOathCaster);
BuffInfo.RemoveBuff(target, BuffIcon.BloodOathCurse);
(caster as PlayerMobile)?.RemoveBuff(BuffIcon.BloodOathCaster);
(target as PlayerMobile)?.RemoveBuff(BuffIcon.BloodOathCurse);
return true;
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Necromancy;
@ -80,7 +82,7 @@ public class CorpseSkinSpell : NecromancerSpell, ITargetingSpell<Mobile>
timer = new ExpireTimer(m, mods, duration);
timer.Start();
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.CorpseSkin, 1075663, duration, m));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.CorpseSkin, 1075663, duration));
_table[m] = timer;
@ -129,7 +131,7 @@ public class CorpseSkinSpell : NecromancerSpell, ITargetingSpell<Mobile>
}
Stop();
BuffInfo.RemoveBuff(_mobile, BuffIcon.CorpseSkin);
(_mobile as PlayerMobile)?.RemoveBuff(BuffIcon.CorpseSkin);
_table.Remove(_mobile);
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
@ -64,7 +65,7 @@ public class EvilOmenSpell : NecromancerSpell, ITargetingSpell<Mobile>
HarmfulSpell(m);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EvilOmen, 1075647, 1075648, duration, m));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.EvilOmen, 1075647, 1075648, duration));
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Necromancy;
@ -72,7 +74,7 @@ public class MindRotSpell : NecromancerSpell, ITargetingSpell<Mobile>
{
timer.Stop();
m.SendLocalizedMessage(1060872); // Your mind feels normal again.
BuffInfo.RemoveBuff(m, BuffIcon.Mindrot);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.Mindrot);
return true;
}
@ -101,7 +103,7 @@ public class MindRotSpell : NecromancerSpell, ITargetingSpell<Mobile>
timer.Start();
_table[target] = timer;
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Mindrot, 1075665, duration, target));
(target as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Mindrot, 1075665, duration));
target.SendLocalizedMessage(1074384);
}
}

View file

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Misc;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Necromancy;
@ -70,7 +72,7 @@ public class PainSpikeSpell : NecromancerSpell, ITargetingSpell<Mobile>
buffTime = timer.Next - Core.Now;
}
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.PainSpike, 1075667, buffTime, m, Convert.ToString((int)damage)));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.PainSpike, 1075667, buffTime, Convert.ToString((int)damage)));
// TODO: Find a better way to do this
StaminaSystem.DFA = DFAlgorithm.PainSpike;
@ -109,7 +111,7 @@ public class PainSpikeSpell : NecromancerSpell, ITargetingSpell<Mobile>
_mobile.Hits += _toRestore;
}
BuffInfo.RemoveBuff(_mobile, BuffIcon.PainSpike);
(_mobile as PlayerMobile)?.RemoveBuff(BuffIcon.PainSpike);
}
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Necromancy;
@ -96,7 +98,7 @@ public class StrangleSpell : NecromancerSpell, ITargetingSpell<Mobile>
var maxDamage = ((int)power + 1) * 3;
var args = $"{minDamage}\t{maxDamage}";
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strangle, 1075794, 1075795, duration, m, args));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Strangle, 1075794, 1075795, duration, args));
}
}

View file

@ -1,4 +1,6 @@
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Second
@ -34,7 +36,7 @@ namespace Server.Spells.Second
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Agility, 1075841, length, percentage.ToString()));
}
}

View file

@ -1,4 +1,6 @@
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Second
@ -34,7 +36,7 @@ namespace Server.Spells.Second
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Cunning, 1075843, length, percentage.ToString()));
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Second
@ -72,7 +73,7 @@ namespace Server.Spells.Second
target.RemoveResistanceMod(mods.Item1);
target.RemoveSkillMod(mods.Item2);
BuffInfo.RemoveBuff(target, BuffIcon.Protection);
(target as PlayerMobile)?.RemoveBuff(BuffIcon.Protection);
}
else
{
@ -91,7 +92,7 @@ namespace Server.Spells.Second
target.AddSkillMod(resistMod);
var args = $"{physLoss}\t{resistLoss}";
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Protection, 1075814, 1075815, args));
(target as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Protection, 1075814, 1075815, args: args));
}
}
@ -108,7 +109,7 @@ namespace Server.Spells.Second
m.RemoveResistanceMod(mods.Item1);
m.RemoveSkillMod(mods.Item2);
BuffInfo.RemoveBuff(m, BuffIcon.Protection);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.Protection);
}
public override void OnCast()

View file

@ -1,4 +1,6 @@
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Second
@ -34,7 +36,7 @@ namespace Server.Spells.Second
var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString()));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Strength, 1075845, length, percentage.ToString()));
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Items;
using Server.Mobiles;
@ -53,8 +54,11 @@ namespace Server.Spells.Sixth
var duration = TimeSpan.FromSeconds(1.2 * Caster.Skills.Magery.Value);
BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825, duration, m)); // Invisibility/Invisible
if (m is PlayerMobile pm)
{
pm.RemoveBuff(BuffIcon.HidingAndOrStealth);
pm.AddBuff(new BuffInfo(BuffIcon.Invisibility, 1075825, duration)); // Invisibility/Invisible
}
Timer.StartTimer(duration,
() =>

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Spellweaving
{
@ -62,9 +64,8 @@ namespace Server.Spells.Spellweaving
Caster.BeginAction<AttuneWeaponSpell>();
BuffInfo.AddBuff(
Caster,
new BuffInfo(BuffIcon.AttuneWeapon, 1075798, duration, Caster, damageAbsorb.ToString())
(Caster as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.AttuneWeapon, 1075798, duration, damageAbsorb.ToString())
);
}
@ -130,7 +131,7 @@ namespace Server.Spells.Spellweaving
_table.Remove(m_Mobile);
StartTimer(TimeSpan.FromSeconds(120), m_Mobile.EndAction<AttuneWeaponSpell>);
BuffInfo.RemoveBuff(m_Mobile, BuffIcon.AttuneWeapon);
(m_Mobile as PlayerMobile)?.RemoveBuff(BuffIcon.AttuneWeapon);
}
}
}

View file

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Server.Collections;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Spellweaving
{
@ -63,9 +65,8 @@ namespace Server.Spells.Spellweaving
_table[m] = t;
BuffInfo.AddBuff(
m,
new BuffInfo(BuffIcon.EssenceOfWind, 1075802, duration, m, $"{fcMalus}\t{ssiMalus}")
(m as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.EssenceOfWind, 1075802, duration, $"{fcMalus}\t{ssiMalus}")
);
}
}
@ -110,7 +111,7 @@ namespace Server.Spells.Spellweaving
Stop();
_table.Remove(_defender);
BuffInfo.RemoveBuff(_defender, BuffIcon.EssenceOfWind);
(_defender as PlayerMobile)?.RemoveBuff(BuffIcon.EssenceOfWind);
}
}
}

View file

@ -1,4 +1,6 @@
using System;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Spellweaving
{
@ -71,7 +73,7 @@ namespace Server.Spells.Spellweaving
// Cannot cast this spell for another 5 minutes(300sec) after effect removed.
Caster.BeginAction<EtherealVoyageSpell>();
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.EtherealVoyage, 1031613, 1075805, duration, Caster));
(Caster as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.EtherealVoyage, 1031613, 1075805, duration));
}
public override void RemoveEffect(Mobile m)
@ -82,7 +84,7 @@ namespace Server.Spells.Spellweaving
Timer.StartTimer(TimeSpan.FromMinutes(5), m.EndAction<EtherealVoyageSpell>);
BuffInfo.RemoveBuff(m, BuffIcon.EtherealVoyage);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.EtherealVoyage);
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ModernUO.CodeGeneratedEvents;
using Server.Engines.BuffIcons;
using Server.Gumps;
using Server.Mobiles;
using Server.Targeting;
@ -67,7 +68,9 @@ namespace Server.Spells.Spellweaving
_table[m] = t;
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true));
(m as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, retainThroughDeath: true)
);
}
}
@ -152,7 +155,7 @@ namespace Server.Spells.Spellweaving
_mobile.SendLocalizedMessage(1074776); // You are no longer protected with Gift of Life.
_table.Remove(_mobile);
BuffInfo.RemoveBuff(_mobile, BuffIcon.GiftOfLife);
(_mobile as PlayerMobile)?.RemoveBuff(BuffIcon.GiftOfLife);
}
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Server.Engines.BuffIcons;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Spellweaving
@ -59,9 +61,14 @@ namespace Server.Spells.Spellweaving
Caster.BeginAction<GiftOfRenewalSpell>();
BuffInfo.AddBuff(
m,
new BuffInfo(BuffIcon.GiftOfRenewal, 1031602, 1075797, TimeSpan.FromSeconds(duration), m, hitsPerRound.ToString())
(m as PlayerMobile)?.AddBuff(
new BuffInfo(
BuffIcon.GiftOfRenewal,
1031602,
1075797,
TimeSpan.FromSeconds(duration),
hitsPerRound.ToString()
)
);
}
}
@ -74,7 +81,7 @@ namespace Server.Spells.Spellweaving
public static bool StopEffect(Mobile m)
{
BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.GiftOfRenewal);
if (_table.Remove(m, out var timer))
{

View file

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Server.Collections;
using Server.Engines.BuffIcons;
using Server.Mobiles;
namespace Server.Spells.Spellweaving
{
@ -72,9 +74,8 @@ namespace Server.Spells.Spellweaving
Timer.StartTimer(duration, () => DoExpire(m), out var timerToken);
_table[m] = timerToken;
BuffInfo.AddBuff(
m,
new BuffInfo(BuffIcon.Thunderstorm, 1075800, duration, m, GetCastRecoveryMalus(m))
(m as PlayerMobile)?.AddBuff(
new BuffInfo(BuffIcon.Thunderstorm, 1075800, duration, GetCastRecoveryMalus(m))
);
}
}
@ -95,7 +96,7 @@ namespace Server.Spells.Spellweaving
public static void DoExpire(Mobile m)
{
StopTimer(m);
BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm);
(m as PlayerMobile)?.RemoveBuff(BuffIcon.Thunderstorm);
}
}
}

View file

@ -1,4 +1,6 @@
using Server.Engines.BuffIcons;
using Server.Engines.ConPVP;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Third
@ -38,7 +40,7 @@ namespace Server.Spells.Third
var args = $"{percentage}\t{percentage}\t{percentage}";
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, m, args));
(m as PlayerMobile)?.AddBuff(new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, args));
}
}