ModernUO/Projects/Scripts/Misc/Notoriety.cs
Kamron Batman 179cb50557 Updates Packets & Randomizer (#43)
* Fixes a bug with the main loop. Removes unnecessary optimizations for RDRand.

* WIP - Rewriting packets.

* Cleanup and updates README

* Converts more packets

* Fixes header

* Converts Effects packets.

* Forgot the send command

* Adds the start of containers packets.

* Adds message packets with caching

* Extends the send methods

* Starts to add Acquire methods

* Converted the packets

* Cleanup

* Cleanup

* Adds more packets

* Adds more packets

* Fixes clearing arrays from pool. Adds Mobile Incoming

* Converts more packets.

* Moves more packets

* Moves more packets

* Test compression

* Merges

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

* Optimize the stack alloc. Changes attributes

* Converted container packets

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

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

* Fixes packets and changes how compression is configured

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

* Fix file

* Fixes formatting

* Changed SpanWriter to be more idiomatic.

* Fixes Span vs RawSpan and missing stackallocs

* Converts over some more gumps

* WIP - Deletes 32bit support.

* Drops RDRand32 support.

* Fixes gump compilation

* Converting gump components

* Removes old huffman compression function

* Revert signature for backwards compatibility

* WIP - Converting more gump components

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

* Converts the maining gump components

* Cleans up gump components

* Cleans up directives

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

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

* Removed OPL Packet

* World packets

* Fixing packet uses

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

* More cleanup for packets

* Code cleanup

* Converts more packet uses and cleans up more code

* More code cleanup

* Finishes fixing the packets in Item

* Updates secure trade packets

* Updates core and gets it to compile.

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

* Code cleanup

* Updates chat packets

* Code cleanuo

* Adds party packets, but need to implement them.

* Party packets WIP

* Finishes party packets

* Rearrange movement namespaces and classes

* Finishes plant packets

* Code Formatting

* Fixes moving effects

* Code cleanup, eliminates equipinfo

* Adds more packets. Fixes bugs with various packets.

* Finishes mahjon packets

* Fixes mahjong packet

* Code cleanup

* Finishes mahjong packets

* Adds Map packets

* Add multifacet maps and charts

* Cleans up some packets with UTF8

* Optimizes packets

* Cleans up more packets. Moves the MessageHelper

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

* Updates protocol extensions packet receiver

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

* Code cleanup and fixing more packets

* Fixes packet effects

* Cleaned up more code

* Buff Icon cleanup

* Removed unused constructors

* Code Cleanup. Adds BoatHS Packets

* Moves house files. Updates house foundation packets.

* Deployment cleanup

* Fixes:

* Code cleanup

* More code cleanup

* More code cleanup

* Cleaned up BaseHouse

* Enforces styling

* Converts foreach to linq where possible.

* Dont need that

* Goals/Readme updates

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

* Code cleanup. Fixes extended features packet.

* Fixes various bugs

* Code cleanup

* Code cleanup

* Code cleanup. Fixes gump X/Y assignment.

* Code cleanup using |= operator

* More code cleanup

* Cleanup

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

* Compiler error

* Fixes NPE from RunUO 2.7

* Renames ScriptCompiler to AssemblyHandler. Fixes packets. Updates README

* Fixes more packets. Stupid trailing nulls.

* Fixes various bugs.

* Fixes for gumps

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

* Recoded the gump writing

* WIP

* *Added output path of scripts project to dev branch
*Activated debugging in code
2019-11-11 12:40:16 +01:00

447 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Server.Engines.ConPVP;
using Server.Engines.PartySystem;
using Server.Factions;
using Server.Guilds;
using Server.Items;
using Server.Mobiles;
using Server.Multis;
using Server.SkillHandlers;
using Server.Spells.Seventh;
namespace Server.Misc
{
public static class NotorietyHandlers
{
public static void Initialize()
{
Notoriety.Hues[Notoriety.Innocent] = 0x59;
Notoriety.Hues[Notoriety.Ally] = 0x3F;
Notoriety.Hues[Notoriety.CanBeAttacked] = 0x3B2;
Notoriety.Hues[Notoriety.Criminal] = 0x3B2;
Notoriety.Hues[Notoriety.Enemy] = 0x90;
Notoriety.Hues[Notoriety.Murderer] = 0x22;
Notoriety.Hues[Notoriety.Invulnerable] = 0x35;
Notoriety.Handler = MobileNotoriety;
Mobile.AllowBeneficialHandler = Mobile_AllowBeneficial;
Mobile.AllowHarmfulHandler = Mobile_AllowHarmful;
}
private static GuildStatus GetGuildStatus(Mobile m)
{
if (m.Guild == null)
return GuildStatus.None;
if (((Guild)m.Guild).Enemies.Count == 0 && m.Guild.Type == GuildType.Regular)
return GuildStatus.Peaceful;
return GuildStatus.Waring;
}
private static bool CheckBeneficialStatus(GuildStatus from, GuildStatus target)
{
if (from == GuildStatus.Waring || target == GuildStatus.Waring)
return false;
return true;
}
/*private static bool CheckHarmfulStatus( GuildStatus from, GuildStatus target )
{
if ( from == GuildStatus.Waring && target == GuildStatus.Waring )
return true;
return false;
}*/
public static bool Mobile_AllowBeneficial(Mobile from, Mobile target)
{
if (from == null || target == null || from.AccessLevel > AccessLevel.Player ||
target.AccessLevel > AccessLevel.Player)
return true;
#region Dueling
PlayerMobile pmFrom = from as PlayerMobile;
PlayerMobile pmTarg = target as PlayerMobile;
if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned)
pmFrom = bcFrom.SummonMaster as PlayerMobile;
if (pmTarg == null && target is BaseCreature bcTarg && bcTarg.Summoned)
pmTarg = bcTarg.SummonMaster as PlayerMobile;
if (pmFrom != null && pmTarg != null)
{
if (pmFrom.DuelContext != pmTarg.DuelContext &&
(pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true))
return false;
if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext &&
(pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started || pmFrom.DuelContext.Tied ||
pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated))
return false;
if (pmFrom.DuelPlayer?.Eliminated == false && pmFrom.DuelContext?.IsSuddenDeath == true)
return false;
if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext &&
pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true &&
pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null &&
pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant)
return false;
if (pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext)
return true;
}
if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true)
return false;
if (from.Region.IsPartOf<SafeZone>() || target.Region.IsPartOf<SafeZone>())
return false;
#endregion
Map map = from.Map;
#region Factions
Faction targetFaction = Faction.Find(target, true);
if ((!Core.ML || map == Faction.Facet) && targetFaction != null)
if (Faction.Find(from, true) != targetFaction)
return false;
#endregion
if ((map?.Rules & MapRules.BeneficialRestrictions) == 0)
return true; // In felucca, anything goes
if (!from.Player)
return true; // NPCs have no restrictions
if (target is BaseCreature creature && !creature.Controlled)
return false; // Players cannot heal uncontrolled mobiles
if (pmFrom?.Young == true || pmTarg?.Young == true)
return false; // Young players cannot perform beneficial actions towards older players
if (from.Guild is Guild fromGuild && target.Guild is Guild targetGuild &&
(targetGuild == fromGuild || fromGuild.IsAlly(targetGuild)))
return true; // Guild members can be beneficial
return CheckBeneficialStatus(GetGuildStatus(from), GetGuildStatus(target));
}
public static bool Mobile_AllowHarmful(Mobile from, Mobile target)
{
if (from == null || target == null || from.AccessLevel > AccessLevel.Player ||
target.AccessLevel > AccessLevel.Player)
return true;
#region Dueling
PlayerMobile pmFrom = from as PlayerMobile;
PlayerMobile pmTarg = target as PlayerMobile;
BaseCreature bcTarg = target as BaseCreature;
if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned)
pmFrom = bcFrom.SummonMaster as PlayerMobile;
if (pmTarg == null && bcTarg?.Summoned == true)
pmTarg = bcTarg.SummonMaster as PlayerMobile;
if (pmFrom != null && pmTarg != null)
{
if (pmFrom.DuelContext != pmTarg.DuelContext &&
(pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true))
return false;
if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext &&
(pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started || pmFrom.DuelContext.Tied ||
pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated))
return false;
if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext &&
pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true &&
pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null &&
pmFrom.DuelPlayer.Participant == pmTarg.DuelPlayer.Participant)
return false;
if ( pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext)
return true;
}
if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true)
return false;
if (from.Region.IsPartOf<SafeZone>() || target.Region.IsPartOf<SafeZone>())
return false;
#endregion
Map map = from.Map;
if ((map?.Rules & MapRules.HarmfulRestrictions) == 0)
return true; // In felucca, anything goes
if (!from.Player && !(from is BaseCreature bc && bc.GetMaster() != null &&
bc.GetMaster().AccessLevel == AccessLevel.Player))
{
if (!CheckAggressor(from.Aggressors, target) && !CheckAggressed(from.Aggressed, target) &&
pmTarg?.CheckYoungProtection(from) == true)
return false;
return true; // Uncontrolled NPCs are only restricted by the young system
}
Guild fromGuild = GetGuildFor(from.Guild as Guild, from);
Guild targetGuild = GetGuildFor(target.Guild as Guild, target);
if (fromGuild != null && targetGuild != null &&
(fromGuild == targetGuild || fromGuild.IsAlly(targetGuild) || fromGuild.IsEnemy(targetGuild)))
return true; // Guild allies or enemies can be harmful
if (bcTarg?.Controlled == true || bcTarg?.Summoned == true && bcTarg?.SummonMaster != from)
return false; // Cannot harm other controlled mobiles
if (target.Player)
return false; // Cannot harm other players
return bcTarg?.InitialInnocent == true || Notoriety.Compute(from, target) != Notoriety.Innocent;
}
public static Guild GetGuildFor(Guild def, Mobile m)
{
Guild g = def;
if (m is BaseCreature c && c.Controlled && c.ControlMaster != null)
{
c.DisplayGuildTitle = false;
if (c.Map != Map.Internal && (Core.AOS || Guild.NewGuildSystem || c.ControlOrder == OrderType.Attack ||
c.ControlOrder == OrderType.Guard))
g = (Guild)(c.Guild = c.ControlMaster.Guild);
else if (c.Map == Map.Internal || c.ControlMaster.Guild == null)
g = (Guild)(c.Guild = null);
}
return g;
}
public static int CorpseNotoriety(Mobile source, Corpse target)
{
if (target.AccessLevel > AccessLevel.Player)
return Notoriety.CanBeAttacked;
Body body = target.Amount;
Guild sourceGuild = GetGuildFor(source.Guild as Guild, source);
Guild targetGuild = GetGuildFor(target.Guild, target.Owner);
Faction srcFaction = Faction.Find(source, true, true);
Faction trgFaction = Faction.Find(target.Owner, true, true);
List<Mobile> list = target.Aggressors;
if (sourceGuild != null && targetGuild != null)
{
if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild))
return Notoriety.Ally;
if (sourceGuild.IsEnemy(targetGuild))
return Notoriety.Enemy;
}
if (target.Owner is BaseCreature creature)
{
if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet)
return Notoriety.Enemy;
if (CheckHouseFlag(source, creature, target.Location, target.Map))
return Notoriety.CanBeAttacked;
int actual = Notoriety.CanBeAttacked;
if (target.Kills >= 5 || body.IsMonster && IsSummoned(creature) || creature.AlwaysMurderer ||
creature.IsAnimatedDead)
actual = Notoriety.Murderer;
if (DateTime.UtcNow >= target.TimeOfDeath + Corpse.MonsterLootRightSacrifice)
return actual;
Party sourceParty = Party.Get(source);
for (int i = 0; i < list.Count; ++i)
if (list[i] == source || sourceParty != null && Party.Get(list[i]) == sourceParty)
return actual;
return Notoriety.Innocent;
}
if (target.Kills >= 5 || body.IsMonster)
return Notoriety.Murderer;
if (target.Criminal && target.Map != null && (target.Map.Rules & MapRules.HarmfulRestrictions) == 0)
return Notoriety.Criminal;
if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet)
for (int i = 0; i < list.Count; ++i)
if (list[i] == source || list[i] is BaseFactionGuard)
return Notoriety.Enemy;
if (CheckHouseFlag(source, target.Owner, target.Location, target.Map))
return Notoriety.CanBeAttacked;
if (!(target.Owner is PlayerMobile))
return Notoriety.CanBeAttacked;
for (int i = 0; i < list.Count; ++i)
if (list[i] == source)
return Notoriety.CanBeAttacked;
return Notoriety.Innocent;
}
/* Must be thread-safe */
public static byte MobileNotoriety(Mobile source, Mobile target)
{
BaseCreature bcTarg = target as BaseCreature;
if (Core.AOS && (target.Blessed || bcTarg?.IsInvulnerable == true || target is PlayerVendor ||
target is TownCrier))
return Notoriety.Invulnerable;
PlayerMobile pmFrom = source as PlayerMobile;
PlayerMobile pmTarg = target as PlayerMobile;
#region Dueling
if (pmFrom != null && pmTarg != null)
if (pmFrom.DuelContext?.StartedBeginCountdown == true && !pmFrom.DuelContext.Finished && pmFrom.DuelContext == pmTarg.DuelContext)
return pmFrom.DuelContext.IsAlly(pmFrom, pmTarg) ? Notoriety.Ally : Notoriety.Enemy;
#endregion
if (target.AccessLevel > AccessLevel.Player)
return Notoriety.CanBeAttacked;
if (source.Player && !target.Player && pmFrom != null && bcTarg != null)
{
Mobile master = bcTarg.GetMaster();
if (master?.AccessLevel > AccessLevel.Player)
return Notoriety.CanBeAttacked;
master = bcTarg.ControlMaster;
if (Core.ML && master != null)
{
if (source == master && CheckAggressor(bcTarg.Aggressors, source) ||
CheckAggressor(source.Aggressors, bcTarg))
return Notoriety.CanBeAttacked;
return MobileNotoriety(source, master);
}
if (!bcTarg.Summoned && !bcTarg.Controlled && pmFrom.EnemyOfOneType == bcTarg.GetType())
return Notoriety.Enemy;
}
if (target.Kills >= 5 ||
target.Body.IsMonster && IsSummoned(bcTarg) && !(target is BaseFamiliar) && !(target is ArcaneFey) &&
!(target is Golem) || bcTarg?.AlwaysMurderer == true || bcTarg?.IsAnimatedDead == true)
return Notoriety.Murderer;
if (target.Criminal)
return Notoriety.Criminal;
Guild sourceGuild = GetGuildFor(source.Guild as Guild, source);
Guild targetGuild = GetGuildFor(target.Guild as Guild, target);
if (sourceGuild != null && targetGuild != null)
{
if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild))
return Notoriety.Ally;
if (sourceGuild.IsEnemy(targetGuild))
return Notoriety.Enemy;
}
Faction srcFaction = Faction.Find(source, true, true);
Faction trgFaction = Faction.Find(target, true, true);
if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet)
return Notoriety.Enemy;
if (Stealing.ClassicMode && pmTarg?.PermaFlags.Contains(source) == true)
return Notoriety.CanBeAttacked;
if (bcTarg?.AlwaysAttackable == true)
return Notoriety.CanBeAttacked;
if (CheckHouseFlag(source, target, target.Location, target.Map))
return Notoriety.CanBeAttacked;
if (bcTarg?.InitialInnocent != true)
if (!target.Body.IsHuman && !target.Body.IsGhost && !IsPet(bcTarg) && pmTarg == null ||
!Core.ML && !target.CanBeginAction<PolymorphSpell>())
return Notoriety.CanBeAttacked;
if (CheckAggressor(source.Aggressors, target))
return Notoriety.CanBeAttacked;
if (CheckAggressed(source.Aggressed, target))
return Notoriety.CanBeAttacked;
if (bcTarg?.Controlled == true && bcTarg.ControlOrder == OrderType.Guard &&
bcTarg.ControlTarget == source)
return Notoriety.CanBeAttacked;
if (source is BaseCreature bc)
{
Mobile master = bc.GetMaster();
if (master != null && CheckAggressor(master.Aggressors, target) ||
MobileNotoriety(master, target) == Notoriety.CanBeAttacked || bcTarg != null)
return Notoriety.CanBeAttacked;
}
return Notoriety.Innocent;
}
public static bool CheckHouseFlag(Mobile from, Mobile m, Point3D p, Map map)
{
BaseHouse house = BaseHouse.FindHouseAt(p, map, 16);
if (house?.Public != false || !house.IsFriend(from))
return false;
if (m != null && house.IsFriend(m))
return false;
return !(m is BaseCreature c) || c.Deleted || !c.Controlled || c.ControlMaster == null ||
!house.IsFriend(c.ControlMaster);
}
public static bool IsPet(BaseCreature c) => c?.Controlled == true;
public static bool IsSummoned(BaseCreature c) => c?.Summoned == true;
public static bool IsSummoned(BaseCreature c) => c?.Summoned == true;
public static bool CheckAggressor(IEnumerable<AggressorInfo> list, Mobile target) => list.Any(t => t.Attacker == target);
public static bool CheckAggressed(IEnumerable<AggressorInfo> list, Mobile target) =>
list.Any(info => !info.CriminalAggression && info.Defender == target);
private enum GuildStatus
{
None,
Peaceful,
Waring
}
}
}