4 using Microsoft.Xna.Framework;
6 using System.Collections.Generic;
7 using System.Collections.Immutable;
8 using System.Globalization;
10 using System.Xml.Linq;
18 readonly record
struct ContainedItem(
Item Item, bool Hide, Vector2?
ItemPos, float Rotation);
20 class SlotRestrictions
26 public SlotRestrictions(
int maxStackSize, List<RelatedItem> containableItems,
bool autoInject)
43 public bool MatchesItem(Identifier identifierOrTag)
47 ContainableItems.Any(c => c.Identifiers.Contains(identifierOrTag) && !c.ExcludedIdentifiers.Contains(identifierOrTag));
53 private bool alwaysContainedItemsSpawned;
57 private readonly List<ActiveContainedItem> activeContainedItems =
new List<ActiveContainedItem>();
59 private readonly List<ContainedItem> containedItems =
new List<ContainedItem>();
61 private List<ushort>[] itemIds;
68 get {
return capacity; }
71 capacity = Math.Max(value, 0);
81 private int maxStackSize;
82 [
Serialize(64,
IsPropertySaveable.No, description:
"How many items can be stacked in one slot. Does not increase the maximum stack size of the items themselves, e.g. a stack of bullets could have a maximum size of 8 but the number of bullets in a specific weapon could be restricted to 6.")]
85 get {
return maxStackSize; }
86 set { maxStackSize = Math.Max(value, 1); }
89 private bool hideItems;
91 +
" If set to false, you should use the ItemPos and ItemInterval properties to determine where the items get rendered.")]
94 get {
return hideItems; }
102 [
Serialize(
"0.0,0.0",
IsPropertySaveable.No, description:
"The position where the contained items get drawn at (offset from the upper left corner of the sprite in pixels).")]
105 [
Serialize(
"0.0,0.0",
IsPropertySaveable.No, description:
"The interval at which the contained items are spaced apart from each other (in pixels).")]
132 [
Serialize(
true,
IsPropertySaveable.Yes, description:
"When this item is equipped, and you 'quick use' (double click / equip button) another equippable item, should the game attempt to move that item inside this one?")]
135 [
Serialize(
false,
IsPropertySaveable.No, description:
"If set to true, interacting with this item will make the character interact with the contained item(s), automatically picking them up if they can be picked up.")]
142 private ImmutableHashSet<Identifier> autoInteractWithContainedTags = ImmutableHashSet<Identifier>.Empty;
143 [
Serialize(
"",
IsPropertySaveable.Yes, description: $
"Interacting with this container will autointeract with contained items that have one of these tags. Only valid if {nameof(AutoInteractWithContained)} is set to true.")]
146 get {
return autoInteractWithContainedTags.ConvertToString(); }
149 autoInteractWithContainedTags = value.ToIdentifiers().ToImmutableHashSet();
156 [
Serialize(
false,
IsPropertySaveable.No, description:
"Is the container only accessible when it's broken. Doesn't apply to editors.")]
165 private readonly HashSet<Identifier> containableRestrictions =
new HashSet<Identifier>();
166 [
Editable,
Serialize(
"",
IsPropertySaveable.Yes, description:
"Define items (by identifiers or tags) that bots should place inside this container. If empty, no restrictions are applied.")]
169 get {
return string.Join(
",", containableRestrictions); }
172 containableRestrictions.Clear();
173 if (!value.IsNullOrEmpty())
175 foreach (var str
in value.Split(
','))
177 if (str.IsNullOrWhiteSpace()) {
continue; }
178 containableRestrictions.Add(str.ToIdentifier());
187 private float itemRotation;
191 get {
return MathHelper.ToDegrees(itemRotation); }
192 set { itemRotation = MathHelper.ToRadians(value); }
202 [
Serialize(
false,
IsPropertySaveable.No, description:
"Should the items configured using SpawnWithId spawn if this item is broken.")]
216 [
Serialize(0.5f,
IsPropertySaveable.No, description:
"The health threshold that the user must reach in order to activate the autoinjection.")]
257 private readonly ImmutableArray<SlotRestrictions> slotRestrictions;
259 readonly List<ISerializableEntity> targets =
new List<ISerializableEntity>();
261 private float prevContainedItemRefreshRotation;
262 private Vector2 prevContainedItemRefreshPosition;
264 private float autoInjectCooldown = 1.0f;
265 const float AutoInjectInterval = 1.0f;
267 private bool subContainersCanAutoInject;
272 isRestrictionsDefined = containableRestrictions.Any();
273 if (slotRestrictions.None(s => s.MatchesItem(
item))) {
return false; }
274 if (!isRestrictionsDefined) {
return true; }
275 return identifiersOrTags.Any(
id => containableRestrictions.Any(r => r ==
id));
280 isRestrictionsDefined = containableRestrictions.Any();
281 if (slotRestrictions.None(s => s.MatchesItem(
item))) {
return false; }
282 if (!isRestrictionsDefined) {
return true; }
286 private ImmutableHashSet<Identifier> containableItemIdentifiers;
296 private string totalConditionValueString =
"", totalConditionPercentageString =
"", totalItemsString =
"";
297 private float prevTotalConditionValue = 0, prevTotalConditionPercentage = 0;
int prevTotalItems = 0;
300 : base(
item, element)
302 int totalCapacity = capacity;
304 foreach (var subElement
in element.Elements())
306 switch (subElement.Name.ToString().ToLowerInvariant())
310 if (containable ==
null)
312 DebugConsole.ThrowError(
"Error in item config \"" +
item.
ConfigFilePath +
"\" - containable with no identifiers.",
320 totalCapacity += subElement.GetAttributeInt(
"capacity", 1);
330 List<SlotRestrictions> newSlotRestrictions =
new List<SlotRestrictions>(totalCapacity);
331 for (
int i = 0; i < capacity; i++)
333 newSlotRestrictions.Add(
new SlotRestrictions(maxStackSize,
ContainableItems, autoInject:
false));
336 int subContainerIndex = capacity;
337 foreach (var subElement
in element.Elements())
339 if (subElement.Name.ToString().ToLowerInvariant() !=
"subcontainer") {
continue; }
341 int subCapacity = subElement.GetAttributeInt(
"capacity", 1);
342 int subMaxStackSize = subElement.GetAttributeInt(
"maxstacksize", maxStackSize);
343 bool autoInject = subElement.GetAttributeBool(
"autoinject",
false);
345 subContainersCanAutoInject |= autoInject;
347 var subContainableItems =
new List<RelatedItem>();
348 foreach (var subSubElement
in subElement.Elements())
350 if (subSubElement.Name.ToString().ToLowerInvariant() !=
"containable") {
continue; }
353 if (containable ==
null)
355 DebugConsole.ThrowError(
"Error in item config \"" +
item.
ConfigFilePath +
"\" - containable with no identifiers.",
359 subContainableItems.Add(containable);
364 for (
int i = subContainerIndex; i < subContainerIndex + subCapacity; i++)
366 newSlotRestrictions.Add(
new SlotRestrictions(subMaxStackSize, subContainableItems, autoInject));
368 subContainerIndex += subCapacity;
370 capacity = totalCapacity;
371 slotRestrictions = newSlotRestrictions.ToImmutableArray();
372 System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length);
373 InitProjSpecific(element);
378 int containableIndex = 0;
379 foreach (var subElement
in element.GetChildElements(
"containable"))
382 if (containable ==
null)
384 DebugConsole.ThrowError(
"Error when loading containable restrictions for \"" +
item.
Name +
"\" - containable with no identifiers.",
385 contentPackage: element.ContentPackage);
392 for (
int i = 0; i < capacity; i++)
397 if (element.GetChildElement(
"clearsubcontainerrestrictions") !=
null)
410 if (slotIndex < 0 || slotIndex >= capacity)
414 return slotRestrictions[slotIndex].MaxStackSize;
423 if (index >= 0 && index < slotRestrictions.Length)
427 activeContainedItems.RemoveAll(i => i.Item == containedItem);
430 if (!containableItem.MatchesItem(containedItem)) {
continue; }
432 relatedItem ??= containableItem;
433 foreach (
StatusEffect effect
in containableItem.StatusEffects)
435 ActiveContainedItem activeContainedItem =
new(containedItem, effect, containableItem.ExcludeBroken, containableItem.ExcludeFullCondition, containableItem.BlameEquipperForDeath);
436 activeContainedItems.Add(activeContainedItem);
438 if (!ShouldApplyEffects(activeContainedItem)) {
continue; }
439 activeContainedItem.StatusEffect.Apply(
ActionType.OnInserted, deltaTime: 1,
item, targets);
445 var containedItemInfo =
new ContainedItem(containedItem,
446 Hide: relatedItem?.Hide ??
false,
448 Rotation: relatedItem?.Rotation ?? 0.0f);
449 containedItems.RemoveAll(d => d.Item == containedItem);
454 containedItems.Add(containedItemInfo);
458 int containedIndex = 0;
459 while (containedIndex < containedItems.Count)
468 containedItems.Insert(containedIndex, containedItemInfo);
471 if (
item.GetComponent<Planter>() !=
null)
483 SetContainedActive(
true);
487 containedItem.
FlipX(relativeToSub:
false);
491 containedItem.
FlipY(relativeToSub:
false);
498 public override void Move(Vector2 amount,
bool ignoreContacts =
false)
505 foreach (ActiveContainedItem activeContainedItem
in activeContainedItems)
507 if (activeContainedItem.Item != containedItem || !ShouldApplyEffects(activeContainedItem)) {
continue; }
508 activeContainedItem.StatusEffect.Apply(
ActionType.OnRemoved, deltaTime: 1,
item, targets);
511 activeContainedItems.RemoveAll(i => i.Item == containedItem);
512 containedItems.RemoveAll(i => i.Item == containedItem);
522 return activeContainedItems.Any(c => c.BlameEquipperForDeath);
528 return slotRestrictions.Any(s => s.MatchesItem(
item));
533 if (index < 0 || index >= capacity) {
return false; }
535 return slotRestrictions[index].MatchesItem(
item);
540 return slotRestrictions.Any(s => s.MatchesItem(itemPrefab));
545 if (index < 0 || index >= capacity) {
return false; }
546 return slotRestrictions[index].MatchesItem(itemPrefab);
551 if (
item ==
null) {
return false; }
562 public override void FlipX(
bool relativeToSub)
564 base.FlipX(relativeToSub);
571 containedItem.
FlipX(relativeToSub);
578 if (!
string.IsNullOrEmpty(
SpawnWithId) && !alwaysContainedItemsSpawned)
580 SpawnAlwaysContainedItems();
581 alwaysContainedItemsSpawned =
true;
586 float totalConditionValue = 0, totalConditionPercentage = 0;
int totalItems = 0;
597 if (!MathUtils.NearlyEqual(totalConditionValue, prevTotalConditionValue))
599 totalConditionValueString = ((int)totalConditionValue).ToString(CultureInfo.InvariantCulture);
600 prevTotalConditionValue = totalConditionValue;
603 if (!MathUtils.NearlyEqual(totalConditionPercentage, prevTotalConditionPercentage))
605 totalConditionPercentageString = ((int)totalConditionPercentage).ToString(CultureInfo.InvariantCulture);
606 prevTotalConditionPercentage = totalConditionPercentage;
609 if (totalItems != prevTotalItems)
611 totalItemsString = totalItems.ToString(CultureInfo.InvariantCulture);
612 prevTotalItems = totalItems;
615 item.
SendSignal(totalConditionValueString,
"contained_conditions");
616 item.
SendSignal(totalConditionPercentageString,
"contained_conditions_percentage");
622 SetContainedItemPositionsIfNeeded();
632 autoInjectCooldown -= deltaTime;
633 if (autoInjectCooldown <= 0.0f &&
634 ownerInventory?.Owner is
Character ownerCharacter &&
636 ownerCharacter.HasEquippedItem(
item))
644 for (
int i = 0; i < slotRestrictions.Length; i++)
658 autoInjectCooldown = AutoInjectInterval;
667 SetContainedItemPositionsIfNeeded();
676 foreach (ActiveContainedItem activeContainedItem
in activeContainedItems)
678 if (!ShouldApplyEffects(activeContainedItem))
continue;
690 private bool ShouldApplyEffects(ActiveContainedItem activeContainedItem)
692 Item contained = activeContainedItem.
Item;
693 if (activeContainedItem.ExcludeBroken && contained.
Condition <= 0) {
return false; }
694 if (activeContainedItem.ExcludeFullCondition && contained.
IsFullCondition) {
return false; }
708 targets.Add(character);
710 if (effect.
HasTargetType(StatusEffect.TargetType.NearbyItems) || effect.
HasTargetType(StatusEffect.TargetType.NearbyCharacters))
720 private void SetContainedItemPositionsIfNeeded()
722 if (Vector2.DistanceSquared(prevContainedItemRefreshPosition,
item.
Position) > 10.0f ||
742 return IsAccessible() && base.HasRequiredItems(character, addMessage, msg);
772 if (CanAutoInteractWithContained(contained) && contained.
TryInteract(character))
789 return base.Select(character);
800 if (CanAutoInteractWithContained(contained) && contained.
TryInteract(picker))
810 return picker !=
null;
816 if (!slotRestrictions.Any(s => s.MatchesItem(
item))) {
return false; }
819 if (this.Item.GetComponent<
GeneticMaterial>() !=
null) {
return false; }
835 SetContainedActive(
false);
843 SetContainedActive(
true);
847 SetContainedActive(
false);
851 private bool CanAutoInteractWithContained(
Item containedItem)
856 private void SetContainedActive(
bool active)
865 RelatedItem containableItem = FindContainableItem(containedItem);
866 if (containableItem !=
null && containableItem.
SetActive)
870 ic.IsActive = active;
872 if (containedItem.
body !=
null)
888 private RelatedItem FindContainableItem(
Item item)
891 if (index == -1 ) {
return null; }
892 return slotRestrictions[index]?.ContainableItems?.FirstOrDefault(ci => ci.MatchesItem(
item));
900 for (
int i = 0; i < slotRestrictions.Length; i++)
902 if (slotRestrictions[i].MatchesItem(itemTagOrIdentifier)) {
return i; }
909 switch (connection.
Name)
914 if (signal.
value !=
"0")
922 #warning There's some code duplication here and in DrawContainedItems() method, but it's not straightforward to get rid of it, because of slightly different logic and the usage of draw positions vs. positions etc. Should probably be splitted into smaller methods.
927 Vector2 transformedItemPos = GetContainedPosition(
929 out Vector2 transformedItemIntervalHorizontal,
930 out Vector2 transformedItemIntervalVertical,
935 Vector2 currentItemPos = transformedItemPos;
936 foreach (ContainedItem contained
in containedItems)
938 Vector2 itemPos = currentItemPos;
939 if (contained.ItemPos.HasValue)
941 Vector2 pos = contained.ItemPos.Value;
945 pos.X *= rootBody.Dir;
954 itemPos.X = -itemPos.X;
959 itemPos.Y = -itemPos.Y;
971 if (contained.Item.body !=
null)
975 Vector2 simPos = ConvertUnits.ToSimUnits(itemPos);
976 float rotation = itemRotation;
977 if (contained.Rotation != 0)
979 rotation = MathHelper.ToRadians(contained.Rotation);
983 rotation *= rootBody.Dir;
990 contained.Item.body.FarseerBody.SetTransformIgnoreContacts(ref simPos, rotation);
991 contained.Item.body.SetPrevTransform(contained.Item.body.SimPosition, contained.Item.body.Rotation);
992 contained.Item.body.UpdateDrawPosition();
996 DebugConsole.Log(
"SetTransformIgnoreContacts threw an exception in SetContainedItemPositions (" + e.Message +
")\n" + e.StackTrace.CleanupStackTrace());
997 GameAnalyticsManager.AddErrorEventOnce(
"ItemContainer.SetContainedItemPositions.InvalidPosition:" + contained.Item.Name,
998 GameAnalyticsManager.ErrorSeverity.Error,
999 "SetTransformIgnoreContacts threw an exception in SetContainedItemPositions (" + e.Message +
")\n" + e.StackTrace.CleanupStackTrace());
1004 contained.Item.Rect =
1006 (
int)(itemPos.X - contained.Item.Rect.Width / 2.0f),
1007 (
int)(itemPos.Y + contained.Item.Rect.Height / 2.0f),
1008 contained.Item.Rect.Width, contained.Item.Rect.Height);
1012 contained.Item.SetContainedItemPositions();
1018 currentItemPos += transformedItemIntervalHorizontal;
1021 currentItemPos = transformedItemPos;
1022 currentItemPos += transformedItemIntervalVertical * (i /
ItemsPerRow);
1027 currentItemPos += transformedItemIntervalHorizontal + transformedItemIntervalVertical;
1032 private Vector2 GetContainedPosition(
bool drawPosition,
1033 out Vector2 transformedItemIntervalHorizontal, out Vector2 transformedItemIntervalVertical,
1034 out
bool flippedX, out
bool flippedY)
1038 transformedItemIntervalHorizontal =
new Vector2(transformedItemInterval.X, 0.0f);
1039 transformedItemIntervalVertical =
new Vector2(0.0f, transformedItemInterval.Y);
1044 bool bodyFlipped = rootBody is { Dir: -1 };
1056 transformedItemPos.X = -transformedItemPos.X;
1057 transformedItemPos.X +=
item.
Rect.Width;
1058 transformedItemInterval.X = -transformedItemInterval.X;
1059 transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
1063 transformedItemPos.Y = -transformedItemPos.Y;
1064 transformedItemPos.Y -=
item.
Rect.Height;
1065 transformedItemInterval.Y = -transformedItemInterval.Y;
1066 transformedItemIntervalVertical.Y = -transformedItemIntervalVertical.Y;
1076 transformedItemPos =
1080 transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
1081 transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
1089 transformedItemPos.X = -transformedItemPos.X;
1090 transformedItemInterval.X = -transformedItemInterval.X;
1091 transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
1094 transformedItemPos = Vector2.Transform(transformedItemPos, transform);
1095 transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
1096 transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
1100 return transformedItemPos;
1106 containableItemIdentifiers = slotRestrictions.SelectMany(s => s.ContainableItems?.SelectMany(ri => ri.Identifiers) ?? Enumerable.Empty<Identifier>()).ToImmutableHashSet();
1110 SpawnAlwaysContainedItems();
1116 if (itemIds !=
null)
1118 for (ushort i = 0; i < itemIds.Length; i++)
1127 foreach (ushort
id in itemIds[i])
1148 SpawnAlwaysContainedItems();
1154 private void SpawnAlwaysContainedItems()
1159 foreach (
string id in splitIds)
1164 bool isEditor =
false;
1170 var spawnedItem =
new Item(prefab, Vector2.Zero,
null);
1171 Inventory.
TryPutItem(spawnedItem,
null, spawnedItem.AllowedSlots, createNetworkEvent:
false);
1172 alwaysContainedItemsSpawned =
true;
1190 base.RemoveComponentSpecific();
1192 inventoryTopSprite?.Remove();
1193 inventoryBackSprite?.Remove();
1194 inventoryBottomSprite?.Remove();
1195 ContainedStateIndicator?.Remove();
1197 if (SubEditorScreen.IsSubEditor())
1212 base.Load(componentElement, usePrefabValues, idRemap, isItemSwap);
1215 string[] itemIdStrings = containedString.Split(
',');
1216 itemIds =
new List<ushort>[itemIdStrings.Length];
1217 for (
int i = 0; i < itemIdStrings.Length; i++)
1219 itemIds[i] ??=
new List<ushort>();
1220 foreach (
string idStr
in itemIdStrings[i].Split(
';'))
1222 if (!
int.TryParse(idStr, out
int id)) {
continue; }
1229 public override XElement
Save(XElement parentElement)
1231 XElement componentElement = base.Save(parentElement);
1236 itemIdStrings[i] =
string.Join(
';', items.Select(it => it.ID.ToString()));
1238 componentElement.Add(
new XAttribute(
"contained",
string.Join(
',', itemIdStrings)));
1240 return componentElement;
void CheckTalents(AbilityEffectType abilityEffectType, AbilityObject abilityObject)
bool HasEquippedItem(Item item, InvSlotType? slotType=null, Func< InvSlotType, bool > predicate=null)
bool CanAccessInventory(Inventory inventory, CharacterInventory.AccessLevel accessLevel=CharacterInventory.AccessLevel.Limited)
Item? SelectedItem
The primary selected item. It can be any device that character interacts with. This excludes items li...
readonly? ContentPackage ContentPackage
string? GetAttributeString(string key, string? def)
int GetAttributeInt(string key, int def)
static EntitySpawner Spawner
virtual Vector2 DrawPosition
static Entity FindEntityByID(ushort ID)
Find an entity based on the ID
void AddItemToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition=null, int? quality=null, Action< Item > onSpawned=null)
static NetworkMember NetworkMember
static GameSession GameSession
static readonly Screen SubEditorScreen
readonly Identifier Identifier
ushort GetOffsetId(XElement element)
virtual bool TryPutItem(Item item, Character user, IEnumerable< InvSlotType > allowedSlots=null, bool createNetworkEvent=true, bool ignoreCondition=false)
If there is room, puts the item in the inventory and returns true, otherwise returns false
void DeleteAllItems()
Deletes all items inside the inventory (and also recursively all items inside the items)
virtual IEnumerable< Item > AllItems
All items contained in the inventory. Stacked items are returned as individual instances....
int FindIndex(Item item)
Find the index of the first slot the item is contained in.
bool AllowSwappingContainedItems
IEnumerable< Item > GetItemsAt(int index)
Get all the item stored in the specified inventory slot. Can return more than one item if the slot co...
IEnumerable< Item > AllItemsMod
All items contained in the inventory. Allows modifying the contents of the inventory while being enum...
bool CanBePut(Item item)
Can the item be put in the inventory (i.e. is there a suitable free slot or a stack the item can be p...
List< Connection > Connections
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...
Inventory ParentInventory
IReadOnlyList< ISerializableEntity > AllPropertyObjects
void Use(float deltaTime, Character user=null, Limb targetLimb=null, Entity useTarget=null, Character userForOnUsedEvent=null)
override Vector2? Position
override void FlipX(bool relativeToSub)
Flip the entity horizontally
void SetContainedItemPositions()
override void FlipY(bool relativeToSub)
Flip the entity vertically
bool TryInteract(Character user, bool ignoreRequiredItems=false, bool forceSelectKey=false, bool forceUseKey=false)
bool HasTag(Identifier tag)
ContentPath ConfigFilePath
override string Name
Note that this is not a LocalizedString instance, just the current name of the item as a string....
float ConditionPercentage
List< ItemComponent > Components
Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, ushort id=Entity.NullEntityID, bool callOnItemLoaded=true)
void SendSignal(string signal, string connectionName)
Entity GetRootInventoryOwner()
static readonly PrefabCollection< ItemPrefab > Prefabs
AbilityItemContainer(Item item)
The base class for components holding the different functionalities of the item
override void Update(float deltaTime, Camera cam)
bool CanBeContained(ItemPrefab itemPrefab, int index)
bool BlameEquipperForDeath()
float AutoInjectThreshold
readonly ItemInventory Inventory
void OnItemRemoved(Item containedItem)
bool AccessOnlyWhenBroken
int ContainedItemCount
Can be used by status effects
override void Equip(Character character)
bool ShouldBeContained(Item item, out bool isRestrictionsDefined)
bool SpawnWithIdWhenBroken
override void RemoveComponentSpecific()
readonly NamedEvent< ItemContainer > OnContainedItemsChanged
ItemContainer(Item item, ContentXElement element)
bool IsAccessible()
Is the container currently accessible. Use this method for checking the accessibility logic,...
override bool HasRequiredItems(Character character, bool addMessage, LocalizedString msg=null)
bool AllowSwappingContainedItems
override void Move(Vector2 amount, bool ignoreContacts=false)
ImmutableHashSet< Identifier > ContainableItemIdentifiers
void OnItemContained(Item containedItem)
override void OnMapLoaded()
Called when all items have been loaded. Use to initialize connections between items.
string AutoInteractWithContainedTags
bool CanBeContained(ItemPrefab itemPrefab)
bool ShouldBeContained(string[] identifiersOrTags, out bool isRestrictionsDefined)
override bool Combine(Item item, Character user)
override void Load(ContentXElement componentElement, bool usePrefabValues, IdRemap idRemap, bool isItemSwap)
bool CanBeContained(Item item, int index)
bool CanBeContained(Item item)
bool ContainsItemsWithSameIdentifier(Item item)
bool AutoInteractWithContained
int ContainedNonBrokenItemCount
Can be used by status effects
bool QuickUseMovesItemsInside
override void ShallowRemoveComponentSpecific()
override void OnItemLoaded()
Called when all the components of the item have been loaded. Use to initialize connections between co...
void SetContainedItemPositions()
override void FlipX(bool relativeToSub)
override XElement Save(XElement parentElement)
override bool Pick(Character picker)
a Character has picked the item
string ContainableRestrictions
List< RelatedItem > AllSubContainableItems
int GetMaxStackSize(int slotIndex)
override bool Select(Character character)
override void ReceiveSignal(Signal signal, Connection connection)
int? FindSuitableSubContainerIndex(Identifier itemTagOrIdentifier)
Returns the index of the first slot whose restrictions match the specified tag or identifier
void ReloadContainableRestrictions(ContentXElement element)
override void Drop(Character dropper, bool setTransform=true)
a Character has dropped the item
bool AllowAccessWhenDropped
bool hasSignalConnections
int MainContainerCapacity
The capacity of the main container without taking the sub containers into account....
List< RelatedItem > ContainableItems
readonly bool HasSubContainers
bool Locked
Can be used by status effects to lock the inventory
override void UpdateBroken(float deltaTime, Camera cam)
bool RemoveContainedItemsOnDeconstruct
readonly Identifier Identifier
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
bool HasTargetType(TargetType targetType)
void AddNearbyTargets(Vector2 worldPosition, List< ISerializableEntity > targets)
virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target, Vector2? worldPosition=null)
static void RecreateHudTextsIfFocused(params Item[] items)
ActionType
ActionTypes define when a StatusEffect is executed.