3 using System.Collections.Generic;
7 using Microsoft.Xna.Framework;
8 using Microsoft.Xna.Framework.Graphics;
12 internal class VineSprite
15 public Rectangle SourceRect {
get;
private set; }
18 public Vector2 Origin {
get;
private set; }
20 public Vector2 AbsoluteOrigin;
22 public VineSprite(ContentXElement element)
24 SerializableProperty.DeserializeProperties(
this, element);
25 AbsoluteOrigin =
new Vector2(SourceRect.Width * Origin.X, SourceRect.Height * Origin.Y);
29 internal partial class Growable
31 public readonly Dictionary<VineTileType, VineSprite> VineSprites =
new Dictionary<VineTileType, VineSprite>();
32 public readonly List<Sprite> FlowerSprites =
new List<Sprite>();
33 public readonly List<Sprite> LeafSprites =
new List<Sprite>();
35 public Sprite? VineAtlas, DecayAtlas;
37 protected override void RemoveComponentSpecific()
42 foreach (Sprite sprite
in FlowerSprites)
47 foreach (Sprite sprite
in LeafSprites)
53 public void Draw(SpriteBatch spriteBatch, Planter planter, Vector2 offset,
float depth)
55 const float zStep = 0.0001f;
58 foreach (VineTile vine
in Vines)
61 DrawBranch(vine, spriteBatch, planter.Item.DrawPosition + offset, depth, leafDepth);
64 if (GameMain.DebugDraw)
66 foreach (Rectangle rect
in FailedRectangles)
70 wRect.Y -= wRect.Height;
71 GUI.DrawRectangle(spriteBatch, wRect, Color.Red);
76 private void DrawBranch(VineTile vine, SpriteBatch spriteBatch, Vector2 position,
float depth,
float leafDepth)
78 Vector2 pos = position + vine.Position;
81 VineSprite vineSprite = VineSprites[vine.Type];
82 Color color = Decayed ? DeadTint : VineTint;
84 float layer1 = depth + 0.01f,
85 layer2 = depth + 0.02f,
86 layer3 = depth + 0.03f;
88 float scale = VineScale * vine.VineStep;
90 if (VineAtlas !=
null && VineAtlas.Loaded)
92 spriteBatch.Draw(VineAtlas.Texture, pos + vine.offset, vineSprite.SourceRect, color, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer3);
95 if (DecayAtlas !=
null && DecayAtlas.Loaded)
97 spriteBatch.Draw(DecayAtlas.Texture, pos, vineSprite.SourceRect, vine.HealthColor, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer2);
100 if (vine.FlowerConfig.Variant >= 0 && !Decayed)
102 Sprite flowerSprite = FlowerSprites[vine.FlowerConfig.Variant];
103 flowerSprite.Draw(spriteBatch, pos, FlowerTint, flowerSprite.Origin, scale: BaseFlowerScale * vine.FlowerConfig.Scale * vine.FlowerStep, rotate: vine.FlowerConfig.Rotation, depth: layer1);
106 if (vine.LeafConfig.Variant >= 0)
108 Sprite leafSprite = LeafSprites[vine.LeafConfig.Variant];
109 leafSprite.Draw(spriteBatch, pos, Decayed ? DeadTint : LeafTint, leafSprite.Origin, scale: BaseLeafScale * vine.LeafConfig.Scale * vine.FlowerStep, rotate: vine.LeafConfig.Rotation, depth: layer3 + leafDepth);
113 partial
void LoadVines(ContentXElement element)
115 ContentPath vineAtlasPath = element.GetAttributeContentPath(
"vineatlas") ?? ContentPath.Empty;
116 ContentPath decayAtlasPath = element.GetAttributeContentPath(
"decayatlas") ?? ContentPath.Empty;
118 if (!vineAtlasPath.IsNullOrEmpty())
120 VineAtlas =
new Sprite(vineAtlasPath.Value,
Rectangle.Empty);
123 if (!decayAtlasPath.IsNullOrEmpty())
125 DecayAtlas =
new Sprite(decayAtlasPath.Value,
Rectangle.Empty);
128 foreach (var subElement
in element.Elements())
130 switch (subElement.Name.ToString().ToLowerInvariant())
133 VineTileType type = subElement.GetAttributeEnum(
"type", VineTileType.Stem);
134 VineSprites.Add(type,
new VineSprite(subElement));
137 FlowerSprites.Add(
new Sprite(subElement));
140 LeafSprites.Add(
new Sprite(subElement));
144 flowerVariants = FlowerSprites.Count;
145 leafVariants = LeafSprites.Count;
148 foreach (VineTileType type
in Enum.GetValues(typeof(VineTileType)).Cast<VineTileType>())
150 if (!VineSprites.ContainsKey(type))
152 DebugConsole.ThrowError($
"Vine sprite missing from {item.Prefab.Identifier}: {type}");
157 private readonly
object mutex =
new object();
159 public void ClientEventRead(
IReadMessage msg,
float sendingTime)
163 if (startOffset > -1)
166 List<VineTile> tiles =
new List<VineTile>();
167 for (
int i = 0; i < vineCount; i++)
173 Vector2 pos =
new Vector2(posX * VineTile.Size, posY * VineTile.Size);
175 tiles.Add(
new VineTile(
this, pos, vineType, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig)));
181 for (var i = 0; i < vineCount; i++)
183 int index = i + startOffset;
184 if (index >= Vines.Count)
190 VineTile oldVine = Vines[index];
191 VineTile newVine = tiles[i];
192 newVine.GrowthStep = oldVine.GrowthStep;
193 Vines[index] = newVine;
198 UpdateBranchHealth();
202 private void ResetPlanterSize()
206 if (parentItem.GetComponent<Planter>() is { } planter)
208 planter.Item.ResetCachedVisibleSize();
217 public void CreateDebugHUD(Planter planter, PlantSlot slot)
219 Vector2 relativeSize =
new Vector2(0.3f, 0.6f);
220 GUIMessageBox msgBox =
new GUIMessageBox(
item.
Name,
"",
new[] { TextManager.Get(
"applysettingsbutton") }, relativeSize);
222 GUILayoutGroup content =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.85f), msgBox.Content.RectTransform)) { Stretch =
true };
223 GUINumberInput seedInput = CreateIntEntry(
"Random Seed", seed, content.RectTransform);
224 GUINumberInput vineTileSizeInput = CreateIntEntry(
"Vine Tile Size (Global)", VineTile.Size, content.RectTransform);
225 GUINumberInput[] leafScaleRangeInput = CreateMinMaxEntry(
"Leaf Scale Range (Global)",
new []{ MinLeafScale, MaxLeafScale }, 1.5f, content.RectTransform);
226 GUINumberInput[] flowerScaleRangeInput = CreateMinMaxEntry(
"Flower Scale Range (Global)",
new []{ MinFlowerScale, MaxFlowerScale }, 1.5f, content.RectTransform);
227 GUINumberInput vineCountInput = CreateIntEntry(
"Vine Count", MaximumVines, content.RectTransform);
228 GUINumberInput vineScaleInput = CreateFloatEntry(
"Vine Scale", VineScale, content.RectTransform);
229 GUINumberInput flowerInput = CreateIntEntry(
"Flower Quantity", FlowerQuantity, content.RectTransform);
230 GUINumberInput flowerScaleInput = CreateFloatEntry(
"Flower Scale", BaseFlowerScale, content.RectTransform);
231 GUINumberInput leafScaleInput = CreateFloatEntry(
"Leaf Scale", BaseLeafScale, content.RectTransform);
232 GUINumberInput leafProbabilityInput = CreateFloatEntry(
"Leaf Probability", LeafProbability, content.RectTransform);
233 GUINumberInput[] leafTintInputs = CreateMinMaxEntry(
"Leaf Tint",
new []{ LeafTint.R / 255f, LeafTint.G / 255f, LeafTint.B / 255f }, 1.0f, content.RectTransform);
234 GUINumberInput[] flowerTintInputs = CreateMinMaxEntry(
"Flower Tint",
new []{ FlowerTint.R / 255f, FlowerTint.G / 255f, FlowerTint.B / 255f }, 1.0f, content.RectTransform);
235 GUINumberInput[] vineTintInputs = CreateMinMaxEntry(
"Branch Tint",
new []{ VineTint.R / 255f, VineTint.G / 255f, VineTint.B / 255f }, 1.0f, content.RectTransform);
238 msgBox.Buttons[0].OnClicked = (button, o) =>
240 seed = seedInput.IntValue;
241 MaximumVines = vineCountInput.IntValue;
242 FlowerQuantity = flowerInput.IntValue;
243 BaseFlowerScale = flowerScaleInput.FloatValue;
244 VineScale = vineScaleInput.FloatValue;
245 BaseLeafScale = leafScaleInput.FloatValue;
246 LeafProbability = leafProbabilityInput.FloatValue;
247 VineTile.Size = vineTileSizeInput.IntValue;
249 MinFlowerScale = flowerScaleRangeInput[0].FloatValue;
250 MaxFlowerScale = flowerScaleRangeInput[1].FloatValue;
251 MinLeafScale = leafScaleRangeInput[0].FloatValue;
252 MaxLeafScale = leafScaleRangeInput[1].FloatValue;
254 LeafTint =
new Color(leafTintInputs[0].FloatValue, leafTintInputs[1].FloatValue, leafTintInputs[2].FloatValue);
255 FlowerTint =
new Color(flowerTintInputs[0].FloatValue, flowerTintInputs[1].FloatValue, flowerTintInputs[2].FloatValue);
256 VineTint =
new Color(vineTintInputs[0].FloatValue, vineTintInputs[1].FloatValue, vineTintInputs[2].FloatValue);
258 if (FlowerQuantity >= MaximumVines - 1)
260 vineCountInput.Flash(Color.Red);
261 flowerInput.Flash(Color.Red);
265 if (MinFlowerScale > MaxFlowerScale)
267 foreach (GUINumberInput input
in flowerScaleRangeInput)
269 input.Flash(Color.Red);
275 if (MinLeafScale > MaxLeafScale)
277 foreach (GUINumberInput input
in leafScaleRangeInput)
279 input.Flash(Color.Red);
290 GenerateFlowerTiles(flowerRandom);
295 while (MaximumVines > Vines.Count)
303 TryGenerateBranches(planter, slot, random, flowerRandom);
311 foreach (VineTile vineTile
in Vines)
313 vineTile.GrowthStep = 2.0f;
320 private static GUINumberInput CreateIntEntry(
string label,
int defaultValue, RectTransform parent)
322 GUILayoutGroup layout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.08f), parent), isHorizontal:
true);
323 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), layout.RectTransform), label);
324 GUINumberInput input =
new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 1f), layout.RectTransform),
NumberType.Int) { IntValue = defaultValue };
328 private static GUINumberInput CreateFloatEntry(
string label,
float defaultValue, RectTransform parent)
330 GUILayoutGroup layout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.08f), parent), isHorizontal:
true);
331 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), layout.RectTransform), label);
332 GUINumberInput input =
new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 1f), layout.RectTransform),
NumberType.Float) { FloatValue = defaultValue, DecimalsToDisplay = 2 };
336 private static GUINumberInput[] CreateMinMaxEntry(
string label,
float[] values,
float max, RectTransform parent,
float min = 0f)
338 GUILayoutGroup layout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.08f), parent), isHorizontal:
true);
339 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), layout.RectTransform), label);
340 GUINumberInput[] inputs =
new GUINumberInput[values.Length];
341 for (var i = 0; i < values.Length; i++)
343 float value = values[i];
344 GUINumberInput input =
new GUINumberInput(
new RectTransform(
new Vector2(0.5f / values.Length, 1f), layout.RectTransform),
NumberType.Float)
346 FloatValue = value, DecimalsToDisplay = 2,
Inventory ParentInventory
override string Name
Note that this is not a LocalizedString instance, just the current name of the item as a string....
int ReadRangedInteger(int min, int max)
Single ReadRangedSingle(Single min, Single max, int bitCount)