From 39409d3b9660213107083507055b94831e4977ad Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Tue, 2 Jun 2020 12:20:16 +0200 Subject: [PATCH] foundation for productivity modifiers --- TouchyTickets/Attractions/Attraction.cs | 23 ++++++++++++++++-- TouchyTickets/Attractions/AttractionType.cs | 12 ++++------ TouchyTickets/Content/Textures/Ui.aseprite | Bin 1402 -> 1502 bytes TouchyTickets/Content/Textures/Ui.png | Bin 2033 -> 2309 bytes TouchyTickets/GameImpl.cs | 1 - TouchyTickets/ParkMap.cs | 25 ++++++++++---------- TouchyTickets/SaveHandler.cs | 3 +-- TouchyTickets/Ui.cs | 3 +-- TouchyTickets/Upgrade.cs | 15 ++++++------ 9 files changed, 48 insertions(+), 34 deletions(-) diff --git a/TouchyTickets/Attractions/Attraction.cs b/TouchyTickets/Attractions/Attraction.cs index 4b74feb..62a2d97 100644 --- a/TouchyTickets/Attractions/Attraction.cs +++ b/TouchyTickets/Attractions/Attraction.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MLEM.Extensions; +using MLEM.Misc; using MLEM.Startup; using MLEM.Textures; @@ -32,13 +34,30 @@ namespace TouchyTickets.Attractions { } } - public void Update(GameTime time, TimeSpan passed) { - this.ticketPercentage += this.Type.GenerationPerSecond * (float) passed.TotalSeconds; + public float Update(GameTime time, TimeSpan passed, ParkMap map, Point position) { + var genRate = this.Type.GenerationPerSecond; + + if (Upgrade.FoodCourtModifier.IsActive() && this.GetSurrounding(map, position, AttractionType.FoodCourt).Any()) + genRate *= 3; + + this.ticketPercentage += genRate * (float) passed.TotalSeconds; var amount = this.ticketPercentage.Floor(); if (amount > 0) { GameImpl.Instance.Tickets += amount; this.ticketPercentage -= amount; } + // return the generation rate per second + return genRate; + } + + public IEnumerable GetSurrounding(ParkMap map, Point position, AttractionType type) { + foreach (var tile in this.GetCoveredTiles()) { + foreach (var dir in Direction2Helper.Adjacent) { + var other = map.GetAttractionAt(position + tile + dir.Offset()); + if (other != null && other != this && other.Type == type) + yield return other; + } + } } } diff --git a/TouchyTickets/Attractions/AttractionType.cs b/TouchyTickets/Attractions/AttractionType.cs index 642c378..8855c5a 100644 --- a/TouchyTickets/Attractions/AttractionType.cs +++ b/TouchyTickets/Attractions/AttractionType.cs @@ -8,12 +8,9 @@ namespace TouchyTickets.Attractions { public class AttractionType { public static readonly Dictionary Attractions = new Dictionary(); - - static AttractionType() { - Register(new AttractionType("Carousel", new[,] {{true}}, Attraction.Texture[0, 0, 1, 1], 0.5F, 50)); - Register(new AttractionType("FoodCourt", new[,] {{true, true}}, Attraction.Texture[1, 0, 2, 1], 1.1F, 300)); - Register(new AttractionType("FerrisWheel", new[,] {{true, true}, {true, true}}, Attraction.Texture[0, 1, 2, 2], 3.5F, 2000)); - } + public static readonly AttractionType Carousel = Register(new AttractionType("Carousel", new[,] {{true}}, Attraction.Texture[0, 0, 1, 1], 0.5F, 50)); + public static readonly AttractionType FoodCourt = Register(new AttractionType("FoodCourt", new[,] {{true, true}}, Attraction.Texture[1, 0, 2, 1], 1.1F, 300)); + public static readonly AttractionType FerrisWheel = Register(new AttractionType("FerrisWheel", new[,] {{true, true}, {true, true}}, Attraction.Texture[0, 1, 2, 2], 3.5F, 2000)); public readonly string Name; public readonly bool[,] Area; @@ -37,8 +34,9 @@ namespace TouchyTickets.Attractions { return this.create(this); } - private static void Register(AttractionType type) { + private static AttractionType Register(AttractionType type) { Attractions.Add(type.Name, type); + return type; } public delegate Attraction Constructor(AttractionType type); diff --git a/TouchyTickets/Content/Textures/Ui.aseprite b/TouchyTickets/Content/Textures/Ui.aseprite index e8386441131fffd5c5fc27bf25924a958882420a..c8ffca6a9f89e30546104ad58ca929ebbcf94146 100644 GIT binary patch delta 978 zcmV;@11C=-jM-+0$v5Nf`Y`P_Wx-Et!%{qgwZ2@^xgM_S8o!=n#W&09e*_>uxq?v##+u?bT8ZHZ0xRjV~nHbb z$*lGDlRFd9b#L)#U!S}7Z7|BC*5B|v=XCAs@F3;2wtOtAh+FINB7VOmv-E&uhtI+N z_h)-gTJALeuzTFeXSEH)3+Jg>q|aVsi66E99Ew=6`u> zb<>#STov4TL+fwkt+B}OM4N|jKi1m%yDDzp-!>M`ppE%=C9mT=wR*dJZsU+go6q^0 zx^cVw&ApBLwRI`hTlP1vm2FO5llz#qF2(+)oXSv2^(LQFK4mE-?lP4EH$|-fQ0wsD zYJ2R6SzT=PX=$>d&ik%w^Yj^2bAQU9oG4d1#t@!eHKz>9>2mv2mfL)5s!;J~SIsE{ zJ_q;3g|orxotw4_+;#9dxaVhQtm4d&Aq~GChUT>U(KQ@yu_}&HXYa6$n+&*^jq1L?KDR^D(+giQx9T0b( zef~wGq4qb;m&Iobxo`V?F4w!B{cd|ZV??b}VMc(3&ZW<}-?`62m^+`XuV-tB6^c)j zFTfG9ujOH`OAwn&zWeLQEF3>;47^ A4*&oF delta 877 zcmV-z1CspS3;GHHdXWKt0{R58f`htU{< zhp2~9FoHo4(L%8C56B;2W0lI*Mp9U6ZK+@@SZHBqV{2nG@(#Y?@$Su!&F$>W>^=Ch zyR&n*@3ZrLZs7~?jrqst2d2ulPHxTLSi8E$eC(uWk9QCEZE~@L8S=49 zpT>~J4d#CDlKJv++wfzI@qHUJ@qzj8?-wI+c8#BVanf228PnK_iLW;uOKI!PdBObW z`-zeGx@-I~YS}g>xqa(R!m;M@xBIh(1b=po7tEN;nd`1)+n9~rwca?!R`WV%2d8A# z>iX5Ah3I;+d3vnQU40vja;w!hJkL2@eH|X8y!N)wL=|ysHD1T_TQW-zNOt%f-2Z;| z4yENzC(8R9dY1Gv*fnnWoN^;37h5Q|HYX-G?^z+|Bsb4nTYoo= zNsgu9t{Pf>BX5mG-V<#c!tXKHR^O?(d41bhID>Y~@0C1{{oK~u<#QW{+}eE3=ak0n z@;CQ3ey`2TalK`I^R=>#$#b%gY4dWdZ_23&<+R@9bIPYF<;2~ja^R+j^$oRzZ>znz zQ)YLwJEpD0^Xj1t*t)y)pr|xUTQy|J2`76?dQJw#(&ebQu9(!9)B_4%eD9P z9N59#q;lcDySC7%a^R+Dl06q@1m)9&Qgg~c&xxtro?{ev#*!#U>`S@M`R3%x9r8`h z_r1+ECs*!i_jy%sht@@|+)XGor!U@jyM~lHk0t}m)5QL!(=jA4<2ZF*O~o|v?%eJh zn}%DupF00Z z0xYyIea`*PeO@{<0vsWItu4$vh|Q(c`85%x_pYkJdska}SZK7VZ&!^rzn}jHRe-x2 DHjv() diff --git a/TouchyTickets/Content/Textures/Ui.png b/TouchyTickets/Content/Textures/Ui.png index 5c4e6ebb72f68971b3ffba0c03213af81ffefe32..ac06e869fef31b1c6f0563ddea2bbbb8c7c0e7ec 100644 GIT binary patch delta 2101 zcmV-52+H^I4}}ttFnle)#k^8Xc%&QE9;|k3X8MU$Z*0!^4ps z9*!der{c)Ksr>#-%hs=1T{E-T_{>wubhcADd2~_I+1VN=k1m>%YzFQG6*GXsr*)bM z%)0Et=T&cF<9{8Fp6oD7MM0E4{R?G>ha)1Qv!|yaWk&{1RU8Yr z)d)oV{*SHkn_u0idE>8cABt*?K>GC0-$(XF=n6o&vJ4;%+Iq@oQ&uPq{^wpAjCbBx z8ABI`A|kgR5%JC&E8~^lp3Q&W`PN9q;7`;2&d%0&;D6y4A|m3;^M8(9SKvkx5gGz0 zkPn8!{`pTI`d+@mv2RoNMwgXl0UMurD%t*8cP#5^%Vz+WhbPN!cv(+dL=VGz3tR0W_??KSf#Tj6k&vAbsjbM7+B<6VJUg81L@Q zl%@a22Y;4CM8uP8CZe;mH72gSR~GmYx!_OhMwB0iyG=_(@yLHf`%Ekhw z$^e%2w8iD&$^5obH{dUS=t$B=AR-s=g`bZPEQu}K#y$DrTlowiJ3Ji!dt~(6z0q4W zI-;Rvr$?^FhLRzHGy`~b`%t{Svp0q=o{xy$*nj!fNNj(tyW+Oe7{Hco<1J}-APxA! z20`#cv3vt??84{K`$$J*$3|<_Z-`?hQ-Zl*PN(+j-Ihy7{|le?g;~MLqcZ?C?_X29(HHn8VcSUw$qTx$} z(|@ObX{w(#0ucuPpiq7#VBu8V%Ui!F+RoIaYx5gx#|M^F?B{RUHr|pR18yl>3LFtd zPxiuWpq3rGd*?miOKsUU-cqffU+Wm$t?~^(X}>&Gm<5yudD=LnU4lLRE8^0%mV9}- zUsyLHB0DkBz<&ZTQ~3s<+S`AHL0#DI-+$A;qNs7$)4wABxv&edygkW(H`TdBDh|z{ z;ut_Z3ZMAtej4zlgM+1Yf#y(g44{(IATA8@^jK*YknX41LakW?VE*N&0V5)Me{yRb zz@=*~vAjLWZ!49R9*Zb$7%J7fa5ahVoX;&k@C!k(u<{Fm)~{I|2habz;7}45u74J8 zE0q-=i->~#YV~qs00shK;T0_ferULBA@2p4XGL!VuIagd-Y$IXf(!r_TE*W3m=F5@ zu<(k4@X3`AB$@9&QdVi`@|EaaRy{kYcDz#g;HRI(@v~nFerN(^KM6K;`AUqAjg?ib zR94UN!t$kE#u%WPlr;ctZHptuB7fSJ)%OlSy(TXY<_+OBc6CN~Ta^8!(sQTR0v1+FL@pp7 zdvL{+>-`&LX;)XAx%fq#9e?&S-LQ~~#sIvm19z8v1F*Ecj(I%bj*?HoSN3!yPyFD~ zdAaCE|2Zf9hbB-Ig!45xC-|W`6paBa?`og(ae&dWu{b+CKBw0J>Qnh`z=)Wfyk2$Q zzSglR>v$UwnnuN?z!4Eclh>=R38-~!sydbeL-VM)6u8#X-FlYwT7UWr&8=z|pwv`p zf8AXMT>xkrWeq^h6n(1Tt#w@B!|mnZ+O^5SwQH^0hdWf&`S{Yn-+bc4jOXqTWHR}4 z{bF#?8USb#6@#&V)v6>SVtGeLL_}N~&&}I!J$-uG!FwQ+Nq)3-YeYmW?e30$?b@Xg zfZIX;s#Qta7|g_hOn)XxKKUd$kjdo#()~u>ConT*PvXr#`*GFaoS2x54~~9R*VFqz zCX;MFbSMr!`)sW1>x+np(UFn(xW7Nv_4UaFpb6w>0S>NRo232x$jI#P9GJC55#` zJbXAJA~G8`O#e=ShHEJeK8u!Q}qV_%dfxQ5)pzPnp9a}ZhZQQnuB{&O#_w&KX99x?z;eo z_U}*jy!oa@K5(0;x)eAa=u1sE?FX7)*?$cdksA{z91Y>0D)=KJ1V7wiX8SIaAqTjV fFb4=2%$NTINg7qu=@yAx00000NkvXXu0mjfZR0KZ delta 1830 zcmV+>2if?A67dg^Fn7kB835qdj)SqirnLd#h5%Jl!GT(eoI~3K zhe#k*<(eZBmmH{+K+;n$6g6CWBB4YoQhTWsDHpCeQHetjoIt4z2T*@Piir{S0`{7X z`P&|rSdGoS@qgCt(sDfP?7zRwd>*hm zdKz6gG`hd754t#hy{-3a#kEV_rJud~T%!XGbk`P~cx!j*(CGdshBQbcG7Af*xv>GAn5cmAkS z;qr^rz1?NCS-|0g2TCVD9*V8Qy_F1LIzM0cgSQU%MnrW6kPiHai0yB_AH@e>MnpuR zFjw{cLZO^lXb7Mt18CcLf044<6@f+>K+@|+M11l2-Z=8X&G_Q;y>;pTmGQoahdT)evBO;F~DS&cvxRBb5q& z`0Zrfmrk7-i4Tw6jcxsn_t=~|Gm`n;iHD`wIXxJKVzKR8gOlFBHq}oWfe4d-kXG3V zn15cX`|#M^s^d~kJzCjVyE5LFInFADdSg<`Rd{{>*FDh)uR zxBt>XogVj}JHMl|O+YkJOAXr_MjX;M+_s50X|4dyf#l*w(F{`ZlT12GI8`Ue%0hkDc)qhvD z6?kWUa5aAmu)?a|1{@v!;fg)@@`MZkR$J!Z16T>h|FHV1g7BR^+e>?YysNI#;>bDH$VyHLj{w0!oC(i;_S64(iAb;}4jz#zTx678n!T8UeyKyV;&ve6T zs+t4vvJPx4l?Gr-e+%n)z<;_@Nx}CF50u{i>FyPI=-2=HR{9SepehJgYI08SLuaU( z1K2j$zwGk>GqbaCD?hia&j4DJ{Wf4k%+Eh=xNhI<+M;#54G0}0b1QH}#N_qKQ0;KJBgDH-RNj_l8_{g3&I-L9Z?SI+TJ|r_0zq7Lh!@-P#469-+jC3xZW}# zY!KcBfc356R^VhCa6;M->rcagPB#LAA2uNG0ssI2000000FyZgv>N~b0I*j4AGB-D U*cWzNyZ`_I07*qoM6N<$g4!*dKL7v# diff --git a/TouchyTickets/GameImpl.cs b/TouchyTickets/GameImpl.cs index 5a80ebd..b702fcb 100644 --- a/TouchyTickets/GameImpl.cs +++ b/TouchyTickets/GameImpl.cs @@ -8,7 +8,6 @@ using MLEM.Extensions; using MLEM.Font; using MLEM.Startup; using TouchyTickets.Attractions; -using TouchyTickets.Upgrades; namespace TouchyTickets { public class GameImpl : MlemGame { diff --git a/TouchyTickets/ParkMap.cs b/TouchyTickets/ParkMap.cs index 659d442..7463100 100644 --- a/TouchyTickets/ParkMap.cs +++ b/TouchyTickets/ParkMap.cs @@ -25,6 +25,7 @@ namespace TouchyTickets { private readonly List<(Point, Attraction)> attractions = new List<(Point, Attraction)>(); private readonly Dictionary treePositions = new Dictionary(); private readonly Dictionary fencePositions = new Dictionary(); + private readonly Attraction[,] attractionGrid; public float TicketsPerSecond { get; private set; } public Attraction PlacingAttraction; @@ -34,6 +35,7 @@ namespace TouchyTickets { public ParkMap(int width, int height) { this.Width = width; this.Height = height; + this.attractionGrid = new Attraction[width, height]; // set up trees var random = new Random(); @@ -65,9 +67,9 @@ namespace TouchyTickets { public void Update(GameTime time, TimeSpan passed) { var tickets = 0F; - foreach (var (_, attraction) in this.attractions) { - attraction.Update(time, passed); - tickets += attraction.Type.GenerationPerSecond; + foreach (var (pos, attraction) in this.attractions) { + var genPerSecond = attraction.Update(time, passed, this, pos); + tickets += genPerSecond; } this.TicketsPerSecond = tickets; @@ -150,25 +152,24 @@ namespace TouchyTickets { } public void Place(Point position, Attraction attraction) { - this.attractions.RemoveAll(pa => pa.Item1 == position); + foreach (var (x, y) in attraction.GetCoveredTiles()) + this.attractionGrid[position.X + x, position.Y + y] = attraction; this.attractions.Add((position, attraction)); } public Attraction GetAttractionAt(Point position) { - foreach (var (pos, attraction) in this.attractions) { - if (attraction.GetCoveredTiles().Any(p => pos + p == position)) - return attraction; - } - return null; + return this.attractionGrid[position.X, position.Y]; } public int GetAttractionAmount(AttractionType type) { return this.attractions.Count(a => a.Item2.Type == type); } - public void CopyAttractionsFrom(ParkMap other) { - foreach (var (pos, attraction) in other.attractions) - this.Place(pos, attraction); + public ParkMap Copy(int? newWidth = null, int? newHeight = null) { + var newMap = new ParkMap(newWidth ?? this.Width, newHeight ?? this.Height); + foreach (var (pos, attraction) in this.attractions) + newMap.Place(pos, attraction); + return newMap; } } diff --git a/TouchyTickets/SaveHandler.cs b/TouchyTickets/SaveHandler.cs index 3e3a633..3b1eccb 100644 --- a/TouchyTickets/SaveHandler.cs +++ b/TouchyTickets/SaveHandler.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Numerics; using Newtonsoft.Json; -using TouchyTickets.Upgrades; namespace TouchyTickets { public static class SaveHandler { @@ -40,7 +39,7 @@ namespace TouchyTickets { var data = Serializer.Deserialize(stream); game.Tickets = data.Tickets; game.LastUpdate = data.LastUpdate; - game.Map = data.Map; + game.Map = data.Map.Copy(); game.Stars = data.Stars; game.TimesRestarted = data.TimesRestarted; game.AppliedUpgrades.Clear(); diff --git a/TouchyTickets/Ui.cs b/TouchyTickets/Ui.cs index 6ea83e3..330f0a2 100644 --- a/TouchyTickets/Ui.cs +++ b/TouchyTickets/Ui.cs @@ -16,7 +16,6 @@ using MLEM.Textures; using MLEM.Ui; using MLEM.Ui.Elements; using TouchyTickets.Attractions; -using TouchyTickets.Upgrades; namespace TouchyTickets { public class Ui { @@ -196,7 +195,7 @@ namespace TouchyTickets { }); button.OnUpdated += (e, time) => { // we want to hide if we're active, or if we still need a dependency to be active - button.IsHidden = Upgrade.IsActive(upgrade) || upgrade.Dependencies.Any(u => !Upgrade.IsActive(u)); + button.IsHidden = upgrade.IsActive() || upgrade.Dependencies.Any(u => !u.IsActive()); button.IsDisabled = GameImpl.Instance.Stars < upgrade.Price; }; var center = button.AddChild(new Group(Anchor.Center, new Vector2(0.8F, 1), false) {CanBeMoused = false}); diff --git a/TouchyTickets/Upgrade.cs b/TouchyTickets/Upgrade.cs index e005c17..0bcfb97 100644 --- a/TouchyTickets/Upgrade.cs +++ b/TouchyTickets/Upgrade.cs @@ -1,15 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.Xna.Framework; using MLEM.Extensions; using MLEM.Textures; -namespace TouchyTickets.Upgrades { +namespace TouchyTickets { public class Upgrade { public static readonly Dictionary Upgrades = new Dictionary(); public static readonly Upgrade[] MapSize = RegisterTiers("MapSize", 10, 1, 0.5F, Ui.Texture[0, 3]); + public static readonly Upgrade FoodCourtModifier = Register(new Upgrade("FoodCourtModifier", 1, Ui.Texture[1, 3])); public readonly string Name; public readonly int Price; @@ -38,18 +38,17 @@ namespace TouchyTickets.Upgrades { // map size upgrades if (MapSize.Contains(this)) { var oldMap = GameImpl.Instance.Map; - var newMap = new ParkMap(oldMap.Width + 5, oldMap.Height + 5); - newMap.CopyAttractionsFrom(oldMap); - GameImpl.Instance.Map = newMap; + GameImpl.Instance.Map = oldMap.Copy(oldMap.Width + 5, oldMap.Height + 5); } } - private static void Register(Upgrade upgrade) { + private static Upgrade Register(Upgrade upgrade) { Upgrades.Add(upgrade.Name, upgrade); + return upgrade; } - public static bool IsActive(Upgrade upgrade) { - return GameImpl.Instance.AppliedUpgrades.Contains(upgrade); + public bool IsActive() { + return GameImpl.Instance.AppliedUpgrades.Contains(this); } }