feat: Adds Mobile.Murderer virtual property, consolidates kill-threshold checks (#2355)

## Summary

- Adds `public virtual bool Murderer => Kills >= 5` property to `Mobile`, replacing ~30 scattered `Kills >= 5` / `Kills < 5` magic-number checks across the codebase
- `BaseCreature` overrides `Murderer` to also return `true` when `AlwaysMurderer` is set
- Updates `Corpse` serialization to v15, storing `_murderer` as a `bool` field (migrated from `int Kills >= 5` in earlier versions)
This commit is contained in:
Jack 2026-03-07 05:36:41 +13:00 committed by GitHub
parent 192f092ee7
commit 6745cf2075
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 200 additions and 43 deletions

View file

@ -2192,7 +2192,7 @@ public partial class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropert
return DeathMoveResult.MoveToBackpack; return DeathMoveResult.MoveToBackpack;
} }
if (CheckNewbied() && parent.Kills < 5) if (CheckNewbied() && !parent.Murderer)
{ {
return DeathMoveResult.MoveToBackpack; return DeathMoveResult.MoveToBackpack;
} }
@ -2222,7 +2222,7 @@ public partial class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropert
return DeathMoveResult.MoveToBackpack; return DeathMoveResult.MoveToBackpack;
} }
if (CheckNewbied() && parent.Kills < 5) if (CheckNewbied() && !parent.Murderer)
{ {
return DeathMoveResult.MoveToBackpack; return DeathMoveResult.MoveToBackpack;
} }

View file

@ -1642,7 +1642,7 @@ public partial class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPro
{ {
m_Kills = Math.Max(value, 0); m_Kills = Math.Max(value, 0);
if (oldValue >= 5 != m_Kills >= 5) if (oldValue >= 5 != Murderer)
{ {
Delta(MobileDelta.Noto); Delta(MobileDelta.Noto);
InvalidateProperties(); InvalidateProperties();
@ -1653,6 +1653,8 @@ public partial class Mobile : IHued, IComparable<Mobile>, ISpawnable, IObjectPro
} }
} }
public virtual bool Murderer => Kills >= 5;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public virtual bool Criminal public virtual bool Criminal
{ {

View file

@ -454,7 +454,7 @@ public partial class ChampionSpawn : Item
// Justice reward // Justice reward
var pm = (PlayerMobile)killer; var pm = (PlayerMobile)killer;
var prot = JusticeVirtue.GetProtector(pm); var prot = JusticeVirtue.GetProtector(pm);
if (prot == null || prot.Map != killer.Map || prot.Kills >= 5 || prot.Criminal || if (prot == null || prot.Map != killer.Map || prot.Murderer || prot.Criminal ||
!JusticeVirtue.CheckMapRegion(killer, prot)) !JusticeVirtue.CheckMapRegion(killer, prot))
{ {
return; return;

View file

@ -42,7 +42,7 @@ namespace Server.Engines.ConPVP
{ {
var mob = players[j]; var mob = players[j];
if (mob.Kills >= 5) if (mob.Murderer)
{ {
parts[0].Players.Add(mob); parts[0].Players.Add(mob);
} }

View file

@ -31,7 +31,7 @@ public sealed partial class HeroEthic : Ethic
} }
} }
public override bool IsEligible(Mobile mob) => mob.Kills < 5 && Faction.Find(mob) is TrueBritannians or CouncilOfMages; public override bool IsEligible(Mobile mob) => !mob.Murderer && Faction.Find(mob) is TrueBritannians or CouncilOfMages;
[AfterDeserialization] [AfterDeserialization]
private void AfterDeserialization() private void AfterDeserialization()

View file

@ -307,7 +307,7 @@ public sealed class HelpGump : DynamicGump
} }
else if (from is PlayerMobile mobile && mobile.CanUseStuckMenu() && else if (from is PlayerMobile mobile && mobile.CanUseStuckMenu() &&
mobile.Region.CanUseStuckMenu(mobile) && !CheckCombat(mobile) && !mobile.Frozen && mobile.Region.CanUseStuckMenu(mobile) && !CheckCombat(mobile) && !mobile.Frozen &&
!mobile.Criminal && (Core.AOS || mobile.Kills < 5)) !mobile.Criminal && (Core.AOS || !mobile.Murderer))
{ {
var menu = new StuckMenu(mobile, mobile, true); var menu = new StuckMenu(mobile, mobile, true);

View file

@ -300,7 +300,7 @@ namespace Server.Menus.Questions
} }
else else
{ {
destMap = m_Mobile.Kills >= 5 ? Map.Felucca : Map.Trammel; destMap = m_Mobile.Murderer ? Map.Felucca : Map.Trammel;
} }
BaseCreature.TeleportPets(m_Mobile, dest, destMap); BaseCreature.TeleportPets(m_Mobile, dest, destMap);

View file

@ -179,7 +179,7 @@ public class JusticeVirtue
{ {
protector.SendLocalizedMessage(1049372); // You cannot use this ability here. protector.SendLocalizedMessage(1049372); // You cannot use this ability here.
} }
else if (pm == protector || pm.Criminal || pm.Kills >= 5) else if (pm == protector || pm.Criminal || pm.Murderer)
{ {
protector.SendLocalizedMessage(1049436); // That player cannot be protected. protector.SendLocalizedMessage(1049436); // That player cannot be protected.
} }
@ -219,7 +219,7 @@ public class JusticeVirtue
{ {
protector.SendLocalizedMessage(1049372); // You cannot use this ability here. protector.SendLocalizedMessage(1049372); // You cannot use this ability here.
} }
else if (protectee == protector || protectee.Criminal || protectee.Kills >= 5) else if (protectee == protector || protectee.Criminal || protectee.Murderer)
{ {
protector.SendLocalizedMessage(1049436); // That player cannot be protected. protector.SendLocalizedMessage(1049436); // That player cannot be protected.
} }

View file

@ -30,7 +30,7 @@ public class VirtueGump : Gump
public static void RequestVirtueGump(PlayerMobile beholder, PlayerMobile beheld) public static void RequestVirtueGump(PlayerMobile beholder, PlayerMobile beheld)
{ {
if (beholder == beheld && beholder.Kills >= 5) if (beholder == beheld && beholder.Murderer)
{ {
beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue.
} }
@ -49,7 +49,7 @@ public class VirtueGump : Gump
beholder.CloseGump<VirtueGump>(); beholder.CloseGump<VirtueGump>();
if (beholder.Kills >= 5) if (beholder.Murderer)
{ {
beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue.
return; return;

View file

@ -1419,7 +1419,7 @@ namespace Server.Gumps
} }
default: default:
{ {
if (m.Kills >= 5) if (m.Murderer)
{ {
return 0x21; return 0x21;
} }

View file

@ -196,7 +196,7 @@ public class WhoGump : DynamicGump
AccessLevel.Seer => 0x144, AccessLevel.Seer => 0x144,
AccessLevel.GameMaster => 0x21, AccessLevel.GameMaster => 0x21,
AccessLevel.Counselor => 0x2, AccessLevel.Counselor => 0x2,
_ when m.Kills >= 5 => 0x21, _ when m.Murderer => 0x21,
_ when m.Criminal => 0x3B1, _ when m.Criminal => 0x3B1,
_ => 0x58 _ => 0x58
}; };

View file

@ -64,7 +64,7 @@ public enum CorpseFlag
SelfLooted = 0x00000080 SelfLooted = 0x00000080
} }
[SerializationGenerator(14, false)] [SerializationGenerator(15, false)]
public partial class Corpse : Container, ICarvable public partial class Corpse : Container, ICarvable
{ {
public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes(2.0); public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes(2.0);
@ -126,7 +126,7 @@ public partial class Corpse : Container, ICarvable
[SerializableField(12)] [SerializableField(12)]
[SerializedCommandProperty(AccessLevel.GameMaster)] [SerializedCommandProperty(AccessLevel.GameMaster)]
private int _kills; private bool _murderer;
[SerializableField(13, setter: "private")] [SerializableField(13, setter: "private")]
[SerializedCommandProperty(AccessLevel.GameMaster)] [SerializedCommandProperty(AccessLevel.GameMaster)]
@ -170,7 +170,7 @@ public partial class Corpse : Container, ICarvable
_accessLevel = owner.AccessLevel; _accessLevel = owner.AccessLevel;
_guild = owner.Guild as Guild; _guild = owner.Guild as Guild;
_kills = owner.Kills; _murderer = owner.Murderer;
SetFlag(CorpseFlag.Criminal, owner.Criminal); SetFlag(CorpseFlag.Criminal, owner.Criminal);
if (hair?.ItemId > 0) if (hair?.ItemId > 0)
@ -254,6 +254,28 @@ public partial class Corpse : Container, ICarvable
DevourCorpse(); DevourCorpse();
} }
// Replaced int Kills snapshot with bool Murderer snapshot
private void MigrateFrom(V14Content content)
{
_restoreEquip = content.RestoreEquip;
_flags = content.Flags;
_timeOfDeath = content.TimeOfDeath;
_restoreTable = content.RestoreTable;
_decayTimer = new InternalTimer(this, content.DecayTimerDelay);
_decayTimer.Start();
_looters = content.Looters;
_killer = content.Killer;
_aggressors = content.Aggressors;
_owner = content.Owner;
_corpseName = content.CorpseName;
_accessLevel = content.AccessLevel;
_guild = content.Guild;
_murderer = content.Kills >= 5;
_equipItems = content.EquipItems;
_hair = content.Hair;
_facialHair = content.FacialHair;
}
// Added corpse hair and corpse facial hair // Added corpse hair and corpse facial hair
private void MigrateFrom(V13Content content) private void MigrateFrom(V13Content content)
{ {
@ -270,7 +292,7 @@ public partial class Corpse : Container, ICarvable
_corpseName = content.CorpseName; _corpseName = content.CorpseName;
_accessLevel = content.AccessLevel; _accessLevel = content.AccessLevel;
_guild = content.Guild; _guild = content.Guild;
_kills = content.Kills; _murderer = content.Kills >= 5;
_equipItems = content.EquipItems; _equipItems = content.EquipItems;
} }
@ -631,7 +653,7 @@ public partial class Corpse : Container, ICarvable
_accessLevel = (AccessLevel)reader.ReadInt(); _accessLevel = (AccessLevel)reader.ReadInt();
reader.ReadInt(); // guild reserve reader.ReadInt(); // guild reserve
_kills = reader.ReadInt(); _murderer = reader.ReadInt() >= 5;
_equipItems = reader.ReadEntityList<Item>(); _equipItems = reader.ReadEntityList<Item>();
} }

View file

@ -64,7 +64,7 @@ public partial class Moonstone : Item
{ {
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
} }
else if (from.Kills >= 5) else if (from.Murderer)
{ {
// The magic of the stone cannot be evoked by someone with blood on their hands. // The magic of the stone cannot be evoked by someone with blood on their hands.
from.SendLocalizedMessage(1005402); from.SendLocalizedMessage(1005402);

View file

@ -25,7 +25,7 @@ public partial class MoonstoneGate : Moongate
public override void CheckGate(Mobile m, int range) public override void CheckGate(Mobile m, int range)
{ {
if (m.Kills >= 5) if (m.Murderer)
{ {
return; return;
} }
@ -41,7 +41,7 @@ public partial class MoonstoneGate : Moongate
public override void UseGate(Mobile m) public override void UseGate(Mobile m)
{ {
if (m.Kills >= 5) if (m.Murderer)
{ {
return; return;
} }

View file

@ -339,7 +339,7 @@ public class MoongateGump : Gump
{ {
checkLists = PMList.SigilLists; checkLists = PMList.SigilLists;
} }
else if (mobile.Kills >= 5) else if (mobile.Murderer)
{ {
checkLists = PMList.RedLists; checkLists = PMList.RedLists;
} }
@ -474,7 +474,7 @@ public class MoongateGump : Gump
{ {
_mobile.SendLocalizedMessage(1019002); // You are too far away to use the gate. _mobile.SendLocalizedMessage(1019002); // You are too far away to use the gate.
} }
else if (_mobile.Player && _mobile.Kills >= 5 && list.Map != Map.Felucca) else if (_mobile.Player && _mobile.Murderer && list.Map != Map.Felucca)
{ {
_mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there. _mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there.
} }

View file

@ -96,7 +96,7 @@ public partial class Moongate : Item
{ {
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
} }
else if (m.Kills >= 5 && TargetMap != Map.Felucca || else if (m.Murderer && TargetMap != Map.Felucca ||
TargetMap == Map.Tokuno && (flags & ClientFlags.Tokuno) == 0 || TargetMap == Map.Tokuno && (flags & ClientFlags.Tokuno) == 0 ||
TargetMap == Map.Malas && (flags & ClientFlags.Malas) == 0 || TargetMap == Map.Malas && (flags & ClientFlags.Malas) == 0 ||
TargetMap == Map.Ilshenar && (flags & ClientFlags.Ilshenar) == 0 || TargetMap == Map.Ilshenar && (flags & ClientFlags.Ilshenar) == 0 ||

View file

@ -226,7 +226,7 @@ public partial class BraceletOfBinding : BaseBracelet, TranslocationItem
return false; return false;
} }
if (from.Kills >= 5 && boundRoot.Map != Map.Felucca) if (from.Murderer && boundRoot.Map != Map.Felucca)
{ {
from.SendLocalizedMessage(1019004); // You are not allowed to travel there. from.SendLocalizedMessage(1019004); // You are not allowed to travel there.
return false; return false;

View file

@ -0,0 +1,131 @@
{
"version": 15,
"type": "Server.Items.Corpse",
"properties": [
{
"name": "RestoreEquip",
"type": "System.Collections.Generic.List\u003CServer.Item\u003E",
"rule": "ListMigrationRule",
"ruleArguments": [
"Server.Item",
"SerializableInterfaceMigrationRule"
]
},
{
"name": "Flags",
"type": "Server.Items.CorpseFlag",
"rule": "EnumMigrationRule"
},
{
"name": "TimeOfDeath",
"type": "System.DateTime",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
"DeltaTime"
]
},
{
"name": "RestoreTable",
"type": "System.Collections.Generic.Dictionary\u003CServer.Item, Server.Point3D\u003E",
"rule": "DictionaryMigrationRule",
"ruleArguments": [
"Server.Item",
"SerializableInterfaceMigrationRule",
"0",
"Server.Point3D",
"PrimitiveUOTypeMigrationRule",
"1",
"Point3D"
]
},
{
"name": "DecayTimer",
"type": "Server.Timer",
"rule": "TimerMigrationRule",
"ruleArguments": [
"@TimerDrift"
]
},
{
"name": "Looters",
"type": "System.Collections.Generic.HashSet\u003CServer.Mobile\u003E",
"rule": "HashSetMigrationRule",
"ruleArguments": [
"Server.Mobile",
"SerializableInterfaceMigrationRule"
]
},
{
"name": "Killer",
"type": "Server.Mobile",
"rule": "SerializableInterfaceMigrationRule"
},
{
"name": "Aggressors",
"type": "System.Collections.Generic.List\u003CServer.Mobile\u003E",
"rule": "ListMigrationRule",
"ruleArguments": [
"Server.Mobile",
"SerializableInterfaceMigrationRule"
]
},
{
"name": "Owner",
"type": "Server.Mobile",
"rule": "SerializableInterfaceMigrationRule"
},
{
"name": "CorpseName",
"type": "string",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
},
{
"name": "AccessLevel",
"type": "Server.AccessLevel",
"rule": "EnumMigrationRule"
},
{
"name": "Guild",
"type": "Server.Guilds.Guild",
"rule": "SerializableInterfaceMigrationRule"
},
{
"name": "Murderer",
"type": "bool",
"rule": "PrimitiveTypeMigrationRule",
"ruleArguments": [
""
]
},
{
"name": "EquipItems",
"type": "System.Collections.Generic.List\u003CServer.Item\u003E",
"rule": "ListMigrationRule",
"ruleArguments": [
"Server.Item",
"SerializableInterfaceMigrationRule"
]
},
{
"name": "Hair",
"type": "Server.VirtualHairInfo",
"rule": "RawSerializableMigrationRule",
"ruleArguments": [
"",
"@CanBeNull"
]
},
{
"name": "FacialHair",
"type": "Server.VirtualHairInfo",
"rule": "RawSerializableMigrationRule",
"ruleArguments": [
"",
"@CanBeNull"
]
}
]
}

View file

@ -311,7 +311,7 @@ namespace Server.Misc
var actual = Notoriety.CanBeAttacked; var actual = Notoriety.CanBeAttacked;
if (target.Kills >= 5 || body.IsMonster && IsSummoned(creature) || creature.AlwaysMurderer || if (target.Murderer || body.IsMonster && IsSummoned(creature) ||
creature.IsAnimatedDead) creature.IsAnimatedDead)
{ {
actual = Notoriety.Murderer; actual = Notoriety.Murderer;
@ -335,7 +335,7 @@ namespace Server.Misc
return Notoriety.Innocent; return Notoriety.Innocent;
} }
if (target.Kills >= 5 || body.IsMonster) if (target.Murderer || body.IsMonster)
{ {
return Notoriety.Murderer; return Notoriety.Murderer;
} }
@ -438,7 +438,7 @@ namespace Server.Misc
} }
} }
if (target.Kills >= 5 || if (target.Murderer ||
target.Body.IsMonster && IsSummoned(bcTarg) && target is not BaseFamiliar && target is not ArcaneFey && target.Body.IsMonster && IsSummoned(bcTarg) && target is not BaseFamiliar && target is not ArcaneFey &&
target is not Golem || bcTarg?.IsAnimatedDead == true) target is not Golem || bcTarg?.IsAnimatedDead == true)
{ {

View file

@ -557,6 +557,8 @@ namespace Server.Mobiles
public virtual bool AlwaysMurderer => false; public virtual bool AlwaysMurderer => false;
public override bool Murderer => AlwaysMurderer || base.Murderer;
public virtual bool AlwaysAttackable => false; public virtual bool AlwaysAttackable => false;
[CommandProperty(AccessLevel.GameMaster)] [CommandProperty(AccessLevel.GameMaster)]
@ -2806,7 +2808,7 @@ namespace Server.Mobiles
return; return;
} }
if (!Body.IsHuman || Kills >= 5 || AlwaysMurderer || AlwaysAttackable || m.Kills < 5 || if (!Body.IsHuman || Murderer || AlwaysAttackable || !m.Murderer ||
!m.InRange(Location, 12) || !m.Alive) !m.InRange(Location, 12) || !m.Alive)
{ {
return; return;

View file

@ -48,7 +48,7 @@ public partial class Healer : BaseHealer
return false; return false;
} }
if (m.Kills >= 5) if (m.Murderer)
{ {
Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee.
return false; return false;

View file

@ -40,7 +40,7 @@ public partial class WanderingHealer : BaseHealer
return false; return false;
} }
if (m.Kills >= 5) if (m.Murderer)
{ {
Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee.
return false; return false;

View file

@ -70,7 +70,7 @@ namespace Server.Mobiles
InLOS(from)) InLOS(from))
{ {
m_NextResurrect = Core.Now + ResurrectDelay; m_NextResurrect = Core.Now + ResurrectDelay;
if (!from.Criminal && from.Kills < 5 && from.Karma > 0) if (!from.Criminal && !from.Murderer && from.Karma > 0)
{ {
if (from.Map?.CanFit(from.Location, 16, false, false) == true) if (from.Map?.CanFit(from.Location, 16, false, false) == true)
{ {

View file

@ -2595,7 +2595,7 @@ namespace Server.Mobiles
} }
} }
if (Kills >= 5 && Core.Now >= m_NextJustAward) if (Murderer && Core.Now >= m_NextJustAward)
{ {
var m = FindMostRecentDamager(false); var m = FindMostRecentDamager(false);

View file

@ -165,7 +165,7 @@ public abstract partial class BaseChampion : BaseCreature
var prot = JusticeVirtue.GetProtector(pm); var prot = JusticeVirtue.GetProtector(pm);
if (prot == null || prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || if (prot == null || prot.Map != pm.Map || prot.Murderer || prot.Criminal ||
!JusticeVirtue.CheckMapRegion(pm, prot)) !JusticeVirtue.CheckMapRegion(pm, prot))
{ {
return; return;

View file

@ -279,7 +279,7 @@ public partial class Harrower : BaseCreature
var prot = JusticeVirtue.GetProtector(pm); var prot = JusticeVirtue.GetProtector(pm);
if (prot == null || prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || if (prot == null || prot.Map != pm.Map || prot.Murderer || prot.Criminal ||
!JusticeVirtue.CheckMapRegion(pm, prot)) !JusticeVirtue.CheckMapRegion(pm, prot))
{ {
continue; continue;

View file

@ -135,7 +135,7 @@ public class GuardedRegion : BaseRegion
} }
public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) => public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) =>
from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || from.Kills < 5; from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || !from.Murderer;
public override bool OnBeginSpellCast(Mobile m, ISpell s) public override bool OnBeginSpellCast(Mobile m, ISpell s)
{ {
@ -171,7 +171,7 @@ public class GuardedRegion : BaseRegion
return; return;
} }
if (!AllowReds && (m.Kills >= 5 || m is BaseCreature { AlwaysMurderer: true })) if (!AllowReds && m.Murderer)
{ {
CheckGuardCandidate(m); CheckGuardCandidate(m);
} }
@ -334,7 +334,7 @@ public class GuardedRegion : BaseRegion
return false; return false;
} }
return !AllowReds && (m.Kills >= 5 || bc?.AlwaysMurderer == true) || m.Criminal; return !AllowReds && m.Murderer || m.Criminal;
} }
private class GuardTimer : Timer private class GuardTimer : Timer

View file

@ -502,7 +502,7 @@ namespace Server.Spells
} }
return bcTarg?.Controlled == false && bcTarg.InitialInnocent || return bcTarg?.Controlled == false && bcTarg.InitialInnocent ||
Notoriety.Compute(from, to) != Notoriety.Innocent || from.Kills >= 5; Notoriety.Compute(from, to) != Notoriety.Innocent || from.Murderer;
} }
public static void Summon( public static void Summon(

View file

@ -60,7 +60,7 @@ namespace Server.Spells.Chivalry
{ {
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
} }
else if (Caster.Kills >= 5 && map != Map.Felucca) else if (Caster.Murderer && map != Map.Felucca)
{ {
Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there.
} }

View file

@ -60,7 +60,7 @@ namespace Server.Spells.Fourth
{ {
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
} }
else if (Caster.Kills >= 5 && map != Map.Felucca) else if (Caster.Murderer && map != Map.Felucca)
{ {
Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there.
} }

View file

@ -52,7 +52,7 @@ public class GateTravelSpell : MagerySpell, IRecallSpell
{ {
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
} }
else if (Caster.Kills >= 5 && map != Map.Felucca) else if (Caster.Murderer && map != Map.Felucca)
{ {
Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there.
} }