1 using Microsoft.Xna.Framework;
3 using System.Collections.Generic;
10 using System.Collections.Immutable;
35 get {
return _sprite; }
38 if (value == _sprite) {
return; }
76 public float Scale {
get;
private set; }
84 get {
return _wearableComponent; }
87 if (value == _wearableComponent) {
return; }
88 if (_wearableComponent !=
null)
90 _wearableComponent.
Remove();
92 _wearableComponent = value;
95 public string Sound {
get;
private set; }
104 if (_lightComponents ==
null)
106 _lightComponents =
new List<LightComponent>();
108 return _lightComponents;
111 private List<LightComponent> _lightComponents;
122 get {
return _picker; }
125 if (value == _picker) {
return; }
159 Variant = Math.Max(variant, 0);
171 $
"{Path.GetDirectoryName(WearableComponent.Item.Prefab.FilePath)}/{textureName}");
186 if (_picker?.Info !=
null)
252 if (index.X > -1 && index.Y > -1)
259 if (wearableTypes !=
null && wearableTypes.Length > 0)
261 foreach (var value
in wearableTypes)
263 if (Enum.TryParse(value, ignoreCase:
true, out
WearableType wearableType))
281 private readonly
LimbType[] limbType;
282 private readonly
Limb[] limb;
284 private readonly List<DamageModifier> damageModifiers;
287 public readonly Dictionary<StatTypes, float>
WearableStatValues =
new Dictionary<StatTypes, float>();
291 get {
return damageModifiers; }
297 [
Serialize(
false,
IsPropertySaveable.No, description:
"Can the item be used (assuming it has components that are usable in some way) when worn.")]
305 get {
return variant; }
308 if (variant == value) {
return; }
313 item.CreateServerEvent(
this);
318 if (character !=
null)
323 for (
int i = 0; i < wearableSprites.Length; i++)
325 var subElement = wearableElements[i];
327 wearableSprites[i]?.Sprite?.Remove();
331 if (character !=
null)
350 damageModifiers =
new List<DamageModifier>();
353 int spriteCount = element.
Elements().Count(x => x.Name.ToString() ==
"sprite");
355 variant = Rand.Range(1,
Variants + 1, Rand.RandSync.ServerAndClient);
358 limbType =
new LimbType[spriteCount];
359 limb =
new Limb[spriteCount];
363 foreach (var subElement
in element.
Elements())
365 switch (subElement.Name.ToString().ToLowerInvariant())
368 if (subElement.GetAttribute(
"texture") ==
null)
370 DebugConsole.ThrowError(
"Item \"" +
item.
Name +
"\" doesn't have a texture specified!",
376 subElement.GetAttributeString(
"limb",
"Head"),
true);
378 wearableSprites[i] =
new WearableSprite(subElement,
this, variant);
379 wearableElements[i] = subElement;
381 foreach (var lightElement
in subElement.Elements())
383 if (!lightElement.Name.ToString().Equals(
"lightcomponent", StringComparison.OrdinalIgnoreCase)) {
continue; }
388 foreach (var light
in wearableSprites[i].LightComponents)
396 case "damagemodifier":
399 case "skillmodifier":
400 Identifier skillIdentifier = subElement.GetAttributeIdentifier(
"skillidentifier", Identifier.Empty);
401 float skillValue = subElement.GetAttributeFloat(
"skillvalue", 0f);
413 float statValue = subElement.GetAttributeFloat(
"value", 0f);
424 if (subElement.GetAttributeString(
"Target",
string.Empty).ToLowerInvariant().Contains(
"character"))
438 foreach (Enum value
in Enum.GetValues(typeof(
InvSlotType)))
442 if (allowedSlot.HasFlag(slotType) && !character.Inventory.IsInLimbSlot(
item, slotType))
451 for (
int i = 0; i < wearableSprites.Length; i++ )
453 var wearableSprite = wearableSprites[i];
454 if (!wearableSprite.IsInitialized) { wearableSprite.Init(
picker); }
456 wearableSprite.Picker =
picker;
458 Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
459 if (equipLimb ==
null) {
continue; }
466 if (wearableSprite.LightComponent !=
null)
468 foreach (var light
in wearableSprite.LightComponents)
470 light.ParentBody = equipLimb.
body;
480 float depth = wearable?.Sprite?.Depth ?? 0;
481 float nextDepth = nextWearable?.Sprite?.Depth ?? 0;
482 return nextDepth.CompareTo(depth);
486 var wearableComponent = wearable?.WearableComponent;
487 var nextWearableComponent = nextWearable?.WearableComponent;
488 if (wearableComponent ==
null && nextWearableComponent ==
null) {
return 0; }
489 if (wearableComponent ==
null) {
return -1; }
490 if (nextWearableComponent ==
null) {
return 1; }
491 return wearableComponent.AllowedSlots.Contains(
InvSlotType.OuterClothes).CompareTo(nextWearableComponent.AllowedSlots.Contains(
InvSlotType.OuterClothes));
498 character.OnWearablesChanged();
505 base.Drop(dropper, setTransform);
513 if (character ==
null || character.
Removed) {
return; }
514 if (
picker ==
null) {
return; }
516 for (
int i = 0; i < wearableSprites.Length; i++)
519 if (equipLimb ==
null) {
continue; }
523 foreach (var light
in wearableSprites[i].LightComponents)
525 light.ParentBody =
null;
529 equipLimb.
WearingItems.RemoveAll(w => w !=
null && w == wearableSprites[i]);
553 if (
item.GetComponent<
Holdable>() is not { IsActive: true })
566 base.RemoveComponentSpecific();
573 wearableSprite.
Picker =
null;
577 public override XElement
Save(XElement parentElement)
579 XElement componentElement = base.Save(parentElement);
580 componentElement.Add(
new XAttribute(
"variant", variant));
581 return componentElement;
584 private int loadedVariant = -1;
587 base.Load(componentElement, usePrefabValues, idRemap, isItemSwap);
594 if (loadedVariant > 0 && loadedVariant <
Variants + 1)
602 base.ServerEventWrite(msg, c, extraData);
608 base.ClientEventRead(msg, sendingTime);
static StatTypes ParseStatType(string statTypeString, string debugIdentifier)
override Vector2? SimPosition
readonly AnimController AnimController
void OnWearablesChanged()
string ReplaceVars(string str)
CharacterInfoPrefab CharacterInfoPrefab
static CharacterPrefab HumanPrefab
static ContentPath FromRaw(string? rawValue)
static readonly ContentPath Empty
string? GetAttributeString(string key, string? def)
Identifier[] GetAttributeIdentifierArray(Identifier[] def, params string[] keys)
Point GetAttributePoint(string key, in Point def)
float GetAttributeFloat(string key, float def)
ContentPackage? ContentPackage
IEnumerable< ContentXElement > Elements()
bool DoesAttributeReferenceFileNameAlone(string key)
ContentPath? GetAttributeContentPath(string key)
bool GetAttributeBool(string key, bool def)
int GetAttributeInt(string key, int def)
string?[] GetAttributeStringArray(string key, string[]? def, bool convertToLowerInvariant=false)
XAttribute? GetAttribute(string name)
void ApplyStatusEffects(ActionType type, float deltaTime, Character character=null, Limb limb=null, Entity useTarget=null, bool isNetworkEvent=false, Vector2? worldPosition=null)
Executes all StatusEffects of the specified type. Note that condition checks are ignored here: that s...
void SetTransform(Vector2 simPosition, float rotation, bool findNewHull=true, bool setPrevTransform=true)
void AddComponent(ItemComponent component)
override string Name
Note that this is not a LocalizedString instance, just the current name of the item as a string....
void PlaySound(ActionType type, Character user=null)
List< InvSlotType > allowedSlots
bool DisplayContainedStatus
override XElement Save(XElement parentElement)
override void Equip(Character character)
override void ClientEventRead(IReadMessage msg, float sendingTime)
readonly Dictionary< StatTypes, float > WearableStatValues
override void OnItemLoaded()
Called when all the components of the item have been loaded. Use to initialize connections between co...
Wearable(Item item, ContentXElement element)
override void RemoveComponentSpecific()
override void Drop(Character dropper, bool setTransform=true)
a Character has dropped the item
IEnumerable< DamageModifier > DamageModifiers
override void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData=null)
readonly Dictionary< Identifier, float > SkillModifiers
readonly float PressureProtection
How deep down does the item protect from pressure? Determined by status effects.
override void Unequip(Character character)
override void Load(ContentXElement componentElement, bool usePrefabValues, IdRemap idRemap, bool isItemSwap)
override void Update(float deltaTime, Camera cam)
override void UpdateBroken(float deltaTime, Camera cam)
readonly List< WearableSprite > WearingItems
void UpdateWearableTypesToHide()
Limb GetLimb(LimbType limbType, bool excludeSevered=true)
Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
bool ParseTexturePath(string path="", string file="")
ImmutableHashSet< Identifier > CanBeHiddenByItem
Tags or identifiers of items that can hide this one.
void ParsePath(bool parseSpritePath)
ContentPath UnassignedSpritePath
bool InheritScale
Does the wearable inherit all the scalings of the wearer? Also the wearable's own scale is used!
ObscuringMode ObscureOtherWearables
List< LightComponent > LightComponents
Character Picker
None = Any/Not Defined -> no effect. Changing the gender forces re-initialization,...
WearableSprite(ContentXElement subElement, Wearable wearable, int variant=0)
Note: this constructor cannot initialize automatically, because the gender is unknown at this point....
List< WearableType > HideWearablesOfType
bool AlphaClipOtherWearables
ContentXElement SourceElement
Wearable WearableComponent
bool CanBeHiddenByOtherWearables
WearableSprite(ContentXElement subElement, WearableType type)
void Init(Character picker=null)
Interface for entities that the server can send events to the clients
ActionType
ActionTypes define when a StatusEffect is executed.
StatTypes
StatTypes are used to alter several traits of a character. They are mostly used by talents.