feat: Adds Pre-UOTD single click support for weapons, armor, wands, and clothing (#2053)
This commit is contained in:
parent
863b4b5460
commit
3b698de556
7 changed files with 350 additions and 12 deletions
|
|
@ -18,6 +18,7 @@ using System.Collections.Generic;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server.Buffers;
|
||||
using Server.Text;
|
||||
|
||||
namespace Server;
|
||||
|
||||
|
|
@ -286,4 +287,18 @@ public static class StringHelpers
|
|||
str.CopyTo(chars);
|
||||
return chars;
|
||||
}
|
||||
|
||||
public static void AppendSpaceWithArticle(this ref ValueStringBuilder builder, string text, bool articleAn)
|
||||
{
|
||||
if (builder.Length != 0)
|
||||
{
|
||||
builder.Append(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(articleAn ? "an " : "a ");
|
||||
}
|
||||
|
||||
builder.Append(text);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Ethics;
|
||||
using Server.Factions;
|
||||
using Server.Network;
|
||||
using Server.Text;
|
||||
using AMA = Server.Items.ArmorMeditationAllowance;
|
||||
using AMT = Server.Items.ArmorMaterialType;
|
||||
|
||||
|
|
@ -559,6 +561,7 @@ namespace Server.Items
|
|||
|
||||
Resource = CraftResources.GetFromType(resourceType);
|
||||
PlayerConstructed = true;
|
||||
Identified = true;
|
||||
|
||||
var context = craftSystem.GetContext(from);
|
||||
|
||||
|
|
@ -1451,6 +1454,12 @@ namespace Server.Items
|
|||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (!Core.UOTD)
|
||||
{
|
||||
OnSingleClickPreUOTD(from);
|
||||
return;
|
||||
}
|
||||
|
||||
var attrs = new List<EquipInfoAttribute>();
|
||||
|
||||
if (DisplayLootType)
|
||||
|
|
@ -1482,13 +1491,12 @@ namespace Server.Items
|
|||
attrs.Add(new EquipInfoAttribute(1038000 + (int)_durability));
|
||||
}
|
||||
|
||||
if (_protectionLevel > ArmorProtectionLevel.Regular && _protectionLevel <= ArmorProtectionLevel.Invulnerability)
|
||||
if (_protectionLevel != ArmorProtectionLevel.Regular)
|
||||
{
|
||||
attrs.Add(new EquipInfoAttribute(1038005 + (int)_protectionLevel));
|
||||
}
|
||||
}
|
||||
else if (_durability != ArmorDurabilityLevel.Regular || _protectionLevel > ArmorProtectionLevel.Regular &&
|
||||
_protectionLevel <= ArmorProtectionLevel.Invulnerability)
|
||||
else if (_durability != ArmorDurabilityLevel.Regular || _protectionLevel != ArmorProtectionLevel.Regular)
|
||||
{
|
||||
attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified
|
||||
}
|
||||
|
|
@ -1513,6 +1521,100 @@ namespace Server.Items
|
|||
from.NetState.SendDisplayEquipmentInfo(Serial, number, _crafter, false, attrs);
|
||||
}
|
||||
|
||||
public void OnSingleClickPreUOTD(Mobile from)
|
||||
{
|
||||
var isMagicItem = _durability != ArmorDurabilityLevel.Regular ||
|
||||
_protectionLevel != ArmorProtectionLevel.Regular;
|
||||
|
||||
if (isMagicItem && !_identified)
|
||||
{
|
||||
LabelTo(from, $"an unidentified {Name ?? Localization.GetText(LabelNumber).ToLowerInvariant()}");
|
||||
return;
|
||||
}
|
||||
|
||||
var name = Name;
|
||||
var articleAnName = (TileData.ItemTable[ItemID].Flags & TileFlag.ArticleAn) != 0;
|
||||
|
||||
if (isMagicItem)
|
||||
{
|
||||
var builder = ValueStringBuilder.Create(128);
|
||||
|
||||
var durabilityText = DurabilityText(out var articleAnDurability);
|
||||
if (durabilityText != null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(durabilityText, articleAnDurability);
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(Localization.GetText(LabelNumber).ToLowerInvariant(), articleAnName);
|
||||
}
|
||||
else if (builder.Length != 0)
|
||||
{
|
||||
builder.Append($" {name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(name);
|
||||
}
|
||||
|
||||
var protectionText = ProtectionText;
|
||||
if (protectionText != null)
|
||||
{
|
||||
builder.Append($" of {protectionText}");
|
||||
}
|
||||
|
||||
LabelTo(from, builder.ToString());
|
||||
builder.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
name ??= $"{(articleAnName ? "an" : "a")} {Localization.GetText(LabelNumber).ToLowerInvariant()}";
|
||||
|
||||
if (Crafter == null)
|
||||
{
|
||||
LabelTo(from, Quality == ArmorQuality.Exceptional ? $"{name} of exceptional quality" : name);
|
||||
return;
|
||||
}
|
||||
|
||||
LabelTo(
|
||||
from,
|
||||
Quality == ArmorQuality.Exceptional
|
||||
? $"{name} crafted with exceptional quality by {Crafter}"
|
||||
: $"{name} crafted by {Crafter}"
|
||||
);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private string DurabilityText(out bool articleAn)
|
||||
{
|
||||
articleAn = _durability is ArmorDurabilityLevel.Indestructible;
|
||||
return _durability switch
|
||||
{
|
||||
ArmorDurabilityLevel.Durable => "durable",
|
||||
ArmorDurabilityLevel.Substantial => "substantial",
|
||||
ArmorDurabilityLevel.Massive => "massive",
|
||||
ArmorDurabilityLevel.Fortified => "fortified",
|
||||
ArmorDurabilityLevel.Indestructible => "indestructable",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
private string ProtectionText
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get =>
|
||||
_protectionLevel switch
|
||||
{
|
||||
ArmorProtectionLevel.Defense => "defense",
|
||||
ArmorProtectionLevel.Guarding => "guarding",
|
||||
ArmorProtectionLevel.Hardening => "hardening",
|
||||
ArmorProtectionLevel.Fortification => "fortification",
|
||||
ArmorProtectionLevel.Invulnerability => "invulnerability",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum OldSaveFlag
|
||||
{
|
||||
|
|
|
|||
|
|
@ -907,8 +907,13 @@ namespace Server.Items
|
|||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
var attrs = new List<EquipInfoAttribute>();
|
||||
if (!Core.UOTD)
|
||||
{
|
||||
OnSingleClickPreUOTD(from);
|
||||
return;
|
||||
}
|
||||
|
||||
var attrs = new List<EquipInfoAttribute>();
|
||||
AddEquipInfoAttributes(from, attrs);
|
||||
|
||||
int number;
|
||||
|
|
@ -931,6 +936,30 @@ namespace Server.Items
|
|||
from.NetState.SendDisplayEquipmentInfo(Serial, number, _crafter, false, attrs);
|
||||
}
|
||||
|
||||
public void OnSingleClickPreUOTD(Mobile from)
|
||||
{
|
||||
var name = Name;
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
var articleAnName = (TileData.ItemTable[ItemID].Flags & TileFlag.ArticleAn) != 0;
|
||||
name = $"{(articleAnName ? "an" : "a")} {Localization.GetText(LabelNumber).ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
if (Crafter == null)
|
||||
{
|
||||
LabelTo(from, Quality == ClothingQuality.Exceptional ? $"{name} of exceptional quality" : name);
|
||||
return;
|
||||
}
|
||||
|
||||
LabelTo(
|
||||
from,
|
||||
Quality == ClothingQuality.Exceptional
|
||||
? $"{name} crafted with exceptional quality by {Crafter}"
|
||||
: $"{name} crafted by {Crafter}"
|
||||
);
|
||||
}
|
||||
|
||||
public virtual void AddEquipInfoAttributes(Mobile from, List<EquipInfoAttribute> attrs)
|
||||
{
|
||||
if (DisplayLootType)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Network;
|
||||
using Server.Spells;
|
||||
using Server.Targeting;
|
||||
using Server.Text;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
|
|
@ -168,6 +171,12 @@ public abstract partial class BaseWand : BaseBashing
|
|||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (!Core.UOTD)
|
||||
{
|
||||
OnSingleClickPreUOTD(from);
|
||||
return;
|
||||
}
|
||||
|
||||
var attrs = new List<EquipInfoAttribute>();
|
||||
|
||||
if (DisplayLootType)
|
||||
|
|
@ -230,6 +239,45 @@ public abstract partial class BaseWand : BaseBashing
|
|||
from.NetState.SendDisplayEquipmentInfo(Serial, number, Crafter, false, attrs);
|
||||
}
|
||||
|
||||
public void OnSingleClickPreUOTD(Mobile from)
|
||||
{
|
||||
var isMagicItem = _charges > 0;
|
||||
var name = Name;
|
||||
if (name == null)
|
||||
{
|
||||
var articleAnName = (TileData.ItemTable[ItemID].Flags & TileFlag.ArticleAn) != 0;
|
||||
name = $"{(articleAnName ? "an" : "a")} {Localization.GetText(LabelNumber).ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
if (isMagicItem && !Identified)
|
||||
{
|
||||
LabelTo(from, $"an unidentified {name}");
|
||||
return;
|
||||
}
|
||||
|
||||
LabelTo(from, isMagicItem ? $"{name} of {WandEffectText}" : name);
|
||||
}
|
||||
|
||||
private string WandEffectText
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _wandEffect switch
|
||||
{
|
||||
WandEffect.Clumsiness => "clumsiness",
|
||||
WandEffect.Identification => "identification",
|
||||
WandEffect.Healing => "healing",
|
||||
WandEffect.Feeblemindedness => "feeblemindedness",
|
||||
WandEffect.Weakness => "weakness",
|
||||
WandEffect.MagicArrow => "magic arrow",
|
||||
WandEffect.Harming => "harming",
|
||||
WandEffect.Fireball => "fireball",
|
||||
WandEffect.GreaterHealing => "greater healing",
|
||||
WandEffect.Lightning => "lightning",
|
||||
WandEffect.ManaDraining => "mana draining",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
public void Cast(Spell spell)
|
||||
{
|
||||
var m = Movable;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Collections;
|
||||
|
|
@ -17,6 +18,7 @@ using Server.Spells.Necromancy;
|
|||
using Server.Spells.Ninjitsu;
|
||||
using Server.Spells.Sixth;
|
||||
using Server.Spells.Spellweaving;
|
||||
using Server.Text;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
|
|
@ -673,6 +675,7 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
|
||||
PlayerConstructed = true;
|
||||
Identified = true;
|
||||
|
||||
var resourceType = typeRes ?? craftItem.Resources[0].ItemType;
|
||||
|
||||
|
|
@ -728,21 +731,18 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
{
|
||||
case CraftResource.DullCopper:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Durable;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Accurate;
|
||||
break;
|
||||
}
|
||||
case CraftResource.ShadowIron:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Durable;
|
||||
DamageLevel = WeaponDamageLevel.Ruin;
|
||||
break;
|
||||
}
|
||||
case CraftResource.Copper:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Fortified;
|
||||
DamageLevel = WeaponDamageLevel.Ruin;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
|
||||
|
|
@ -750,7 +750,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
case CraftResource.Bronze:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Fortified;
|
||||
DamageLevel = WeaponDamageLevel.Might;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
|
||||
|
|
@ -758,7 +757,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
case CraftResource.Gold:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
|
||||
DamageLevel = WeaponDamageLevel.Force;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Eminently;
|
||||
|
|
@ -766,7 +764,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
case CraftResource.Agapite:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
|
||||
DamageLevel = WeaponDamageLevel.Power;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Eminently;
|
||||
|
|
@ -774,7 +771,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
case CraftResource.Verite:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
|
||||
DamageLevel = WeaponDamageLevel.Power;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Exceedingly;
|
||||
|
|
@ -782,7 +778,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
}
|
||||
case CraftResource.Valorite:
|
||||
{
|
||||
Identified = true;
|
||||
DurabilityLevel = WeaponDurabilityLevel.Indestructible;
|
||||
DamageLevel = WeaponDamageLevel.Vanq;
|
||||
AccuracyLevel = WeaponAccuracyLevel.Supremely;
|
||||
|
|
@ -3332,6 +3327,12 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (!Core.UOTD)
|
||||
{
|
||||
OnSingleClickPreUOTD(from);
|
||||
return;
|
||||
}
|
||||
|
||||
var attrs = new List<EquipInfoAttribute>();
|
||||
|
||||
if (DisplayLootType)
|
||||
|
|
@ -3423,6 +3424,130 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab
|
|||
from.NetState.SendDisplayEquipmentInfo(Serial, number, _crafter, false, attrs);
|
||||
}
|
||||
|
||||
public virtual void OnSingleClickPreUOTD(Mobile from)
|
||||
{
|
||||
var isMagicItem = _durabilityLevel > WeaponDurabilityLevel.Regular ||
|
||||
_accuracyLevel > WeaponAccuracyLevel.Regular ||
|
||||
_damageLevel > WeaponDamageLevel.Regular ||
|
||||
_slayer != SlayerName.None;
|
||||
|
||||
if (isMagicItem && !_identified)
|
||||
{
|
||||
LabelTo(from, $"an unidentified {Name ?? Localization.GetText(LabelNumber).ToLowerInvariant()}");
|
||||
return;
|
||||
}
|
||||
|
||||
var name = Name;
|
||||
var articleAnName = (TileData.ItemTable[ItemID].Flags & TileFlag.ArticleAn) != 0;
|
||||
|
||||
if (isMagicItem)
|
||||
{
|
||||
var builder = ValueStringBuilder.Create(128);
|
||||
|
||||
var durabilityText = DurabilityText(out var articleAnDurability);
|
||||
if (durabilityText != null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(durabilityText, articleAnDurability);
|
||||
}
|
||||
|
||||
var accuracyText = AccuracyText(out var articleAnAccuracy);
|
||||
if (accuracyText != null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(accuracyText, articleAnAccuracy);
|
||||
}
|
||||
|
||||
var slayerEntry = SlayerGroup.GetEntryByName(_slayer);
|
||||
if (slayerEntry != null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(slayerEntry.SlayerText(out var articleAnSlayer), articleAnSlayer);
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
builder.AppendSpaceWithArticle(Localization.GetText(LabelNumber).ToLowerInvariant(), articleAnName);
|
||||
}
|
||||
else if (builder.Length != 0)
|
||||
{
|
||||
builder.Append($" {name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append(name);
|
||||
}
|
||||
|
||||
var weaponDamageText = WeaponDamageText;
|
||||
if (weaponDamageText != null)
|
||||
{
|
||||
builder.Append($" of {weaponDamageText}");
|
||||
}
|
||||
|
||||
// TODO: Spells (of Ghoul's Touch)
|
||||
|
||||
LabelTo(from, builder.ToString());
|
||||
builder.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
name ??= $"{(articleAnName ? "an" : "a")} {Localization.GetText(LabelNumber).ToLowerInvariant()}";
|
||||
|
||||
if (Crafter == null)
|
||||
{
|
||||
LabelTo(from, Quality == WeaponQuality.Exceptional ? $"{name} of exceptional quality" : name);
|
||||
return;
|
||||
}
|
||||
|
||||
LabelTo(
|
||||
from,
|
||||
Quality == WeaponQuality.Exceptional
|
||||
? $"{name} crafted with exceptional quality by {Crafter}"
|
||||
: $"{name} crafted by {Crafter}"
|
||||
);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private string DurabilityText(out bool articleAn)
|
||||
{
|
||||
articleAn = _durabilityLevel is WeaponDurabilityLevel.Indestructible;
|
||||
return _durabilityLevel switch
|
||||
{
|
||||
WeaponDurabilityLevel.Durable => "durable",
|
||||
WeaponDurabilityLevel.Substantial => "substantial",
|
||||
WeaponDurabilityLevel.Massive => "massive",
|
||||
WeaponDurabilityLevel.Fortified => "fortified",
|
||||
WeaponDurabilityLevel.Indestructible => "indestructible",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private string AccuracyText(out bool articleAn)
|
||||
{
|
||||
articleAn = _accuracyLevel is WeaponAccuracyLevel.Accurate or WeaponAccuracyLevel.Eminently;
|
||||
return _accuracyLevel switch
|
||||
{
|
||||
WeaponAccuracyLevel.Accurate => "accurate",
|
||||
WeaponAccuracyLevel.Surpassingly => "surpassingly accurate",
|
||||
WeaponAccuracyLevel.Eminently => "eminently accurate",
|
||||
WeaponAccuracyLevel.Exceedingly => "exceedingly accurate",
|
||||
WeaponAccuracyLevel.Supremely => "supremely accurate",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
private string WeaponDamageText
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _damageLevel switch
|
||||
{
|
||||
WeaponDamageLevel.Ruin => "ruin",
|
||||
WeaponDamageLevel.Might => "might",
|
||||
WeaponDamageLevel.Force => "force",
|
||||
WeaponDamageLevel.Power => "power",
|
||||
WeaponDamageLevel.Vanq => "vanquishing",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
public virtual int GetHitAttackSound(Mobile attacker, Mobile defender)
|
||||
{
|
||||
var sound = attacker.GetAttackSound();
|
||||
|
|
|
|||
|
|
@ -98,5 +98,10 @@ namespace Server.Items
|
|||
Effects.PlaySound(endLoc, map, Utility.Random(0x11B, 4));
|
||||
Effects.SendLocationEffect(endLoc, map, 0x373A + 0x10 * Utility.Random(4), 16, 10, hue, renderMode);
|
||||
}
|
||||
|
||||
public override void OnSingleClickPreUOTD(Mobile from)
|
||||
{
|
||||
LabelTo(from, Name ?? Localization.GetText(LabelNumber).ToLowerInvariant());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,20 @@ namespace Server.Items
|
|||
}
|
||||
}
|
||||
|
||||
public string SlayerText(out bool articleAn)
|
||||
{
|
||||
if (Name == SlayerName.None)
|
||||
{
|
||||
articleAn = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
articleAn = Name is SlayerName.OrcSlaying or SlayerName.OgreTrashing or SlayerName.Exorcism or SlayerName.Ophidian
|
||||
or SlayerName.ArachnidDoom or SlayerName.ElementalBan or SlayerName.ElementalHealth or SlayerName.EarthShatter;
|
||||
|
||||
return Localization.GetText(Title)?.ToLowerInvariant();
|
||||
}
|
||||
|
||||
public bool Slays(Mobile m)
|
||||
{
|
||||
var t = m.GetType();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue