From 5e68917902b8df8100d43407794ac74dc23daf70 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Mon, 8 Jun 2020 22:55:33 +0200 Subject: [PATCH] finished modifiers --- TouchyTickets/Attractions/Attraction.cs | 30 +++++--- .../Attractions/AttractionModifier.cs | 5 +- .../Content/Localization/Localization.json | 12 ++-- TouchyTickets/Content/Textures/Ui.aseprite | Bin 2666 -> 2781 bytes TouchyTickets/Content/Textures/Ui.png | Bin 4206 -> 4375 bytes TouchyTickets/ParkMap.cs | 15 ++-- TouchyTickets/SaveHandler.cs | 7 +- TouchyTickets/Tutorial.cs | 6 ++ TouchyTickets/Ui.cs | 68 +++++++++--------- 9 files changed, 88 insertions(+), 55 deletions(-) diff --git a/TouchyTickets/Attractions/Attraction.cs b/TouchyTickets/Attractions/Attraction.cs index af22666..80818a9 100644 --- a/TouchyTickets/Attractions/Attraction.cs +++ b/TouchyTickets/Attractions/Attraction.cs @@ -30,6 +30,19 @@ namespace TouchyTickets.Attractions { } public float Update(GameTime time, TimeSpan passed, ParkMap map, Point position) { + var genRate = this.GetGenerationRate(map, position); + // apply generation rate to ticket amount + this.ticketPercentage += genRate * (float) passed.TotalSeconds; + var total = this.ticketPercentage.Floor(); + if (total > 0) { + GameImpl.Instance.Tickets += total; + this.ticketPercentage -= total; + } + // return the generation rate per second + return genRate; + } + + public float GetGenerationRate(ParkMap map, Point position) { var genRate = this.Type.GetGenerationRate(); // apply attraction modifiers @@ -43,15 +56,7 @@ namespace TouchyTickets.Attractions { genRate *= 2; if (Upgrade.HauntedHouseModifier.IsActive() && this.Type.Flags.HasFlag(Relaxed) && this.GetSurrounding(map, position, HauntedHouse).Any()) genRate *= 3; - - // apply generation rate to ticket amount - this.ticketPercentage += genRate * (float) passed.TotalSeconds; - var total = this.ticketPercentage.Floor(); - if (total > 0) { - GameImpl.Instance.Tickets += total; - this.ticketPercentage -= total; - } - // return the generation rate per second + return genRate; } @@ -68,7 +73,12 @@ namespace TouchyTickets.Attractions { } public int GetModifierAmount(AttractionModifier modifier) { - return this.Modifiers.Where(m => m.Modifier == modifier).Sum(m => m.Amount); + return this.Modifiers.Where(m => modifier == null || m.Modifier == modifier).Sum(m => m.Amount); + } + + public int GetModifierPrice(AttractionModifier modifier) { + var amount = this.GetModifierAmount(modifier); + return (modifier.InitialPrice * (float) Math.Pow(1 + 0.4F, amount)).Ceil(); } private IEnumerable GetSurrounding(ParkMap map, Point position, AttractionType type) { diff --git a/TouchyTickets/Attractions/AttractionModifier.cs b/TouchyTickets/Attractions/AttractionModifier.cs index 6c97f6f..be81aa4 100644 --- a/TouchyTickets/Attractions/AttractionModifier.cs +++ b/TouchyTickets/Attractions/AttractionModifier.cs @@ -11,8 +11,9 @@ namespace TouchyTickets.Attractions { public static readonly Dictionary Modifiers = new Dictionary(); static AttractionModifier() { - Register(new AttractionModifier("Lubricant", 200, AttractionFlags.Cars, 1.05F, Ui.Texture[0, 4])); - Register(new AttractionModifier("LongerQueue", 1000, AttractionFlags.All, 1.01F, Ui.Texture[1, 4])); + Register(new AttractionModifier("Lubricant", 200, AttractionFlags.Cars, 1.02F, Ui.Texture[0, 4])); + Register(new AttractionModifier("LouderMusic", 500, AttractionFlags.Relaxed, 1.05F, Ui.Texture[2, 4])); + Register(new AttractionModifier("LongerQueue", 1000, AttractionFlags.All, 1.1F, Ui.Texture[1, 4])); } public readonly string Name; diff --git a/TouchyTickets/Content/Localization/Localization.json b/TouchyTickets/Content/Localization/Localization.json index 0c02ea5..f91adaa 100644 --- a/TouchyTickets/Content/Localization/Localization.json +++ b/TouchyTickets/Content/Localization/Localization.json @@ -6,11 +6,8 @@ "ReallyEarnStar": "Cashing in your now would earn you {0}. It will also remove all placed attractions and reset your . Are you sure?", "Yes": "Yes", "Okay": "Okay", - "Add": "Add", "RequiresTickets": "{0} for 1. Maximum {1}.", "AppliedUpgrades": "Active Upgrades", - "Attractions": "Attractions", - "Modifiers": "Modifiers", "Tutorial1": "Hi! Welcome to Touchy Tickets. To start the game, simply tap the ticket booth to sell a . Start by racking up 50!", "Tutorial2": "Great! Now, you can buy your first attraction. Access the menu on the right by swiping and purchase a carousel.", "Tutorial3": "This is your park map. The area inside the fence is what belongs to you. Place the carousel by dragging it to the perfect location and then pressing the button below.", @@ -21,6 +18,9 @@ "Tutorial8": "Alternatively, you can wait a little bit longer and buy multiple at once with more .", "Tutorial9": "Now that you have a , you also have to restart the game. But don't worry: give you the ability to purchase some great permanent upgrades for your attractions.", "Tutorial10": "Now, you can rack up more even faster to earn more to rack up more ... you get the point. Have fun!", + "Tutorial11": "Now that you have a couple of attractions, you can start thinking about purchasing modifiers for them! Swipe to access the modifier menu on the far right and purchase a modifier.", + "Tutorial12": "Different kinds of modifiers can be applied to different attractions. Click on one of your attractions and add the modifier to it.", + "Tutorial13": "Modifiers add a ticket sale multiplier to a single attraction. Each attraction can have an infinite amount of any given modifier, so they're a great way to rack up tickets faster.", "Carousel": "Carousel", "FoodCourt": "Food Court", "FerrisWheel": "Ferris Wheel", @@ -33,9 +33,11 @@ "MirrorHouse": "House of Mirrors", "HauntedHouse": "Haunted House", "Lubricant": "Slip and Slide", - "LubricantDescription": "A ride's cars are lubricated for greater speed. Works on attractions with cars.", + "LubricantDescription": "The wheels of a ride's cars are lubricated for greater speed.", "LongerQueue": "Queuete", - "LongerQueueDescription": "The queue length of an attraction is increased. Works on all attractions.", + "LongerQueueDescription": "The queue length of an attraction is increased.", + "LouderMusic": "Audiophobia", + "LouderMusicDescription": "Relaxed rides play louder music, causing riders to leave faster.", "MapSize1": "Big Park", "MapSize1Description": "Increases your park's buildable area. Existing attractions are not removed.", "MapSize2": "Bigger Park", diff --git a/TouchyTickets/Content/Textures/Ui.aseprite b/TouchyTickets/Content/Textures/Ui.aseprite index b2ca80782255cfd5e41103ee12dd82c17c7125b5..c4eb818f6d9691872a01024451ffbdbcee761645 100644 GIT binary patch delta 2269 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 M07*qoM6N<$f-c!(Q~&?~ delta 3939 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 diff --git a/TouchyTickets/ParkMap.cs b/TouchyTickets/ParkMap.cs index ffa3fad..338cc9e 100644 --- a/TouchyTickets/ParkMap.cs +++ b/TouchyTickets/ParkMap.cs @@ -114,7 +114,7 @@ namespace TouchyTickets { if (MlemGame.Input.GetGesture(GestureType.Tap, out var tap)) { var pos = (camera.ToWorldPos(tap.Position) / Attraction.TileSize).ToPoint(); var attraction = this.GetAttractionAt(pos); - if (attraction != null) { + if (attraction != null && (this.PlacingModifier == null || this.PlacingModifier.IsAffected(attraction))) { // actually select the top left for easy usage later this.SelectedPosition = this.attractions.First(kv => kv.Item2 == attraction).Item1; } else if (GameImpl.Instance.UiSystem.Controls.GetElementUnderPos(tap.Position) == null) { @@ -152,16 +152,21 @@ namespace TouchyTickets { var selected = this.SelectedPosition.Value; var attr = this.GetAttractionAt(selected); foreach (var pos in attr.Type.GetCoveredTiles()) - batch.Draw(batch.GetBlankTexture(), new RectangleF(position + (selected.ToVector2() + pos.ToVector2()) * tileSize, tileSize), Color.Black * 0.15F * alpha); + batch.Draw(batch.GetBlankTexture(), new RectangleF(position + (selected + pos).ToVector2() * tileSize, tileSize), Color.Black * 0.25F * alpha); } // draw attractions - foreach (var (pos, attraction) in this.attractions) + foreach (var (pos, attraction) in this.attractions) { + if (this.SelectedPosition != pos && this.PlacingModifier != null && this.PlacingModifier.IsAffected(attraction)) { + foreach (var offset in attraction.Type.GetCoveredTiles()) + batch.Draw(batch.GetBlankTexture(), new RectangleF(position + (pos + offset).ToVector2() * tileSize, tileSize), Color.Yellow * 0.25F * alpha); + } batch.Draw(attraction.Type.TextureRegion, position + pos.ToVector2() * tileSize, Color.White * alpha, 0, Vector2.Zero, scale, SpriteEffects.None, 0); + } // placing attraction if (this.PlacingAttraction != null) { var placingPos = position + this.PlacingPosition.ToVector2() * tileSize; foreach (var pos in this.PlacingAttraction.Type.GetCoveredTiles()) - batch.Draw(batch.GetBlankTexture(), new RectangleF(placingPos + pos.ToVector2() * tileSize, tileSize), Color.Black * 0.15F * alpha); + batch.Draw(batch.GetBlankTexture(), new RectangleF(placingPos + pos.ToVector2() * tileSize, tileSize), Color.Black * 0.25F * alpha); batch.Draw(this.PlacingAttraction.Type.TextureRegion, placingPos, Color.White * alpha * 0.5F, 0, Vector2.Zero, scale, SpriteEffects.None, 0); } } @@ -197,7 +202,7 @@ namespace TouchyTickets { } public int GetAttractionAmount(AttractionType type) { - return this.attractions.Count(a => a.Item2.Type == type); + return this.attractions.Count(a => type == null || a.Item2.Type == type); } public int GetModifierAmount(AttractionModifier modifier) { diff --git a/TouchyTickets/SaveHandler.cs b/TouchyTickets/SaveHandler.cs index 4d78451..1c6c063 100644 --- a/TouchyTickets/SaveHandler.cs +++ b/TouchyTickets/SaveHandler.cs @@ -13,7 +13,7 @@ namespace TouchyTickets { TypeNameHandling = TypeNameHandling.Auto, Formatting = Formatting.Indented }); - private const int SaveVersion = 2; + private const int SaveVersion = 3; public static void Save(GameImpl game) { var file = GetSaveFile(true); @@ -56,6 +56,11 @@ namespace TouchyTickets { foreach (var upgrade in game.AppliedUpgrades.Intersect(Upgrade.MapSize)) upgrade.OnApplied(); } + // new tutorial additions need to be forced + if (data.SaveVersion <= 2) { + if (game.Tutorial.CurrentStep > 4) + game.Tutorial.CurrentStep = 4; + } return true; } diff --git a/TouchyTickets/Tutorial.cs b/TouchyTickets/Tutorial.cs index e96c6df..9cfb154 100644 --- a/TouchyTickets/Tutorial.cs +++ b/TouchyTickets/Tutorial.cs @@ -8,10 +8,16 @@ namespace TouchyTickets { public class Tutorial { private static readonly Step[] Steps = { + // introduction new Step(g => true, "Tutorial1"), new Step(g => g.Tickets >= AttractionType.Carousel.InitialPrice, "Tutorial2"), new Step(g => g.DrawMap && g.Map.PlacingAttraction?.Type == AttractionType.Carousel, "Tutorial3"), new Step(g => g.Map.GetAttractionAmount(AttractionType.Carousel) > 0, "Tutorial4", "Tutorial5", "Tutorial6"), + // modifier tutorial + new Step(g => g.Map.GetAttractionAmount(null) >= 3, "Tutorial11"), + new Step(g => g.Map.PlacingModifier != null, "Tutorial12"), + new Step(g => g.Map.GetModifierAmount(null) > 0, "Tutorial13"), + // star tutorial new Step(g => g.Tickets >= g.GetStarPrice(), "Tutorial7", "Tutorial8"), new Step(g => g.Stars > 0, "Tutorial9", "Tutorial10") }; diff --git a/TouchyTickets/Ui.cs b/TouchyTickets/Ui.cs index 33064fa..80bab48 100644 --- a/TouchyTickets/Ui.cs +++ b/TouchyTickets/Ui.cs @@ -123,12 +123,7 @@ namespace TouchyTickets { return; var map = GameImpl.Instance.Map; var infoUi = new Group(Anchor.BottomLeft, new Vector2(1)); - infoUi.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => { - if (map.SelectedPosition == null) - return string.Empty; - var attraction = map.GetAttractionAt(map.SelectedPosition.Value); - return string.Join(" ", attraction.Modifiers.Select(m => $"{m.Amount}")); - }, true) {TextScale = 0.15F}); + AddSelectedAttractionInfo(infoUi); infoUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(0.5F, 30), Localization.Get("Back")) { OnPressed = e2 => this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name)) }); @@ -220,14 +215,6 @@ namespace TouchyTickets { IsHidden = true }; foreach (var modifier in AttractionModifier.Modifiers.Values) { - BigInteger price = 0; - - BigInteger CalculatePrice() { - var modAmount = GameImpl.Instance.Map.GetModifierAmount(modifier); - price = (modifier.InitialPrice * (float) Math.Pow(1 + 0.4F, modAmount)).Ceil(); - return price; - } - var button = modifierUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) { SetHeightBasedOnChildren = true, PositionOffset = new Vector2(0, 1), @@ -236,52 +223,52 @@ namespace TouchyTickets { if (this.swipeProgress != 0) return; var map = GameImpl.Instance.Map; + map.PlacingModifier = modifier; var infoUi = new Group(Anchor.BottomLeft, new Vector2(1)); - infoUi.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => { - if (map.SelectedPosition == null) - return string.Empty; - var attraction = map.GetAttractionAt(map.SelectedPosition.Value); - return string.Join(" ", attraction.Modifiers.Select(m => $"{m.Amount}")); - }, true) {TextScale = 0.15F}); + AddSelectedAttractionInfo(infoUi); infoUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(0.5F, 30), Localization.Get("Back")) { OnPressed = e2 => this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name)) }); - infoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 30), Localization.Get("Add")) { + var addButton = infoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 30), string.Empty) { OnPressed = e2 => { if (map.SelectedPosition == null) return; var attraction = map.GetAttractionAt(map.SelectedPosition.Value); - attraction.ApplyModifier(modifier); - - GameImpl.Instance.Tickets -= price; - // if we're out of tickets to buy this modifier, automatically go back - if (GameImpl.Instance.Tickets < CalculatePrice()) - this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name)); + GameImpl.Instance.Tickets -= attraction.GetModifierPrice(map.PlacingModifier); + attraction.ApplyModifier(map.PlacingModifier); }, OnUpdated = (e2, time) => { var disabled = map.SelectedPosition == null; if (!disabled) { var attraction = map.GetAttractionAt(map.SelectedPosition.Value); - disabled = attraction == null || !modifier.IsAffected(attraction); + disabled = attraction == null || !map.PlacingModifier.IsAffected(attraction) || GameImpl.Instance.Tickets < attraction.GetModifierPrice(map.PlacingModifier); } ((Button) e2).IsDisabled = disabled; } }); + addButton.Text.GetTextCallback = p => { + var price = map.PlacingModifier.InitialPrice; + if (map.SelectedPosition != null) { + var attraction = map.GetAttractionAt(map.SelectedPosition.Value); + if (attraction != null && map.PlacingModifier.IsAffected(attraction)) + price = attraction.GetModifierPrice(map.PlacingModifier); + } + return PrettyPrintNumber(price) + ""; + }; // we want this to render below the main ui while it fades away this.uiSystem.Add("ModifierInfo", infoUi).Priority = -100; this.FadeUi(true); - }, - OnAreaUpdated = e => CalculatePrice() + } }); - button.OnUpdated += (e, time) => button.IsDisabled = GameImpl.Instance.Tickets < price; + button.OnUpdated += (e, time) => button.IsDisabled = GameImpl.Instance.Tickets < modifier.InitialPrice; button.AddChild(new Image(Anchor.CenterLeft, new Vector2(0.2F, 40), modifier.Texture) { Padding = new Vector2(4) }); var right = button.AddChild(new Group(Anchor.TopRight, new Vector2(0.8F, 1)) {CanBeMoused = false}); right.AddChild(new Paragraph(Anchor.TopLeft, 1, Localization.Get(modifier.Name), true)); right.AddChild(new Paragraph(Anchor.AutoLeft, 1, Localization.Get(modifier.Name + "Description"), true) {TextScale = 0.08F}); - right.AddChild(new Paragraph(Anchor.AutoRight, 1, p => PrettyPrintNumber(price) + "", true)); + right.AddChild(new Paragraph(Anchor.AutoRight, 1, p => PrettyPrintNumber(modifier.InitialPrice) + "", true)); right.AddChild(new Paragraph(Anchor.BottomLeft, 1, $"x{modifier.Multiplier}", true) {TextScale = 0.08F}); } this.uiSystem.Add("Modifiers", modifierUi); @@ -436,6 +423,23 @@ namespace TouchyTickets { CoroutineHandler.Start(Impl()); } + private static void AddSelectedAttractionInfo(Element element) { + var map = GameImpl.Instance.Map; + element.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => { + if (map.SelectedPosition == null) + return string.Empty; + var attraction = map.GetAttractionAt(map.SelectedPosition.Value); + return string.Join(" ", attraction.Modifiers.Select(m => $"{m.Amount}")); + }, true)); + element.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => { + if (map.SelectedPosition == null) + return string.Empty; + var pos = map.SelectedPosition.Value; + var attraction = map.GetAttractionAt(pos); + return attraction.GetGenerationRate(map, pos).ToString("0.##") + "/s"; + }, true)); + } + private static void PopulateUpgradeList(Element upgradeList) { upgradeList.RemoveChildren(c => !(c is ScrollBar)); var reachedActive = false;