public void RecreateSprites() { if (Sprite != null) { Sprite.Remove(); var source = Sprite.SourceElement; Sprite = new Sprite(source, file: GetSpritePath(source, Params.normalSpriteParams)); } if (_deformSprite != null) { _deformSprite.Remove(); var source = _deformSprite.Sprite.SourceElement; _deformSprite = new DeformableSprite(source, filePath: GetSpritePath(source, Params.deformSpriteParams)); } if (DamagedSprite != null) { DamagedSprite.Remove(); var source = DamagedSprite.SourceElement; DamagedSprite = new Sprite(source, file: GetSpritePath(source, Params.damagedSpriteParams)); } for (int i = 0; i < ConditionalSprites.Count; i++) { var conditionalSprite = ConditionalSprites[i]; var source = conditionalSprite.ActiveSprite.SourceElement; conditionalSprite.Remove(); ConditionalSprites[i] = new ConditionalSprite(source, character, file: GetSpritePath(source, null)); } for (int i = 0; i < DecorativeSprites.Count; i++) { var decorativeSprite = DecorativeSprites[i]; decorativeSprite.Remove(); var source = decorativeSprite.Sprite.SourceElement; DecorativeSprites[i] = new DecorativeSprite(source, file: GetSpritePath(source, Params.decorativeSpriteParams[i])); } }
public void UpdateSpriteStates(float deltaTime) { DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches); foreach (int spriteGroup in Prefab.DecorativeSpriteGroups.Keys) { for (int i = 0; i < Prefab.DecorativeSpriteGroups[spriteGroup].Count; i++) { var decorativeSprite = Prefab.DecorativeSpriteGroups[spriteGroup][i]; if (decorativeSprite == null) { continue; } if (spriteGroup > 0) { int activeSpriteIndex = ID % Prefab.DecorativeSpriteGroups[spriteGroup].Count; if (i != activeSpriteIndex) { spriteAnimState[decorativeSprite].IsActive = false; continue; } } //check if the sprite is active (whether it should be drawn or not) var spriteState = spriteAnimState[decorativeSprite]; spriteState.IsActive = true; foreach (PropertyConditional conditional in decorativeSprite.IsActiveConditionals) { if (!ConditionalMatches(conditional)) { spriteState.IsActive = false; break; } } if (!spriteState.IsActive) { continue; } //check if the sprite should be animated bool animate = true; foreach (PropertyConditional conditional in decorativeSprite.AnimationConditionals) { if (!ConditionalMatches(conditional)) { animate = false; break; } } if (!animate) { continue; } spriteState.OffsetState += deltaTime; spriteState.RotationState += deltaTime; } } }
private static StructurePrefab Load(XElement element, bool allowOverride, ContentFile file) { StructurePrefab sp = new StructurePrefab { originalName = element.GetAttributeString("name", ""), FilePath = file.Path, ContentPackage = file.ContentPackage }; sp.name = sp.originalName; sp.ConfigElement = element; sp.identifier = element.GetAttributeString("identifier", ""); var parentType = element.Parent?.GetAttributeString("prefabtype", "") ?? string.Empty; string nameIdentifier = element.GetAttributeString("nameidentifier", ""); string descriptionIdentifier = element.GetAttributeString("descriptionidentifier", ""); if (string.IsNullOrEmpty(sp.originalName)) { if (string.IsNullOrEmpty(nameIdentifier)) { sp.name = TextManager.Get("EntityName." + sp.identifier, true) ?? string.Empty; } else { sp.name = TextManager.Get("EntityName." + nameIdentifier, true) ?? string.Empty; } } if (string.IsNullOrEmpty(sp.name)) { sp.name = TextManager.Get("EntityName." + sp.identifier, returnNull: true) ?? $"Not defined ({sp.identifier})"; } sp.Tags = new HashSet <string>(); string joinedTags = element.GetAttributeString("tags", ""); if (string.IsNullOrEmpty(joinedTags)) { joinedTags = element.GetAttributeString("Tags", ""); } foreach (string tag in joinedTags.Split(',')) { sp.Tags.Add(tag.Trim().ToLowerInvariant()); } if (element.Attribute("ishorizontal") != null) { sp.IsHorizontal = element.GetAttributeBool("ishorizontal", false); } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) { case "sprite": sp.sprite = new Sprite(subElement, lazyLoad: true); if (subElement.Attribute("sourcerect") == null) { DebugConsole.ThrowError("Warning - sprite sourcerect not configured for structure \"" + sp.name + "\"!"); } #if CLIENT if (subElement.GetAttributeBool("fliphorizontal", false)) { sp.sprite.effects = SpriteEffects.FlipHorizontally; } if (subElement.GetAttributeBool("flipvertical", false)) { sp.sprite.effects = SpriteEffects.FlipVertically; } #endif sp.canSpriteFlipX = subElement.GetAttributeBool("canflipx", true); sp.canSpriteFlipY = subElement.GetAttributeBool("canflipy", true); if (subElement.Attribute("name") == null && !string.IsNullOrWhiteSpace(sp.Name)) { sp.sprite.Name = sp.Name; } sp.sprite.EntityID = sp.identifier; break; case "backgroundsprite": sp.BackgroundSprite = new Sprite(subElement, lazyLoad: true); if (subElement.Attribute("sourcerect") == null && sp.sprite != null) { sp.BackgroundSprite.SourceRect = sp.sprite.SourceRect; sp.BackgroundSprite.size = sp.sprite.size; sp.BackgroundSprite.size.X *= sp.sprite.SourceRect.Width; sp.BackgroundSprite.size.Y *= sp.sprite.SourceRect.Height; sp.BackgroundSprite.RelativeOrigin = subElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f)); } #if CLIENT if (subElement.GetAttributeBool("fliphorizontal", false)) { sp.BackgroundSprite.effects = SpriteEffects.FlipHorizontally; } if (subElement.GetAttributeBool("flipvertical", false)) { sp.BackgroundSprite.effects = SpriteEffects.FlipVertically; } sp.BackgroundSpriteColor = subElement.GetAttributeColor("color", Color.White); #endif break; case "decorativesprite": #if CLIENT string decorativeSpriteFolder = ""; if (!subElement.GetAttributeString("texture", "").Contains("/")) { decorativeSpriteFolder = Path.GetDirectoryName(file.Path); } int groupID = 0; DecorativeSprite decorativeSprite = null; if (subElement.Attribute("texture") == null) { groupID = subElement.GetAttributeInt("randomgroupid", 0); } else { decorativeSprite = new DecorativeSprite(subElement, decorativeSpriteFolder, lazyLoad: true); sp.DecorativeSprites.Add(decorativeSprite); groupID = decorativeSprite.RandomGroupID; } if (!sp.DecorativeSpriteGroups.ContainsKey(groupID)) { sp.DecorativeSpriteGroups.Add(groupID, new List <DecorativeSprite>()); } sp.DecorativeSpriteGroups[groupID].Add(decorativeSprite); #endif break; } } if (string.Equals(parentType, "wrecked", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrEmpty(sp.Name)) { sp.name = TextManager.GetWithVariable("wreckeditemformat", "[name]", sp.name); } } string categoryStr = element.GetAttributeString("category", "Structure"); if (!Enum.TryParse(categoryStr, true, out MapEntityCategory category)) { category = MapEntityCategory.Structure; } sp.Category = category; if (category.HasFlag(MapEntityCategory.Legacy)) { if (string.IsNullOrWhiteSpace(sp.identifier)) { sp.identifier = "legacystructure_" + sp.name.ToLowerInvariant().Replace(" ", ""); } } sp.Aliases = (element.GetAttributeStringArray("aliases", null) ?? element.GetAttributeStringArray("Aliases", new string[0])).ToHashSet(); string nonTranslatedName = element.GetAttributeString("name", null) ?? element.Name.ToString(); sp.Aliases.Add(nonTranslatedName.ToLowerInvariant()); SerializableProperty.DeserializeProperties(sp, element); if (sp.Body) { sp.Tags.Add("wall"); } if (string.IsNullOrEmpty(sp.Description)) { if (!string.IsNullOrEmpty(descriptionIdentifier)) { sp.Description = TextManager.Get("EntityDescription." + descriptionIdentifier, returnNull: true) ?? string.Empty; } else if (string.IsNullOrEmpty(nameIdentifier)) { sp.Description = TextManager.Get("EntityDescription." + sp.identifier, returnNull: true) ?? string.Empty; } else { sp.Description = TextManager.Get("EntityDescription." + nameIdentifier, true) ?? string.Empty; } } //backwards compatibility if (element.Attribute("size") == null) { sp.size = Vector2.Zero; if (element.Attribute("width") == null && element.Attribute("height") == null) { sp.size.X = sp.sprite.SourceRect.Width; sp.size.Y = sp.sprite.SourceRect.Height; } else { sp.size.X = element.GetAttributeFloat("width", 0.0f); sp.size.Y = element.GetAttributeFloat("height", 0.0f); } } //backwards compatibility if (categoryStr.Equals("Thalamus", StringComparison.OrdinalIgnoreCase)) { sp.Category = MapEntityCategory.Wrecked; sp.Subcategory = "Thalamus"; } if (string.IsNullOrEmpty(sp.identifier)) { DebugConsole.ThrowError( "Structure prefab \"" + sp.name + "\" has no identifier. All structure prefabs have a unique identifier string that's used to differentiate between items during saving and loading."); } Prefabs.Add(sp, allowOverride); return(sp); }
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); }
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); } }
partial void InitProjSpecific(XElement element) { for (int i = 0; i < Params.decorativeSpriteParams.Count; i++) { var param = Params.decorativeSpriteParams[i]; var decorativeSprite = new DecorativeSprite(param.Element, file: GetSpritePath(param.Element, param)); DecorativeSprites.Add(decorativeSprite); int groupID = decorativeSprite.RandomGroupID; if (!DecorativeSpriteGroups.ContainsKey(groupID)) { DecorativeSpriteGroups.Add(groupID, new List <DecorativeSprite>()); } DecorativeSpriteGroups[groupID].Add(decorativeSprite); spriteAnimState.Add(decorativeSprite, new SpriteState()); } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "sprite": Sprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.normalSpriteParams)); break; case "damagedsprite": DamagedSprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.damagedSpriteParams)); break; case "conditionalsprite": var conditionalSprite = new ConditionalSprite(subElement, character, file: GetSpritePath(subElement, null)); ConditionalSprites.Add(conditionalSprite); if (conditionalSprite.DeformableSprite != null) { CreateDeformations(subElement.GetChildElement("deformablesprite")); } break; case "deformablesprite": _deformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement, Params.deformSpriteParams)); CreateDeformations(subElement); break; case "lightsource": LightSource = new LightSource(subElement); InitialLightSourceColor = LightSource.Color; break; } void CreateDeformations(XElement e) { foreach (XElement animationElement in e.GetChildElements("spritedeformation")) { int sync = animationElement.GetAttributeInt("sync", -1); SpriteDeformation deformation = null; if (sync > -1) { // if the element is marked with the sync attribute, use a deformation of the same type with the same sync value, if there is one already. string typeName = animationElement.GetAttributeString("type", "").ToLowerInvariant(); deformation = ragdoll.Limbs .Where(l => l != null) .SelectMany(l => l.Deformations) .Where(d => d.TypeName == typeName && d.Sync == sync) .FirstOrDefault(); } if (deformation == null) { deformation = SpriteDeformation.Load(animationElement, character.SpeciesName); if (deformation != null) { ragdoll.SpriteDeformations.Add(deformation); } } if (deformation != null) { Deformations.Add(deformation); } } } } }