Example #1
0
        public ItemPrefab(XElement element, string filePath)
        {
            configFile    = filePath;
            ConfigElement = element;

            name = element.GetAttributeString("name", "");
            if (name == "")
            {
                DebugConsole.ThrowError("Unnamed item in " + filePath + "!");
            }

            DebugConsole.Log("    " + name);

            string aliases = element.GetAttributeString("aliases", "");

            if (!string.IsNullOrWhiteSpace(aliases))
            {
                Aliases = aliases.Split(',');
            }

            MapEntityCategory category;

            if (!Enum.TryParse(element.GetAttributeString("category", "Misc"), true, out category))
            {
                category = MapEntityCategory.Misc;
            }
            Category = category;

            Triggers         = new List <Rectangle>();
            DeconstructItems = new List <DeconstructItem>();
            DeconstructTime  = 1.0f;

            Tags = new List <string>();
            Tags.AddRange(element.GetAttributeString("tags", "").Split(','));

            SerializableProperty.DeserializeProperties(this, element);

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "sprite":
                    string spriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        spriteFolder = Path.GetDirectoryName(filePath);
                    }

                    canSpriteFlipX = subElement.GetAttributeBool("canflipx", true);

                    sprite = new Sprite(subElement, spriteFolder);
                    if (subElement.Attribute("sourcerect") == null)
                    {
                        DebugConsole.ThrowError("Warning - sprite sourcerect not configured for item \"" + Name + "\"!");
                    }
                    size = sprite.size;
                    break;

#if CLIENT
                case "brokensprite":
                    string brokenSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        brokenSpriteFolder = Path.GetDirectoryName(filePath);
                    }

                    var brokenSprite = new BrokenItemSprite(
                        new Sprite(subElement, brokenSpriteFolder),
                        subElement.GetAttributeFloat("maxcondition", 0.0f),
                        subElement.GetAttributeBool("fadein", false));

                    int spriteIndex = 0;
                    for (int i = 0; i < BrokenSprites.Count && BrokenSprites[i].MaxCondition < brokenSprite.MaxCondition; i++)
                    {
                        spriteIndex = i;
                    }
                    BrokenSprites.Insert(spriteIndex, brokenSprite);
                    break;
#endif
                case "deconstruct":
                    DeconstructTime = subElement.GetAttributeFloat("time", 10.0f);

                    foreach (XElement deconstructItem in subElement.Elements())
                    {
                        string deconstructItemName = deconstructItem.GetAttributeString("name", "not found");
                        //minCondition does <= check, meaning that below or equeal to min condition will be skipped.
                        float minCondition = deconstructItem.GetAttributeFloat("mincondition", -0.1f);
                        //maxCondition does > check, meaning that above this max the deconstruct item will be skipped.
                        float maxCondition = deconstructItem.GetAttributeFloat("maxcondition", 1.0f);
                        //Condition of item on creation
                        float outCondition = deconstructItem.GetAttributeFloat("outcondition", 1.0f);

                        DeconstructItems.Add(new DeconstructItem(deconstructItemName, minCondition, maxCondition, outCondition));
                    }

                    break;

                case "trigger":
                    Rectangle trigger = new Rectangle(0, 0, 10, 10);

                    trigger.X = subElement.GetAttributeInt("x", 0);
                    trigger.Y = subElement.GetAttributeInt("y", 0);

                    trigger.Width  = subElement.GetAttributeInt("width", 0);
                    trigger.Height = subElement.GetAttributeInt("height", 0);

                    Triggers.Add(trigger);

                    break;
                }
            }

            List.Add(this);
        }
Example #2
0
        public ItemPrefab(XElement element, string filePath, bool allowOverriding)
        {
            FilePath      = filePath;
            ConfigElement = element;

            originalName = element.GetAttributeString("name", "");
            name         = originalName;
            identifier   = element.GetAttributeString("identifier", "");

            if (!Enum.TryParse(element.GetAttributeString("category", "Misc"), true, out MapEntityCategory category))
            {
                category = MapEntityCategory.Misc;
            }
            Category = category;

            var parentType = element.Parent?.GetAttributeString("itemtype", "") ?? string.Empty;

            //nameidentifier can be used to make multiple items use the same names and descriptions
            string nameIdentifier = element.GetAttributeString("nameidentifier", "");

            //works the same as nameIdentifier, but just replaces the description
            string descriptionIdentifier = element.GetAttributeString("descriptionidentifier", "");

            if (string.IsNullOrEmpty(originalName))
            {
                if (string.IsNullOrEmpty(nameIdentifier))
                {
                    name = TextManager.Get("EntityName." + identifier, true) ?? string.Empty;
                }
                else
                {
                    name = TextManager.Get("EntityName." + nameIdentifier, true) ?? string.Empty;
                }
            }
            else if (Category.HasFlag(MapEntityCategory.Legacy))
            {
                // Legacy items use names as identifiers, so we have to define them in the xml. But we also want to support the translations. Therefore
                if (string.IsNullOrEmpty(nameIdentifier))
                {
                    name = TextManager.Get("EntityName." + identifier, true) ?? originalName;
                }
                else
                {
                    name = TextManager.Get("EntityName." + nameIdentifier, true) ?? originalName;
                }

                if (string.IsNullOrWhiteSpace(identifier))
                {
                    identifier = GenerateLegacyIdentifier(originalName);
                }
            }

            if (string.Equals(parentType, "wrecked", StringComparison.OrdinalIgnoreCase))
            {
                if (!string.IsNullOrEmpty(name))
                {
                    name = TextManager.GetWithVariable("wreckeditemformat", "[name]", name);
                }
            }

            if (string.IsNullOrEmpty(name))
            {
                DebugConsole.ThrowError($"Unnamed item ({identifier})in {filePath}!");
            }

            DebugConsole.Log("    " + name);

            Aliases = new HashSet <string>
                          (element.GetAttributeStringArray("aliases", null, convertToLowerInvariant: true) ??
                          element.GetAttributeStringArray("Aliases", new string[0], convertToLowerInvariant: true));
            Aliases.Add(originalName.ToLowerInvariant());

            Triggers           = new List <Rectangle>();
            DeconstructItems   = new List <DeconstructItem>();
            FabricationRecipes = new List <FabricationRecipe>();
            DeconstructTime    = 1.0f;

            Tags = new HashSet <string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
            if (!Tags.Any())
            {
                Tags = new HashSet <string>(element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true));
            }

            if (element.Attribute("cargocontainername") != null)
            {
                DebugConsole.ThrowError("Error in item prefab \"" + name + "\" - cargo container should be configured using the item's identifier, not the name.");
            }

            SerializableProperty.DeserializeProperties(this, element);

            if (string.IsNullOrEmpty(Description))
            {
                if (!string.IsNullOrEmpty(descriptionIdentifier))
                {
                    Description = TextManager.Get("EntityDescription." + descriptionIdentifier, true) ?? string.Empty;
                }
                else if (string.IsNullOrEmpty(nameIdentifier))
                {
                    Description = TextManager.Get("EntityDescription." + identifier, true) ?? string.Empty;
                }
                else
                {
                    Description = TextManager.Get("EntityDescription." + nameIdentifier, true) ?? string.Empty;
                }
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "sprite":
                    string spriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        spriteFolder = Path.GetDirectoryName(filePath);
                    }

                    CanSpriteFlipX = subElement.GetAttributeBool("canflipx", true);
                    CanSpriteFlipY = subElement.GetAttributeBool("canflipy", true);

                    sprite = new Sprite(subElement, spriteFolder, lazyLoad: true);
                    if (subElement.Attribute("sourcerect") == null)
                    {
                        DebugConsole.ThrowError("Warning - sprite sourcerect not configured for item \"" + Name + "\"!");
                    }
                    size = sprite.size;

                    if (subElement.Attribute("name") == null && !string.IsNullOrWhiteSpace(Name))
                    {
                        sprite.Name = Name;
                    }
                    sprite.EntityID = identifier;
                    break;

                case "price":
                    if (locationPrices == null)
                    {
                        locationPrices = new Dictionary <string, PriceInfo>();
                    }
                    if (subElement.Attribute("baseprice") != null)
                    {
                        foreach (Tuple <string, PriceInfo> priceInfo in PriceInfo.CreatePriceInfos(subElement, out defaultPrice))
                        {
                            if (priceInfo == null)
                            {
                                continue;
                            }
                            locationPrices.Add(priceInfo.Item1, priceInfo.Item2);
                        }
                    }
                    else if (subElement.Attribute("buyprice") != null)
                    {
                        string locationType = subElement.GetAttributeString("locationtype", "").ToLowerInvariant();
                        locationPrices.Add(locationType, new PriceInfo(subElement));
                    }
                    break;

                case "upgradeoverride":
                {
#if CLIENT
                    var sprites = new List <DecorativeSprite>();
                    foreach (XElement decorSprite in subElement.Elements())
                    {
                        if (decorSprite.Name.ToString().Equals("decorativesprite", StringComparison.OrdinalIgnoreCase))
                        {
                            sprites.Add(new DecorativeSprite(decorSprite));
                        }
                    }
                    UpgradeOverrideSprites.Add(subElement.GetAttributeString("identifier", ""), sprites);
#endif
                    break;
                }

#if CLIENT
                case "inventoryicon":
                {
                    string iconFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        iconFolder = Path.GetDirectoryName(filePath);
                    }
                    InventoryIcon = new Sprite(subElement, iconFolder, lazyLoad: true);
                }
                break;

                case "minimapicon":
                {
                    string iconFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        iconFolder = Path.GetDirectoryName(filePath);
                    }
                    MinimapIcon = new Sprite(subElement, iconFolder, lazyLoad: true);
                }
                break;

                case "brokensprite":
                    string brokenSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        brokenSpriteFolder = Path.GetDirectoryName(filePath);
                    }

                    var brokenSprite = new BrokenItemSprite(
                        new Sprite(subElement, brokenSpriteFolder, lazyLoad: true),
                        subElement.GetAttributeFloat("maxcondition", 0.0f),
                        subElement.GetAttributeBool("fadein", false),
                        subElement.GetAttributePoint("offset", Point.Zero));

                    int spriteIndex = 0;
                    for (int i = 0; i < BrokenSprites.Count && BrokenSprites[i].MaxCondition < brokenSprite.MaxCondition; i++)
                    {
                        spriteIndex = i;
                    }
                    BrokenSprites.Insert(spriteIndex, brokenSprite);
                    break;

                case "decorativesprite":
                    string decorativeSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        decorativeSpriteFolder = Path.GetDirectoryName(filePath);
                    }

                    int groupID = 0;
                    DecorativeSprite decorativeSprite = null;
                    if (subElement.Attribute("texture") == null)
                    {
                        groupID = subElement.GetAttributeInt("randomgroupid", 0);
                    }
                    else
                    {
                        decorativeSprite = new DecorativeSprite(subElement, decorativeSpriteFolder, lazyLoad: true);
                        DecorativeSprites.Add(decorativeSprite);
                        groupID = decorativeSprite.RandomGroupID;
                    }
                    if (!DecorativeSpriteGroups.ContainsKey(groupID))
                    {
                        DecorativeSpriteGroups.Add(groupID, new List <DecorativeSprite>());
                    }
                    DecorativeSpriteGroups[groupID].Add(decorativeSprite);

                    break;

                case "containedsprite":
                    string containedSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        containedSpriteFolder = Path.GetDirectoryName(filePath);
                    }
                    var containedSprite = new ContainedItemSprite(subElement, containedSpriteFolder, lazyLoad: true);
                    if (containedSprite.Sprite != null)
                    {
                        ContainedSprites.Add(containedSprite);
                    }
                    break;
#endif
                case "deconstruct":
                    DeconstructTime  = subElement.GetAttributeFloat("time", 1.0f);
                    AllowDeconstruct = true;
                    foreach (XElement deconstructItem in subElement.Elements())
                    {
                        if (deconstructItem.Attribute("name") != null)
                        {
                            DebugConsole.ThrowError("Error in item config \"" + Name + "\" - use item identifiers instead of names to configure the deconstruct items.");
                            continue;
                        }

                        DeconstructItems.Add(new DeconstructItem(deconstructItem));
                    }

                    break;

                case "fabricate":
                case "fabricable":
                case "fabricableitem":
                    fabricationRecipeElements.Add(subElement);
                    break;

                case "preferredcontainer":
                    var preferredContainer = new PreferredContainer(subElement);
                    if (preferredContainer.Primary.Count == 0 && preferredContainer.Secondary.Count == 0)
                    {
                        DebugConsole.ThrowError($"Error in item prefab {Name}: preferred container has no preferences defined ({subElement.ToString()}).");
                    }
                    else
                    {
                        PreferredContainers.Add(preferredContainer);
                    }
                    break;

                case "trigger":
                    Rectangle trigger = new Rectangle(0, 0, 10, 10)
                    {
                        X      = subElement.GetAttributeInt("x", 0),
                        Y      = subElement.GetAttributeInt("y", 0),
                        Width  = subElement.GetAttributeInt("width", 0),
                        Height = subElement.GetAttributeInt("height", 0)
                    };

                    Triggers.Add(trigger);

                    break;

                case "levelresource":
                    foreach (XElement levelCommonnessElement in subElement.Elements())
                    {
                        string levelName = levelCommonnessElement.GetAttributeString("levelname", "").ToLowerInvariant();
                        if (!LevelCommonness.ContainsKey(levelName))
                        {
                            LevelCommonness.Add(levelName, levelCommonnessElement.GetAttributeFloat("commonness", 0.0f));
                        }
                    }
                    break;

                case "suitabletreatment":
                    if (subElement.Attribute("name") != null)
                    {
                        DebugConsole.ThrowError("Error in item prefab \"" + Name + "\" - suitable treatments should be defined using item identifiers, not item names.");
                    }

                    string treatmentIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();

                    float suitability = subElement.GetAttributeFloat("suitability", 0.0f);

                    treatmentSuitability.Add(treatmentIdentifier, suitability);
                    break;
                }
            }

            // Set the default price in case the prices are defined in the old way
            // with separate Price elements and there is no default price explicitly set
            if (locationPrices != null && locationPrices.Any())
            {
                defaultPrice ??= new PriceInfo(GetMinPrice() ?? 0, false);
            }

            if (sprite == null)
            {
                DebugConsole.ThrowError("Item \"" + Name + "\" has no sprite!");
#if SERVER
                sprite            = new Sprite("", Vector2.Zero);
                sprite.SourceRect = new Rectangle(0, 0, 32, 32);
#else
                sprite = new Sprite(TextureLoader.PlaceHolderTexture, null, null)
                {
                    Origin = TextureLoader.PlaceHolderTexture.Bounds.Size.ToVector2() / 2
                };
#endif
                size            = sprite.size;
                sprite.EntityID = identifier;
            }

            if (string.IsNullOrEmpty(identifier))
            {
                DebugConsole.ThrowError(
                    "Item prefab \"" + name + "\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading.");
            }

            AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList();

            Prefabs.Add(this, allowOverriding);
        }
Example #3
0
        public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
        {
            if (!Visible)
            {
                return;
            }

            Color color = (IsSelected && editing) ? Color.Red : GetSpriteColor();

            if (isHighlighted)
            {
                color = Color.Orange;
            }

            Sprite           activeSprite            = prefab.sprite;
            BrokenItemSprite fadeInBrokenSprite      = null;
            float            fadeInBrokenSpriteAlpha = 0.0f;

            if (condition < 100.0f)
            {
                for (int i = 0; i < prefab.BrokenSprites.Count; i++)
                {
                    if (condition <= prefab.BrokenSprites[i].MaxCondition)
                    {
                        activeSprite = prefab.BrokenSprites[i].Sprite;
                        break;
                    }

                    if (prefab.BrokenSprites[i].FadeIn)
                    {
                        float min = i > 0 ? prefab.BrokenSprites[i].MaxCondition : 0.0f;
                        float max = i < prefab.BrokenSprites.Count - 1 ? prefab.BrokenSprites[i + 1].MaxCondition : 100.0f;
                        fadeInBrokenSpriteAlpha = 1.0f - ((condition - min) / (max - min));
                        if (fadeInBrokenSpriteAlpha > 0.0f && fadeInBrokenSpriteAlpha < 1.0f)
                        {
                            fadeInBrokenSprite = prefab.BrokenSprites[i];
                        }
                    }
                }
            }

            Sprite selectedSprite = prefab.GetActiveSprite(condition);

            if (selectedSprite != null)
            {
                SpriteEffects oldEffects = selectedSprite.effects;
                selectedSprite.effects ^= SpriteEffects;

                float depth = GetDrawDepth();

                if (body == null)
                {
                    if (prefab.ResizeHorizontal || prefab.ResizeVertical || SpriteEffects.HasFlag(SpriteEffects.FlipHorizontally) || SpriteEffects.HasFlag(SpriteEffects.FlipVertically))
                    {
                        selectedSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color);
                        fadeInBrokenSprite?.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color * fadeInBrokenSpriteAlpha, Point.Zero, selectedSprite.Depth - 0.000001f);
                    }
                    else
                    {
                        selectedSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, 0.0f, 1.0f, SpriteEffects.None, depth);
                        fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color * fadeInBrokenSpriteAlpha, 0.0f, 1.0f, SpriteEffects.None, depth - 0.000001f);
                    }
                }
                else if (body.Enabled)
                {
                    var holdable = GetComponent <Holdable>();
                    if (holdable != null && holdable.Picker?.AnimController != null)
                    {
                        if (holdable.Picker.SelectedItems[0] == this)
                        {
                            Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
                            depth = holdLimb.sprite.Depth + 0.000001f;
                            foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
                            {
                                if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null)
                                {
                                    depth = Math.Min(wearableSprite.Sprite.Depth, depth);
                                }
                            }
                        }
                        else if (holdable.Picker.SelectedItems[1] == this)
                        {
                            Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
                            depth = holdLimb.sprite.Depth - 0.000001f;
                            foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
                            {
                                if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null)
                                {
                                    depth = Math.Max(wearableSprite.Sprite.Depth, depth);
                                }
                            }
                        }
                    }
                    body.Draw(spriteBatch, selectedSprite, color, depth);
                    if (fadeInBrokenSprite != null)
                    {
                        body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, depth - 0.000001f);
                    }
                }

                selectedSprite.effects = oldEffects;
            }


            List <IDrawableComponent> staticDrawableComponents = new List <IDrawableComponent>(drawableComponents); //static list to compensate for drawable toggling

            for (int i = 0; i < staticDrawableComponents.Count; i++)
            {
                staticDrawableComponents[i].Draw(spriteBatch, editing);
            }

            if (GameMain.DebugDraw && aiTarget != null)
            {
                aiTarget.Draw(spriteBatch);
            }

            if (!editing || (body != null && !body.Enabled))
            {
                return;
            }

            if (IsSelected || isHighlighted)
            {
                GUI.DrawRectangle(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), Color.Green, false, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));

                foreach (Rectangle t in prefab.Triggers)
                {
                    Rectangle transformedTrigger = TransformTrigger(t);

                    Vector2 rectWorldPos = new Vector2(transformedTrigger.X, transformedTrigger.Y);
                    if (Submarine != null)
                    {
                        rectWorldPos += Submarine.Position;
                    }
                    rectWorldPos.Y = -rectWorldPos.Y;

                    GUI.DrawRectangle(spriteBatch,
                                      rectWorldPos,
                                      new Vector2(transformedTrigger.Width, transformedTrigger.Height),
                                      Color.Green,
                                      false,
                                      0,
                                      (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
                }
            }

            if (!ShowLinks)
            {
                return;
            }

            foreach (MapEntity e in linkedTo)
            {
                GUI.DrawLine(spriteBatch,
                             new Vector2(WorldPosition.X, -WorldPosition.Y),
                             new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
                             Color.Red * 0.3f);
            }
        }
Example #4
0
        public ItemPrefab(XElement element, string filePath, bool allowOverriding)
        {
            configFile    = filePath;
            ConfigElement = element;

            OriginalName = element.GetAttributeString("name", "");
            identifier   = element.GetAttributeString("identifier", "");

            //nameidentifier can be used to make multiple items use the same names and descriptions
            string nameIdentifier = element.GetAttributeString("nameidentifier", "");

            if (string.IsNullOrEmpty(nameIdentifier))
            {
                name = TextManager.Get("EntityName." + identifier, true) ?? OriginalName;
            }
            else
            {
                name = TextManager.Get("EntityName." + nameIdentifier, true) ?? OriginalName;
            }

            if (name == "")
            {
                DebugConsole.ThrowError("Unnamed item in " + filePath + "!");
            }

            DebugConsole.Log("    " + name);

            Aliases = new HashSet <string>
                          (element.GetAttributeStringArray("aliases", null, convertToLowerInvariant: true) ??
                          element.GetAttributeStringArray("Aliases", new string[0], convertToLowerInvariant: true));
            Aliases.Add(OriginalName.ToLowerInvariant());

            if (!Enum.TryParse(element.GetAttributeString("category", "Misc"), true, out MapEntityCategory category))
            {
                category = MapEntityCategory.Misc;
            }
            Category = category;

            Triggers           = new List <Rectangle>();
            DeconstructItems   = new List <DeconstructItem>();
            FabricationRecipes = new List <FabricationRecipe>();
            DeconstructTime    = 1.0f;

            Tags = new HashSet <string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
            if (!Tags.Any())
            {
                Tags = new HashSet <string>(element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true));
            }

            if (element.Attribute("cargocontainername") != null)
            {
                DebugConsole.ThrowError("Error in item prefab \"" + name + "\" - cargo container should be configured using the item's identifier, not the name.");
            }

            SerializableProperty.DeserializeProperties(this, element);

            string translatedDescription = "";

            if (string.IsNullOrEmpty(nameIdentifier))
            {
                translatedDescription = TextManager.Get("EntityDescription." + identifier, true);
            }
            else
            {
                translatedDescription = TextManager.Get("EntityDescription." + nameIdentifier, true);
            }
            if (!string.IsNullOrEmpty(translatedDescription))
            {
                Description = translatedDescription;
            }

            foreach (XElement subElement in element.Elements())
            {
                switch (subElement.Name.ToString().ToLowerInvariant())
                {
                case "sprite":
                    string spriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        spriteFolder = Path.GetDirectoryName(filePath);
                    }

                    canSpriteFlipX = subElement.GetAttributeBool("canflipx", true);
                    canSpriteFlipY = subElement.GetAttributeBool("canflipy", true);

                    sprite = new Sprite(subElement, spriteFolder, lazyLoad: true);
                    if (subElement.Attribute("sourcerect") == null)
                    {
                        DebugConsole.ThrowError("Warning - sprite sourcerect not configured for item \"" + Name + "\"!");
                    }
                    size = sprite.size;

                    if (subElement.Attribute("name") == null && !string.IsNullOrWhiteSpace(Name))
                    {
                        sprite.Name = Name;
                    }
                    sprite.EntityID = identifier;
                    break;

                case "price":
                    string locationType = subElement.GetAttributeString("locationtype", "");
                    if (prices == null)
                    {
                        prices = new Dictionary <string, PriceInfo>();
                    }
                    prices[locationType.ToLowerInvariant()] = new PriceInfo(subElement);
                    break;

#if CLIENT
                case "inventoryicon":
                    string iconFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        iconFolder = Path.GetDirectoryName(filePath);
                    }
                    InventoryIcon = new Sprite(subElement, iconFolder, lazyLoad: true);
                    break;

                case "brokensprite":
                    string brokenSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        brokenSpriteFolder = Path.GetDirectoryName(filePath);
                    }

                    var brokenSprite = new BrokenItemSprite(
                        new Sprite(subElement, brokenSpriteFolder, lazyLoad: true),
                        subElement.GetAttributeFloat("maxcondition", 0.0f),
                        subElement.GetAttributeBool("fadein", false));

                    int spriteIndex = 0;
                    for (int i = 0; i < BrokenSprites.Count && BrokenSprites[i].MaxCondition < brokenSprite.MaxCondition; i++)
                    {
                        spriteIndex = i;
                    }
                    BrokenSprites.Insert(spriteIndex, brokenSprite);
                    break;

                case "decorativesprite":
                    string decorativeSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        decorativeSpriteFolder = Path.GetDirectoryName(filePath);
                    }

                    int groupID = 0;
                    DecorativeSprite decorativeSprite = null;
                    if (subElement.Attribute("texture") == null)
                    {
                        groupID = subElement.GetAttributeInt("randomgroupid", 0);
                    }
                    else
                    {
                        decorativeSprite = new DecorativeSprite(subElement, decorativeSpriteFolder, lazyLoad: true);
                        DecorativeSprites.Add(decorativeSprite);
                        groupID = decorativeSprite.RandomGroupID;
                    }
                    if (!DecorativeSpriteGroups.ContainsKey(groupID))
                    {
                        DecorativeSpriteGroups.Add(groupID, new List <DecorativeSprite>());
                    }
                    DecorativeSpriteGroups[groupID].Add(decorativeSprite);

                    break;

                case "containedsprite":
                    string containedSpriteFolder = "";
                    if (!subElement.GetAttributeString("texture", "").Contains("/"))
                    {
                        containedSpriteFolder = Path.GetDirectoryName(filePath);
                    }
                    var containedSprite = new ContainedItemSprite(subElement, containedSpriteFolder, lazyLoad: true);
                    if (containedSprite.Sprite != null)
                    {
                        ContainedSprites.Add(containedSprite);
                    }
                    break;
#endif
                case "deconstruct":
                    DeconstructTime = subElement.GetAttributeFloat("time", 1.0f);

                    foreach (XElement deconstructItem in subElement.Elements())
                    {
                        if (deconstructItem.Attribute("name") != null)
                        {
                            DebugConsole.ThrowError("Error in item config \"" + Name + "\" - use item identifiers instead of names to configure the deconstruct items.");
                            continue;
                        }

                        DeconstructItems.Add(new DeconstructItem(deconstructItem));
                    }

                    break;

                case "fabricate":
                case "fabricable":
                case "fabricableitem":
                    fabricationRecipeElements.Add(subElement);
                    break;

                case "trigger":
                    Rectangle trigger = new Rectangle(0, 0, 10, 10)
                    {
                        X      = subElement.GetAttributeInt("x", 0),
                        Y      = subElement.GetAttributeInt("y", 0),
                        Width  = subElement.GetAttributeInt("width", 0),
                        Height = subElement.GetAttributeInt("height", 0)
                    };

                    Triggers.Add(trigger);

                    break;

                case "levelresource":
                    foreach (XElement levelCommonnessElement in subElement.Elements())
                    {
                        string levelName = levelCommonnessElement.GetAttributeString("levelname", "").ToLowerInvariant();
                        if (!LevelCommonness.ContainsKey(levelName))
                        {
                            LevelCommonness.Add(levelName, levelCommonnessElement.GetAttributeFloat("commonness", 0.0f));
                        }
                    }
                    break;

                case "suitabletreatment":
                    if (subElement.Attribute("name") != null)
                    {
                        DebugConsole.ThrowError("Error in item prefab \"" + Name + "\" - suitable treatments should be defined using item identifiers, not item names.");
                    }

                    string treatmentIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();

                    List <AfflictionPrefab> matchingAfflictions = AfflictionPrefab.List.FindAll(a => a.Identifier == treatmentIdentifier || a.AfflictionType == treatmentIdentifier);
                    if (matchingAfflictions.Count == 0)
                    {
                        DebugConsole.ThrowError("Error in item prefab \"" + Name + "\" - couldn't define as a treatment, no treatments with the identifier or type \"" + treatmentIdentifier + "\" were found.");
                        continue;
                    }

                    float suitability = subElement.GetAttributeFloat("suitability", 0.0f);
                    foreach (AfflictionPrefab matchingAffliction in matchingAfflictions)
                    {
                        if (matchingAffliction.TreatmentSuitability.ContainsKey(identifier))
                        {
                            matchingAffliction.TreatmentSuitability[identifier] =
                                Math.Max(matchingAffliction.TreatmentSuitability[identifier], suitability);
                        }
                        else
                        {
                            matchingAffliction.TreatmentSuitability.Add(identifier, suitability);
                        }
                    }
                    break;
                }
            }

            if (sprite == null)
            {
                DebugConsole.ThrowError("Item \"" + Name + "\" has no sprite!");
#if SERVER
                sprite            = new Sprite("", Vector2.Zero);
                sprite.SourceRect = new Rectangle(0, 0, 32, 32);
#else
                sprite = new Sprite(TextureLoader.PlaceHolderTexture, null, null)
                {
                    Origin = TextureLoader.PlaceHolderTexture.Bounds.Size.ToVector2() / 2
                };
#endif
                size            = sprite.size;
                sprite.EntityID = identifier;
            }

            if (!category.HasFlag(MapEntityCategory.Legacy) && string.IsNullOrEmpty(identifier))
            {
                DebugConsole.ThrowError(
                    "Item prefab \"" + name + "\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading.");
            }

            AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList();

            if (HandleExisting(identifier, allowOverriding, filePath))
            {
                List.Add(this);
            }
        }
Example #5
0
        public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
        {
            if (!Visible)
            {
                return;
            }
            if (editing && !ShowItems)
            {
                return;
            }

            Color color = isHighlighted ? Color.Orange : GetSpriteColor();

            if (IsSelected && editing)
            {
                color = Color.Lerp(color, Color.Gold, 0.5f);
            }

            Sprite           activeSprite            = prefab.sprite;
            BrokenItemSprite fadeInBrokenSprite      = null;
            float            fadeInBrokenSpriteAlpha = 0.0f;

            if (condition < 100.0f)
            {
                for (int i = 0; i < Prefab.BrokenSprites.Count; i++)
                {
                    if (condition <= Prefab.BrokenSprites[i].MaxCondition)
                    {
                        activeSprite = Prefab.BrokenSprites[i].Sprite;
                        break;
                    }

                    if (Prefab.BrokenSprites[i].FadeIn)
                    {
                        float min = i > 0 ? Prefab.BrokenSprites[i].MaxCondition : 0.0f;
                        float max = i < Prefab.BrokenSprites.Count - 1 ? Prefab.BrokenSprites[i + 1].MaxCondition : 100.0f;
                        fadeInBrokenSpriteAlpha = 1.0f - ((condition - min) / (max - min));
                        if (fadeInBrokenSpriteAlpha > 0.0f && fadeInBrokenSpriteAlpha < 1.0f)
                        {
                            fadeInBrokenSprite = Prefab.BrokenSprites[i];
                        }
                    }
                }
            }

            if (activeSprite != null)
            {
                SpriteEffects oldEffects = activeSprite.effects;
                activeSprite.effects ^= SpriteEffects;
                SpriteEffects oldBrokenSpriteEffects = SpriteEffects.None;
                if (fadeInBrokenSprite != null)
                {
                    oldBrokenSpriteEffects             = fadeInBrokenSprite.Sprite.effects;
                    fadeInBrokenSprite.Sprite.effects ^= SpriteEffects;
                }

                float depth = GetDrawDepth();
                if (body == null)
                {
                    bool flipHorizontal = (SpriteEffects & SpriteEffects.FlipHorizontally) != 0;
                    bool flipVertical   = (SpriteEffects & SpriteEffects.FlipVertically) != 0;

                    if (prefab.ResizeHorizontal || prefab.ResizeVertical)
                    {
                        activeSprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color: color,
                                               depth: depth,
                                               scaleMultiplier: Scale);
                        fadeInBrokenSprite?.Sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color: color * fadeInBrokenSpriteAlpha,
                                                             depth: depth - 0.000001f,
                                                             scaleMultiplier: Scale);
                    }
                    else
                    {
                        activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, SpriteRotation, Scale, activeSprite.effects, depth);
                        fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color * fadeInBrokenSpriteAlpha, SpriteRotation, Scale, activeSprite.effects, depth - 0.000001f);
                    }
                }
                else if (body.Enabled)
                {
                    var holdable = GetComponent <Holdable>();
                    if (holdable != null && holdable.Picker?.AnimController != null)
                    {
                        if (holdable.Picker.SelectedItems[0] == this)
                        {
                            Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
                            depth = holdLimb.ActiveSprite.Depth + 0.000001f;
                            foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
                            {
                                if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null)
                                {
                                    depth = Math.Min(wearableSprite.Sprite.Depth, depth);
                                }
                            }
                        }
                        else if (holdable.Picker.SelectedItems[1] == this)
                        {
                            Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
                            depth = holdLimb.ActiveSprite.Depth - 0.000001f;
                            foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
                            {
                                if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null)
                                {
                                    depth = Math.Max(wearableSprite.Sprite.Depth, depth);
                                }
                            }
                        }
                    }
                    body.Draw(spriteBatch, activeSprite, color, depth, Scale);
                    if (fadeInBrokenSprite != null)
                    {
                        body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, depth - 0.000001f, Scale);
                    }
                }

                activeSprite.effects = oldEffects;
                if (fadeInBrokenSprite != null)
                {
                    fadeInBrokenSprite.Sprite.effects = oldEffects;
                }
            }

            //use a backwards for loop because the drawable components may disable drawing,
            //causing them to be removed from the list
            for (int i = drawableComponents.Count - 1; i >= 0; i--)
            {
                drawableComponents[i].Draw(spriteBatch, editing);
            }

            if (GameMain.DebugDraw)
            {
                aiTarget?.Draw(spriteBatch);
                var containedItems = ContainedItems;
                if (containedItems != null)
                {
                    foreach (Item item in containedItems)
                    {
                        item.AiTarget?.Draw(spriteBatch);
                    }
                }
            }

            if (!editing || (body != null && !body.Enabled))
            {
                return;
            }

            if (IsSelected || IsHighlighted)
            {
                GUI.DrawRectangle(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), Color.Green, false, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));

                foreach (Rectangle t in Prefab.Triggers)
                {
                    Rectangle transformedTrigger = TransformTrigger(t);

                    Vector2 rectWorldPos = new Vector2(transformedTrigger.X, transformedTrigger.Y);
                    if (Submarine != null)
                    {
                        rectWorldPos += Submarine.Position;
                    }
                    rectWorldPos.Y = -rectWorldPos.Y;

                    GUI.DrawRectangle(spriteBatch,
                                      rectWorldPos,
                                      new Vector2(transformedTrigger.Width, transformedTrigger.Height),
                                      Color.Green,
                                      false,
                                      0,
                                      (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
                }
            }

            if (!ShowLinks)
            {
                return;
            }

            foreach (MapEntity e in linkedTo)
            {
                //if (IsSelected || IsHighlighted)
                //{
                //    float offset = 20;
                //    if (AllowedLinks.Count == 0)
                //    {
                //        GUI.DrawString(spriteBatch, new Vector2(WorldPosition.X, -WorldPosition.Y), $"No allowed links for {Prefab.Name}", Color.LightBlue, Color.Black * 0.5f);
                //    }
                //    for (int i = 0; i < AllowedLinks.Count; i++)
                //    {
                //        GUI.DrawString(spriteBatch, new Vector2(WorldPosition.X, -WorldPosition.Y + offset * i), $"Allowed link to {AllowedLinks[i]}", Color.LightBlue, Color.Black * 0.5f);
                //    }
                //}
                bool  isLinkAllowed = prefab.IsLinkAllowed(e.prefab);
                Color lineColor     = Color.Red * 0.5f;
                if (isLinkAllowed)
                {
                    lineColor = e is Item i && (DisplaySideBySideWhenLinked || i.DisplaySideBySideWhenLinked) ? Color.Purple * 0.5f : Color.LightGreen * 0.5f;
                }
                Vector2 from = new Vector2(WorldPosition.X, -WorldPosition.Y);
                Vector2 to   = new Vector2(e.WorldPosition.X, -e.WorldPosition.Y);
                GUI.DrawLine(spriteBatch, from, to, lineColor * 0.25f, width: 3);
                GUI.DrawLine(spriteBatch, from, to, lineColor, width: 1);
                //GUI.DrawString(spriteBatch, from, $"Linked to {e.Name}", lineColor, Color.Black * 0.5f);
            }
        }