Description:
Merge in m5-tiles-and-trees! ?
Commit status:
[Not Reviewed]
References:
merge default
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r682:ead2604f189e -

@@ -0,0 +1,11
1 using Microsoft.Xna.Framework;
2
3 using Encompass;
4
5 namespace isometricparkfna.Components {
6
7 public struct CursorComponent : IComponent {
8 public Vector2 position;
9 public int size;
10 }
11 }
@@ -0,0 +1,11
1 using Microsoft.Xna.Framework;
2
3 using Encompass;
4
5 namespace isometricparkfna.Components {
6
7 public struct PointComponent : IComponent {
8 public Vector2 Square;
9 public Tool Tool;
10 }
11 }
@@ -0,0 +1,10
1
2 using Encompass;
3 using System;
4
5 namespace isometricparkfna.Components {
6
7 public struct PreserveComponent : IComponent {
8 public DateTime date;
9 }
10 }
@@ -0,0 +1,17
1
2 using Encompass;
3
4 using isometricparkfna.Messages;
5
6 namespace isometricparkfna.Components {
7 public enum Structure
8 {
9 None,
10 Tower
11 }
12
13 public struct StructureComponent : IComponent {
14 public Structure Structure;
15 // public DateTime Placed;
16 }
17 }
@@ -0,0 +1,19
1 using Encompass;
2
3 using isometricparkfna.Messages;
4
5 namespace isometricparkfna.Components {
6
7 public enum Tool
8 {
9 None,
10 Preserve,
11 Dezone,
12 Tower,
13 Bulldozer
14 }
15
16 public struct ToolComponent : IComponent {
17 public Tool Tool;
18 }
19 }
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,350
1 using System;
2 using System.Linq;
3 using System.Collections.Generic;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Graphics;
6 using Microsoft.Xna.Framework.Input;
7
8 using Encompass;
9 using JM.LinqFaster;
10
11 using isometricparkfna.Messages;
12 using isometricparkfna.Components;
13
14 namespace isometricparkfna.Engines {
15
16 [Receives(typeof(SpawnSelection),
17 typeof(AdjustSelection),
18 typeof(UndoPreserveMessage))]
19 [Writes(typeof(AreaComponent),
20 typeof(PointComponent),
21 typeof(PreserveComponent))]
22 [Reads(typeof(SelectedComponent),
23 typeof(ContractStatusComponent),
24 typeof(AreaComponent),
25 typeof(PreserveComponent),
26 typeof(SelectedComponent),
27 typeof(ToolComponent),
28 typeof(PointComponent),
29 typeof(StructureComponent))]
30 [Sends(typeof(ChangeContractStatusMessage),
31 typeof(PlaySoundMessage),
32 typeof(SingleExpenseMessage),
33 typeof(SpawnDialogMessage))]
34 public class BuildToolEngine : Engine {
35
36 private CellMap Map;
37 private Simulation Simulation;
38
39 private static Dictionary<Tool, bool> ToolArea = new Dictionary<Tool, bool> {{Tool.Preserve, true},
40 {Tool.Dezone, true},
41 {Tool.Tower, false},
42 {Tool.Bulldozer, true}};
43
44 public BuildToolEngine(Simulation simulation) {
45 this.Map = simulation.map;
46 this.Simulation = simulation;
47 }
48
49 private System.Collections.Generic.IEnumerable<float> step_until(float start, float stop) {
50 if (stop >= start) {
51 for(float i = start; i <= stop; i++)
52 {
53 yield return i;
54 }
55 }
56 else {
57 for(float i = start; i >= stop; i--)
58 {
59 yield return i;
60 }
61 }
62 }
63
64 private void clear_areas(Vector2[] clear_squares) {
65 List<Entity> entities = new List<Entity>();
66 foreach(ref readonly var entity in ReadEntities<AreaComponent>() ) {
67 var squares = GetComponent<AreaComponent>(entity).squares;
68
69 foreach(var clear_square in clear_squares) {
70
71 foreach(var square in squares) {
72 if(square == clear_square) {
73 entities.Add(entity);
74 break;
75 }
76 }
77 }
78 }
79
80 foreach(var entity in entities) {
81 Logging.Debug("Deleting entity.");
82
83 if (HasComponent<ContractStatusComponent>(entity)) {
84 SendMessage(new ChangeContractStatusMessage {newStatus = ContractStatus.Broken, Entity = entity});
85 }
86 else {
87 Destroy(entity);
88 }
89 }
90 }
91
92 private void clear_structures(Vector2[] clear_squares) {
93 List<Entity> entities = new List<Entity>();
94 foreach(ref readonly var entity in ReadEntities<StructureComponent>() ) {
95 var square = GetComponent<PointComponent>(entity).Square;
96
97 foreach(var clear_square in clear_squares) {
98 if(square == clear_square) {
99 entities.Add(entity);
100 }
101 }
102 }
103
104 foreach(var entity in entities) {
105 Logging.Debug("Deleting entity.");
106 Destroy(entity);
107 }
108 }
109
110 private void SpawnSelection(Tool tool) {
111 foreach (ref readonly var message in ReadMessages<SpawnSelection>())
112 {
113 if (message.Start.X >= 0 && message.Start.X < this.Map.MapWidth
114 && message.Start.Y >= 0 && message.Start.Y < this.Map.MapHeight) {
115 var entity = CreateEntity();
116 if (BuildToolEngine.ToolArea[tool]) {
117 AddComponent(entity, new AreaComponent {squares = new[] {message.Start},
118 Tool = tool});
119 }
120 else {
121 AddComponent(entity, new PointComponent {Square = message.Start,
122 Tool=tool});
123 }
124 AddComponent(entity, new SelectedComponent {selected = true, Type= SelectionType.Area});
125 }
126 }
127 }
128
129
130 public List<Vector2> GetOccupied() {
131 List<Vector2> occupied = new List<Vector2>();
132
133 foreach (var (entity, status) in ReadEntities<AreaComponent>()
134 .WhereF((e) => HasComponent<ContractStatusComponent>(e))
135 .SelectWhereF((e) => (e, GetComponent<ContractStatusComponent>(e)),
136 (e) => ((e.Item2.status != ContractStatus.Broken)
137 && (e.Item2.status != ContractStatus.Rejected)
138 && (e.Item2.status != ContractStatus.Expired)
139 && (e.Item2.status != ContractStatus.Completed)
140 && (e.Item2.status != ContractStatus.Proposed))
141 )) {
142 var entitySquares = GetComponent<AreaComponent>(entity).squares;
143 occupied.AddRange(entitySquares);
144 }
145 return occupied;
146 }
147
148 public override void Update(double dt) {
149 Dictionary<Tool, bool> statuses = new Dictionary<Tool, bool>();
150
151 foreach (var entity in ReadEntities<ToolComponent>()) {
152 var tool = GetComponent<ToolComponent>(entity);
153 var selected = GetComponent<SelectedComponent>(entity);
154
155 statuses.Add(tool.Tool, selected.selected);
156 }
157
158 if (statuses.ContainsKey(Tool.Preserve) && statuses[Tool.Preserve]) {
159 var occupied = GetOccupied();
160 foreach (var entity in ReadEntities<AreaComponent>()
161 .WhereF((e) => HasComponent<PreserveComponent>(e))) {
162 var entitySquares = GetComponent<AreaComponent>(entity).squares;
163 occupied.AddRange(entitySquares);
164 }
165
166 SpawnSelection(Tool.Preserve);
167
168 foreach (ref readonly var message in ReadMessages<AdjustSelection>()) {
169 foreach (ref readonly var entity in ReadEntities<SelectedComponent>()) {
170 var selection = GetComponent<SelectedComponent>(entity);
171 if(selection.Type == SelectionType.Area
172 && selection.selected) {
173 if(message.Type == AdjustmentType.Clear) {
174 Destroy(entity);
175 }
176 else if(message.Type == AdjustmentType.Complete) {
177 SetComponent(entity, new PreserveComponent {date = this.Simulation.DateTime});
178 // SetComponent(entity, new SelectedComponent {selected = false });
179 var area = GetComponent<AreaComponent>(entity);
180 if (area.squares.Length > 400) {
181 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {
182 Path = "LargePreserve" });
183 }
184 }
185 else {
186 var area = GetComponent<AreaComponent>(entity);
187
188 var newSquares = new List<Vector2>();
189
190 var end_x = MathUtils.Clamp(message.End.X, 0.0f, this.Map.MapWidth-1);
191 var end_y = MathUtils.Clamp(message.End.Y, 0.0f, this.Map.MapHeight-1);
192
193 if (area.squares.Length > 0) {
194 foreach (var i in step_until(area.squares[0].X, end_x)) {
195 foreach (var j in step_until(area.squares[0].Y, end_y)) {
196 var newSquare = new Vector2(i, j);
197 if (!occupied.Contains(newSquare)) {
198 newSquares.Add(newSquare);
199 }
200 }
201 }
202 }
203 SetComponent(entity, new AreaComponent { squares = newSquares.ToArray(), Tool = area.Tool});
204 }
205 }
206 }
207 }
208 }
209 else if (statuses.ContainsKey(Tool.Dezone) && statuses[Tool.Dezone]) {
210 SpawnSelection(Tool.Dezone);
211
212 foreach (ref readonly var message in ReadMessages<AdjustSelection>()) {
213 foreach (ref readonly var entity in ReadEntities<SelectedComponent>()) {
214 var selection = GetComponent<SelectedComponent>(entity);
215 if(selection.Type == SelectionType.Area
216 && selection.selected) {
217 if(message.Type == AdjustmentType.Clear) {
218 Destroy(entity);
219 }
220 else if(message.Type == AdjustmentType.Complete) {
221 var squares = GetComponent<AreaComponent>(entity).squares;
222 clear_areas(squares);
223 }
224 else {
225 var area = GetComponent<AreaComponent>(entity);
226
227 var newSquares = new List<Vector2>();
228
229 var end_x = MathUtils.Clamp(message.End.X, 0.0f, this.Map.MapWidth);
230 var end_y = MathUtils.Clamp(message.End.Y, 0.0f, this.Map.MapHeight);
231
232 foreach (var i in step_until(area.squares[0].X, end_x)) {
233 foreach (var j in step_until(area.squares[0].Y, end_y)) {
234 var newSquare = new Vector2(i, j);
235 newSquares.Add(newSquare);
236 }
237 }
238 SetComponent(entity, new AreaComponent { squares = newSquares.ToArray(), Tool = area.Tool});
239 }
240 }
241 }
242 }
243 }
244 else if (statuses.ContainsKey(Tool.Tower) && statuses[Tool.Tower]) {
245 SpawnSelection(Tool.Tower);
246
247 var occupied = GetOccupied();
248
249 foreach (var (entity, point) in ReadEntities<StructureComponent>()
250 .WhereF((e) => HasComponent<PointComponent>(e))
251 .Select((e) => (e, GetComponent<PointComponent>(e)))) {
252
253 occupied.Add(point.Square);
254 }
255
256 foreach (ref readonly var message in ReadMessages<AdjustSelection>()) {
257 foreach (ref readonly var entity in ReadEntities<SelectedComponent>()) {
258 var selection = GetComponent<SelectedComponent>(entity);
259
260 if (selection.Type == SelectionType.Area
261 && selection.selected) {
262 if(message.Type == AdjustmentType.Clear) {
263 Destroy(entity);
264 }
265 else if (message.Type == AdjustmentType.Complete) {
266 var point = GetComponent<PointComponent>(entity);
267 var structure_entity = CreateEntity();
268 var cell = this.Map.cells[(int)point.Square.X][(int)point.Square.Y];
269 //Verify square is free:
270 //
271 if (!occupied.Contains(point.Square) && !cell.HasTree && !cell.HasWater) {
272
273 AddComponent(structure_entity, new PointComponent {Square = point.Square,
274 Tool = point.Tool} );
275 AddComponent(structure_entity,
276 new StructureComponent { Structure = Structure.Tower});
277 Destroy(entity);
278 SendMessage(new PlaySoundMessage { SoundName = "ConstructionShort" });
279 SendMessage(new SingleExpenseMessage { category = "Construction",
280 amount = 500M });
281 Logging.Success("Placed Tower!");
282 }
283
284 }
285 else {
286 var point = GetComponent<PointComponent>(entity);
287 SetComponent(entity, new PointComponent {Square = message.End,
288 Tool = point.Tool});
289 }
290 }
291 }
292 }
293 }
294
295 else if ((statuses.ContainsKey(Tool.Bulldozer) && statuses[Tool.Bulldozer])) {
296 SpawnSelection(Tool.Bulldozer);
297
298 foreach (ref readonly var message in ReadMessages<AdjustSelection>()) {
299 foreach (ref readonly var entity in ReadEntities<SelectedComponent>()) {
300 var selection = GetComponent<SelectedComponent>(entity);
301 if(selection.Type == SelectionType.Area
302 && selection.selected) {
303 if (message.Type == AdjustmentType.Clear) {
304 Destroy(entity);
305 }
306 else if (message.Type == AdjustmentType.Complete) {
307 var squares = GetComponent<AreaComponent>(entity).squares;
308 clear_structures(squares);
309 Destroy(entity); //Dezone destroys itself, so it doesn't need this command.
310 }
311 else {
312 var area = GetComponent<AreaComponent>(entity);
313
314 var newSquares = new List<Vector2>();
315
316 var end_x = MathUtils.Clamp(message.End.X, 0.0f, this.Map.MapWidth);
317 var end_y = MathUtils.Clamp(message.End.Y, 0.0f, this.Map.MapHeight);
318
319 foreach (var i in step_until(area.squares[0].X, end_x)) {
320 foreach (var j in step_until(area.squares[0].Y, end_y)) {
321 var newSquare = new Vector2(i, j);
322 newSquares.Add(newSquare);
323 }
324 }
325 SetComponent(entity, new AreaComponent { squares = newSquares.ToArray(), Tool = area.Tool});
326 }
327 }
328 }
329 }
330 }
331
332 DateTime min = DateTime.MinValue;
333 Entity newestEntity = default;
334
335 foreach (ref readonly var message in ReadMessages<UndoPreserveMessage>()) {
336 foreach (var entity in ReadEntities<PreserveComponent>()) {
337 var preserveComponent = GetComponent<PreserveComponent>(entity);
338 if (min < preserveComponent.date) {
339 min = preserveComponent.date;
340 newestEntity = entity;
341 }
342 Logging.Debug(String.Format("Checking preserve entity for {0}.", min));
343 }
344 }
345 if (min != DateTime.MinValue) {
346 Destroy(newestEntity);
347 }
348 }
349 }
350 }
@@ -0,0 +1,68
1 using System.Collections.Generic;
2 using Microsoft.Xna.Framework.Content;
3 using Microsoft.Xna.Framework.Audio;
4
5 using Encompass;
6
7 using isometricparkfna.Messages;
8 using isometricparkfna.Components;
9
10 namespace isometricparkfna.Engines
11 {
12
13 [Reads(typeof(OptionsComponent))]
14 [Receives(typeof(PlaySoundMessage))]
15 public class SoundEffectEngine : Engine
16 {
17 public static Dictionary<string, SoundEffect> sounds = new Dictionary<string, SoundEffect>();
18 public float volume = 1.0f;
19 public float pitch = 0.0f;
20 public float pan = 0.0f;
21 public bool muted = false;
22
23 public static SoundEffect LoadSound(ContentManager content, string path) {
24 return LoadSound(content, path, path);
25 }
26
27 public static SoundEffect LoadSound(ContentManager content,
28 string path, string name) {
29 var sfx = content.Load<SoundEffect>(path);
30 sounds.Add(name, sfx);
31 return sfx;
32
33 }
34
35 public static void DisposeSounds() {
36
37 foreach (KeyValuePair<string, SoundEffect> entry in sounds ) {
38 entry.Value.Dispose();
39 }
40
41 }
42
43 public override void Update(double dt) {
44
45 foreach(ref readonly var entity in
46 ReadEntities<OptionsComponent>()) {
47
48 var component = GetComponent<OptionsComponent>(entity);
49 volume = component.SoundEffectVolume;
50 muted = component.SoundEffectMuted;
51
52 }
53
54 foreach(ref readonly var message
55 in ReadMessages<PlaySoundMessage>()) {
56 var sound = sounds[message.SoundName];
57
58 var volume = message.Volume ?? this.volume;
59
60 if (!muted) {
61 sound.Play(volume, this.pitch, this.pan);
62 }
63 }
64
65 }
66
67 }
68 }
@@ -0,0 +1,17
1 using Microsoft.Xna.Framework;
2
3 using Encompass;
4
5 namespace isometricparkfna.Messages {
6
7 public enum AdjustmentType {
8 None,
9 Clear,
10 Complete
11 }
12
13 public struct AdjustSelection : IMessage {
14 public Vector2 End;
15 public AdjustmentType Type;
16 }
17 }
@@ -0,0 +1,10
1 using Microsoft.Xna.Framework;
2
3 using Encompass;
4
5 namespace isometricparkfna.Messages {
6
7 public struct DebugAlterTreesMessage : IMessage {
8 public int DeltaTrees;
9 }
10 }
@@ -0,0 +1,15
1 using Microsoft.Xna.Framework.Audio;
2
3 using Encompass;
4
5 #nullable enable
6
7 namespace isometricparkfna.Messages
8 {
9 public struct PlaySoundMessage : IMessage
10 {
11 public string SoundName;
12 public float? Volume;
13
14 }
15 }
@@ -0,0 +1,10
1 using Encompass;
2
3 namespace isometricparkfna.Messages
4 {
5 public struct SingleExpenseMessage : IMessage
6 {
7 public string category;
8 public decimal amount;
9 }
10 }
@@ -0,0 +1,9
1 using Microsoft.Xna.Framework;
2
3 using Encompass;
4
5 namespace isometricparkfna.Messages {
6 public struct SpawnSelection : IMessage {
7 public Vector2 Start;
8 }
9 }
@@ -0,0 +1,11
1 using isometricparkfna.Components;
2
3 using Encompass;
4
5 namespace isometricparkfna.Messages
6 {
7 public struct ToggleToolMessage : IMessage
8 {
9 public Tool Tool;
10 }
11 }
@@ -0,0 +1,7
1 using Encompass;
2
3 namespace isometricparkfna.Messages
4 {
5
6 public struct UndoPreserveMessage : IMessage { }
7 }
@@ -0,0 +1,63
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3
4 using isometricparkfna.UI;
5 using isometricparkfna.Components;
6
7 using Encompass;
8 using SpriteFontPlus;
9
10 namespace isometricparkfna.Renderers
11 {
12 public class CursorRenderer : GeneralRenderer
13 {
14 private SpriteBatch batch;
15 private SpriteFont font;
16
17 public CursorRenderer(SpriteBatch batch, SpriteFont font)
18 {
19 this.batch = batch;
20 this.font = font;
21 }
22
23 public override void Render()
24 {
25
26 Tool selectedTool = Tool.None;
27
28 foreach (ref readonly var entity in ReadEntities<ToolComponent>()) {
29 var toolComponent = GetComponent<ToolComponent>(entity);
30 var selectedComponent = GetComponent<SelectedComponent>(entity);
31 if (selectedComponent.selected) {
32 selectedTool = toolComponent.Tool;
33 }
34 }
35
36 foreach (ref readonly var entity in ReadEntities<CursorComponent>())
37 {
38
39 var cursorComponent = GetComponent<CursorComponent>(entity);
40 switch (selectedTool) {
41 case Tool.Dezone:
42 Tile.OutlineSquare(batch, cursorComponent.position.X, cursorComponent.position.Y, Color.Red);
43 break;
44 case Tool.Bulldozer:
45 Tile.OutlineSquare(batch, cursorComponent.position.X, cursorComponent.position.Y, Color.Red);
46 break;
47 case Tool.Preserve:
48 Tile.OutlineSquare(batch, cursorComponent.position.X, cursorComponent.position.Y, Color.Blue);
49 break;
50 default:
51 Tile.OutlineSquare(batch, cursorComponent.position.X, cursorComponent.position.Y, Color.Yellow);
52 break;
53
54 }
55 if(selectedTool == Tool.Tower) {
56 Tile.drawTileAt(batch, (int)cursorComponent.position.X, (int)cursorComponent.position.Y, 300, 2, 0.70f, new Color(1.0f, 1.0f, 1.0f, 0.5f));
57 }
58 }
59 }
60
61
62 }
63 }
@@ -0,0 +1,40
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3
4 using isometricparkfna.UI;
5 using isometricparkfna.Components;
6
7 using Encompass;
8 using SpriteFontPlus;
9
10 namespace isometricparkfna.Renderers
11 {
12 public class StructureRenderer : GeneralRenderer
13 {
14 private SpriteBatch batch;
15 private SpriteFont font;
16
17 public StructureRenderer(SpriteBatch batch, SpriteFont font)
18 {
19 this.batch = batch;
20 this.font = font;
21 }
22
23 public override void Render()
24 {
25
26
27 foreach (ref readonly var entity in ReadEntities<StructureComponent>())
28 {
29 var point = GetComponent<PointComponent>(entity);
30 Tile.drawTileAt(this.batch, (int)point.Square.X, (int)point.Square.Y,
31 300, 2, 0.79f, Color.White);
32 }
33
34
35
36 }
37 }
38
39
40 }
@@ -0,0 +1,18
1
2 namespace isometricparkfna.UI {
3
4 public enum ImGuiColor : uint {
5 BLACK = 0xFF000000,
6 RED = 0xFFFF0000,
7 GREEN = 0xFF00FF00,
8 BLUE = 0xFF0000FF,
9 DARKGREY = 0xFF999999,
10 LIGHTRED = 0xFFAA0000,
11 LIGHTGREEN = 0xFF00AA00,
12 LIGHTBLUE = 0xFF0000AA,
13 LIGHTGREY = 0xFFAAAAAA,
14 WHITE = 0xFF000000,
15
16 }
17
18 } No newline at end of file
1 NO CONTENT: new file 100644, binary diff hidden
@@ -14,22 +14,25
14 14 build-debug:
15 15 stage: build
16 16 script:
17 - dotnet restore isometric-park-fna-core.sln
17 18 - dotnet build isometric-park-fna-core.sln -f netcoreapp3.1
18 image: mcr.microsoft.com/dotnet/sdk:3.1-focal
19 image: mcr.microsoft.com/dotnet/sdk:3.1.415-focal
19 20
20 21
21 22 build-release-windows:
22 23 stage: build
23 24 script:
25 - dotnet restore isometric-park-fna-core.sln
24 26 - dotnet build isometric-park-fna-core.sln -f netcoreapp3.1 -c Release
25 image: mcr.microsoft.com/dotnet/sdk:3.1
27 image: mcr.microsoft.com/dotnet/sdk:3.1.415
26 28
27 29 build-release:
28 30 stage: build
29 31 script:
32 - dotnet restore isometric-park-fna-core.sln
30 33 - dotnet build isometric-park-fna-core.sln -f netcoreapp3.1 -c Release
31 34 artifacts:
32 35 paths:
33 36 - screenshot.xwd
34 37 expire_in: 1 week
35 image: mcr.microsoft.com/dotnet/sdk:3.1-focal
38 image: mcr.microsoft.com/dotnet/sdk:3.1.415-focal
@@ -29,6 +29,7
29 29 isometric-park-fna/Content/images/crops/*
30 30 isometric-park-fna/Content/Portraits/converted/*
31 31 isometric-park-fna/Content/Portraits/crops/*
32 isometric-park-fna/Content/Pak64/split/*
32 33 isometric-park-fna/DynamicLanguageRuntime.1.3.0/*
33 34 isometric-park-fna/IronPython.2.7.11/
34 35 **.patch
@@ -1,6 +1,24
1 1 {
2 2 "version": "0.2.0",
3 3 "configurations": [
4
5
6 {
7 "name": "Launch with Core Debugger No Build",
8 "type": "coreclr",
9 "request": "launch",
10 // "preLaunchTask": "Build: Core Debug",
11 "program": "${workspaceFolder}/isometric-park-fna/bin/Debug/netcoreapp3.1/isometric-park-fna.dll",
12 "args": [],
13 "env": {
14 // "LD_LIBRARY_PATH": "${workspaceFolder}/isometric-park-fna/bin/Debug/netcoreapp3.1/lib64",
15 "LD_LIBRARY_PATH": "${workspaceFolder}/fnalibs/lib64",
16 "DYLD_LIBRARY_PATH": "${workspaceFolder}/fnalibs/osx"
17 },
18 "cwd": "${workspaceFolder}/isometric-park-fna/bin/Debug/netcoreapp3.1",
19 "console": "integratedTerminal",
20 "internalConsoleOptions": "neverOpen"
21 },
4 22 {
5 23 "name": "Launch with Core Debugger",
6 24 "type": "coreclr",
@@ -23,12 +41,19
23 41 "name": "Attach LLDB to Running Process",
24 42 "pid": "${command:pickMyProcess}" // use ${command:pickProcess} to pick other users' processes
25 43 },
44
45 {
46 "type": "lldb",
47 "request": "attach",
48 "name": "Attach LLDB to Running Process",
49 "pid": "${command:pickMyProcess}" // use ${command:pickProcess} to pick other users' processes
50 },
26 51
27 52 {
28 53 "name": "Attach .NET Core to Running Process",
29 54 "type": "coreclr",
30 55 "request": "attach",
31 "processId":"${command:pickMyProcess}"
56 "pid":"${command:pickMyProcess}"
32 57 }
33 58 ]
34 59 }
@@ -137,7 +137,7
137 137 "command": "dotnet",
138 138 "args": [
139 139 "build",
140 "./isometric-park-fna-core.sln",
140 "./isometric-park-fna/isometric-park-fna-core.csproj",
141 141 "-f",
142 142 "netcoreapp3.1"
143 143 ],
@@ -175,7 +175,7
175 175 "command": "dotnet",
176 176 "args": [
177 177 "build",
178 "./isometric-park-fna-core.sln",
178 "./isometric-park-fna/isometric-park-fna-core.csproj",
179 179 "--configuration",
180 180 "Release",
181 181 "-f",
@@ -21,7 +21,6
21 21 <DocumentationFile></DocumentationFile>
22 22 </PropertyGroup>
23 23 <ItemGroup>
24 <Reference Include="System" />
25 24 <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
26 25 <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
27 26 <PackageReference Include="System.Buffers" Version="4.5.1" />
@@ -26,6 +26,33
26 26
27 27 #PIPELINE
28 28
29 ##Paks
30
31 ##I do some dubious things here to adopt Make to a workflow that generates multiple output files per input file, which
32 ##is not Make's strong suit.
33
34 isometric-park-fna/Content/Pak64/split/%.png: isometric-park-fna/Content/Pak64/%.png
35 convert $< -transparent '#e7ffff' -crop 64x64 isometric-park-fna/Content/Pak64/split/$*"%02d.png"
36 cp isometric-park-fna/Content/Pak64/split/$*00.png $@
37
38 isometric-park-fna/Content/pak64_tileset.png: $(shell find -ipath "*isometric-park-fna/Content/Pak64/*.png" -and -not -ipath "*split*" | sed "s:Pak64/:Pak64/split/:" |sort)
39 rm $^
40 montage isometric-park-fna/Content/Pak64/split/* -background transparent -tile 5 -geometry +0+0 -gravity north PNG8:$@
41 touch $^
42
43
44 pak: isometric-park-fna/Content/pak64_tileset.png
45
46
47 ## Merged
48
49 isometric-park-fna/Content/merged_tileset.png: isometric-park-fna/Content/pak64_tileset.png
50 montage isometric-park-fna/Content/part4_tileset.png $^ isometric-park-fna/Content/remos_trees2.png isometric-park-fna/Content/64x64_Objects_2.png isometric-park-fna/Content/rubberduck_parts_tower.png -background transparent -geometry +0+0 -tile 1x PNG:isometric-park-fna/Content/merged_tileset.png
51
52 merged: isometric-park-fna/Content/merged_tileset.png
53
54 ##Portraits
55
29 56 isometric-park-fna/Content/Portraits/converted/%.png: isometric-park-fna/Content/Portraits/%.jpg
30 57 convert $< -resize 500x500\> -dither FloydSteinberg -colors 8 -colorspace gray $@
31 58
@@ -1,11 +1,12
1
2 1
3 2 # isometric-park-fna
4 3
5 4
6 5 As the director of a small state park, your job is to balance conservation, leisure, and fiscal sustainability. Gameplay is still being added.
7 6
8 This is inspired by Maxis' Sim series of games, particularly SimSafari, and Chris Sawyer's Tycoon games. Its premise more closely resembles SimPark, but I never played it except for a demo. (Alternatively, watch [1990's Sim Games. SO GOOD!](https://www.youtube.com/watch?v=APFnM6DqtiA))
7 This is inspired by Maxis' [Sim series of games](https://en.wikipedia.org/wiki/List_of_Sim_video_games), particularly SimSafari, and Chris Sawyer's [Tycoon games](http://www.chrissawyergames.com/info.htm). Its premise more closely resembles [SimPark](https://en.wikipedia.org/wiki/SimPark), but I never played it except for a demo. (Alternatively, watch [1990's Sim Games. SO GOOD!](https://www.youtube.com/watch?v=APFnM6DqtiA))
8
9 I rewrote the core of this game for Procjam 2020, but the majority of the game has been added since.
9 10
10 11 I rewrote the core of this game for Procjam 2020, but the majority of the game has been added since.
11 12
@@ -24,11 +25,21
24 25 options aren't sufficient.
25 26
26 27 Currently, there are no options for adjusting the difficulty beyond the settings
27 that appear on the initial selection.
28 that appear on the initial selection when you begin a game.
29
30 ## System Requirements ##
31
32 The requirements are pretty modest. It runs pretty well on a 2010 MacBook Pro. Here's my estimated minimum:
33
34 * ~2 Ghz Core 2 Duo or equivalent
35 * 2 GB of memory
36 * Nvidia GeForce 200 series
37
38 If you have a more typical machine with, say, 8 GB of memory, an NVIDIA GeForce GTX, and an i5, you should have no trouble running the game.
28 39
29 40 ## Relationship to past work ##
30 41
31 This game is a total rewrite of the original version in C#. I honestly like the original language and library more (Clojure and Quil), but Quil was starting to struggle with the amount of drawing, and I was hitting the limit of my optimization abilities and available information online. (Another drawback: I'm also giving up the browser version, unless people get XNA in the browser working.)
42 This game is a total rewrite of the [original version](https://actuallyalys.itch.io/isometric-park-working-title) in C#. I honestly like the original language and library more (Clojure and Quil), but Quil was starting to struggle with the amount of drawing, and I was hitting the limit of my optimization abilities and available information online. (Another drawback: I'm also giving up the browser version, unless people get FNA in the browser working.)
32 43
33 44
34 45 ## Installing and Running ##
@@ -37,7 +48,6
37 48 * Windows and Linux users should be able to double-click the EXE and run it.
38 49 * BSD users can try using [fbsd-fnaify](https://github.com/oshogbo/fbsd-fnaify), although I have yet to confirm it works with Isometric Park. (If you do try it, let me know!)
39 50
40
41 51 ## Developing ##
42 52
43 53 To run from the command line, `make run`.
@@ -54,7 +64,11
54 64 2. Removed the ImGui folder: `rm -r ImGui.NET/`
55 65 3. Copied `cp -r /tmp/ImGui.NET/src/ImGui.NET .`
56 66
67 ### Architecture ###
57 68
69 This game uses an ECS structure, with significant parts of the simulation done in the `Simulation` class and some drawing in the `FNAGame` class. I use Encompass, which calls systems engines. It also adds messages, which last only one frame and are ideal for updates.
70
71 I call engines that connect the ECS and non-ECS parts bridge engines. It works reasonably well, although I'm trying to add new code to the ECS rather than to the `Simulation` and `FNAGame` classes.
58 72
59 73 ### File Structure ###
60 74
@@ -67,8 +81,8
67 81 β”‚Β Β  β”œβ”€β”€ **bin**
68 82 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **Debug** Debug version
69 83 β”‚Β Β  β”‚Β Β  └── **Release** Release version
70 β”‚Β Β  β”œβ”€β”€ *Camera.cs*
71 β”‚Β Β  β”œβ”€β”€ *CellMap.cs*
84 β”‚Β Β  β”œβ”€β”€ *Camera.cs*
85 β”‚Β Β  β”œβ”€β”€ *CellMap.cs*
72 86 β”‚Β Β  β”œβ”€β”€ **Components** Components that store data on entities.
73 87 β”‚Β Β  β”œβ”€β”€ **Content**
74 88 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **DejaVuSerif-BoldItalic.ttf**
@@ -91,11 +105,11
91 105 β”‚Β Β  β”‚Β Β  └── **typicons.ttf**
92 106 β”‚Β Β  β”œβ”€β”€ *DllMap.cs* (vendored)
93 107 β”‚Β Β  β”œβ”€β”€ *DrawVertDeclaration.cs*
94 β”‚Β Β  β”œβ”€β”€ **Engines** Engines
108 β”‚Β Β  β”œβ”€β”€ **Engines** Engines
95 109 β”‚Β Β  β”œβ”€β”€ *FilledRectangle.cs* Class for drawing a filled rectangle.
96 110 β”‚Β Β  β”œβ”€β”€ *FNAGame.cs* Primary game class.
97 111 β”‚Β Β  β”œβ”€β”€ **fnalibs** Compiled native libraries.
98 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **lib64**
112 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **lib64**
99 113 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **osx**
100 114 β”‚Β Β  β”‚Β Β  β”œβ”€β”€ **x64**
101 115 β”‚Β Β  β”‚Β Β  └── **x86**
@@ -146,22 +160,22
146 160
147 161 ## Acknowledgements ##
148 162
149 Art: [Isometric 64x64 Outside Tileset by Yar](https://opengameart.org/content/isometric-64x64-outside-tileset), various images from the Library of Congress and USDA Forest Service
163 Art: [Isometric 64x64 Outside Tileset by Yar](https://opengameart.org/content/isometric-64x64-outside-tileset), [Peaceful](https://silivar.itch.io/isometric-asset-pack-peaceful) by Silivar various images from the Library of Congress and USDA Forest Service
150 164
151 165 Libraries: [FNA](https://fna-xna.github.io/), [SpriteFontPlus](https://github.com/rds1983/SpriteFontPlus), [Tracery.Net](https://github.com/josh-perry/Tracery.Net), [ImGui.NET](http://imgui.net/), and [Encompass-cs](http://moonside.games/docs/encompass/)
152 166
153 Fonts: Droid Sans, [Iosevka](https://typeof.net/Iosevka/) by Belleve Invis, [Typicons](https://www.s-ings.com/typicons/) by Stephen Hutchings
167 Fonts: Droid Sans, [Iosevka](https://typeof.net/Iosevka/) by Belleve Invis, [Typicons](https://www.s-ings.com/typicons/) by Stephen Hutchings, [OCRA}(http://luc.devroye.org/fonts-48511.html) designed by American Type Founders and converted by Matthew Skala
168
169 Sounds: Bell, hammering, and jackhammer sounds by InspectorJ; Switch clicking by qubodup
154 170
155 Sources for the procedural generation are documented in Sources.md.
171 Sources for the procedural generation are documented in Sources.md.
156 172
157 Watching Thin Matrix's [video devlogs](https://www.youtube.com/watch?v=90CZ7Q17sls&list=PLRIWtICgwaX1gcSZ8qj8Q473tz7PsNmpR) for Equilinox inspired me to press on. :) Despite some similarities, the design of this game wasn't really inspired by Equilinox. (I've also enjoyed Thoughtquake's [video devlogs](https://www.youtube.com/user/Thoughtquake/videos) for Cargo Defense and Cliff Harris' Democracy 4 [video devlogs](https://www.youtube.com/user/cliffski2/videos))
173 Watching ThinMatrix's [video devlogs](https://www.youtube.com/watch?v=90CZ7Q17sls&list=PLRIWtICgwaX1gcSZ8qj8Q473tz7PsNmpR) for Equilinox and his subsequent games inspired me to press on. :) Despite some similarities, the design of this game wasn't really inspired by Equilinox. (I've also enjoyed Thoughtquake's [video devlogs](https://www.youtube.com/user/Thoughtquake/videos) and Cliff Harris' Democracy 4 [video devlogs](https://www.youtube.com/user/cliffski2/videos)).
158 174
159 175 The original versions used art from the [Low Poly Forest Pack](https://devilsworkshop.itch.io/lowpoly-forest-pack) by [Devil's Work.Shop](https://devilsworkshop.itch.io/). (I had converted the models into isometric 2D images, using [this process.](https://www.youtube.com/watch?v=bk0PXMgZgQg))
160 176
161 177 ## License ##
162 178
163 Β© 2021 Alys S. Brooks
179 Β© 2022 Alys S. Brooks
164 180
165 181 I haven't decided on a license.
166
167
1 NO CONTENT: modified file, binary diff hidden
@@ -1,4 +1,4
1 // <autogenerated />
2 using System;
3 using System.Reflection;
1 // <autogenerated />
2 using System;
3 using System.Reflection;
4 4 // [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
1 NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file, binary diff hidden
This diff has been collapsed as it changes many lines, (595 lines changed) Show them Hide them
@@ -2,57 +2,8
2 2 "version": 3,
3 3 "targets": {
4 4 ".NETFramework,Version=v4.5": {
5 "Microsoft.NETFramework.ReferenceAssemblies/1.0.0": {
6 "type": "package",
7 "dependencies": {
8 "Microsoft.NETFramework.ReferenceAssemblies.net45": "1.0.0"
9 }
10 },
11 "Microsoft.NETFramework.ReferenceAssemblies.net45/1.0.0": {
12 "type": "package",
13 "build": {
14 "build/Microsoft.NETFramework.ReferenceAssemblies.net45.targets": {}
15 }
16 },
17 5 "FNA/1.0.0": {
18 6 "type": "project",
19 "framework": ".NETFramework,Version=v4.0",
20 "compile": {
21 "bin/placeholder/FNA.dll": {}
22 },
23 "runtime": {
24 "bin/placeholder/FNA.dll": {}
25 }
26 }
27 },
28 ".NETStandard,Version=v2.0": {
29 "Microsoft.NETCore.Platforms/1.1.0": {
30 "type": "package",
31 "compile": {
32 "lib/netstandard1.0/_._": {}
33 },
34 "runtime": {
35 "lib/netstandard1.0/_._": {}
36 }
37 },
38 "NETStandard.Library/2.0.3": {
39 "type": "package",
40 "dependencies": {
41 "Microsoft.NETCore.Platforms": "1.1.0"
42 },
43 "compile": {
44 "lib/netstandard1.0/_._": {}
45 },
46 "runtime": {
47 "lib/netstandard1.0/_._": {}
48 },
49 "build": {
50 "build/netstandard2.0/NETStandard.Library.targets": {}
51 }
52 },
53 "FNA/1.0.0": {
54 "type": "project",
55 "framework": ".NETStandard,Version=v2.0",
56 7 "compile": {
57 8 "bin/placeholder/FNA.dll": {}
58 9 },
@@ -63,536 +14,43
63 14 }
64 15 },
65 16 "libraries": {
66 "Microsoft.NETCore.Platforms/1.1.0": {
67 "sha512": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
68 "type": "package",
69 "path": "microsoft.netcore.platforms/1.1.0",
70 "files": [
71 ".nupkg.metadata",
72 ".signature.p7s",
73 "ThirdPartyNotices.txt",
74 "dotnet_library_license.txt",
75 "lib/netstandard1.0/_._",
76 "microsoft.netcore.platforms.1.1.0.nupkg.sha512",
77 "microsoft.netcore.platforms.nuspec",
78 "runtime.json"
79 ]
80 },
81 "Microsoft.NETFramework.ReferenceAssemblies/1.0.0": {
82 "sha512": "7D2TMufjGiowmt0E941kVoTIS+GTNzaPopuzM1/1LSaJAdJdBrVP0SkZW7AgDd0a2U1DjsIeaKG1wxGVBNLDMw==",
83 "type": "package",
84 "path": "microsoft.netframework.referenceassemblies/1.0.0",
85 "files": [
86 ".nupkg.metadata",
87 ".signature.p7s",
88 "microsoft.netframework.referenceassemblies.1.0.0.nupkg.sha512",
89 "microsoft.netframework.referenceassemblies.nuspec"
90 ]
91 },
92 "Microsoft.NETFramework.ReferenceAssemblies.net45/1.0.0": {
93 "sha512": "f7XMQsZFaoc3w8Vg3VQ3FHuU2C9vf0Ng5EAV4gzdNWDerPM/OmrzccLj15eI1wCLLXj4jk8+lKsbonzJeyXgQQ==",
94 "type": "package",
95 "path": "microsoft.netframework.referenceassemblies.net45/1.0.0",
96 "files": [
97 ".nupkg.metadata",
98 ".signature.p7s",
99 "build/.NETFramework/v4.5/Accessibility.dll",
100 "build/.NETFramework/v4.5/Accessibility.xml",
101 "build/.NETFramework/v4.5/CustomMarshalers.dll",
102 "build/.NETFramework/v4.5/CustomMarshalers.xml",
103 "build/.NETFramework/v4.5/Facades/System.Collections.Concurrent.dll",
104 "build/.NETFramework/v4.5/Facades/System.Collections.dll",
105 "build/.NETFramework/v4.5/Facades/System.ComponentModel.Annotations.dll",
106 "build/.NETFramework/v4.5/Facades/System.ComponentModel.EventBasedAsync.dll",
107 "build/.NETFramework/v4.5/Facades/System.ComponentModel.dll",
108 "build/.NETFramework/v4.5/Facades/System.Diagnostics.Contracts.dll",
109 "build/.NETFramework/v4.5/Facades/System.Diagnostics.Debug.dll",
110 "build/.NETFramework/v4.5/Facades/System.Diagnostics.Tools.dll",
111 "build/.NETFramework/v4.5/Facades/System.Diagnostics.Tracing.dll",
112 "build/.NETFramework/v4.5/Facades/System.Dynamic.Runtime.dll",
113 "build/.NETFramework/v4.5/Facades/System.Globalization.dll",
114 "build/.NETFramework/v4.5/Facades/System.IO.dll",
115 "build/.NETFramework/v4.5/Facades/System.Linq.Expressions.dll",
116 "build/.NETFramework/v4.5/Facades/System.Linq.Parallel.dll",
117 "build/.NETFramework/v4.5/Facades/System.Linq.Queryable.dll",
118 "build/.NETFramework/v4.5/Facades/System.Linq.dll",
119 "build/.NETFramework/v4.5/Facades/System.Net.NetworkInformation.dll",
120 "build/.NETFramework/v4.5/Facades/System.Net.Primitives.dll",
121 "build/.NETFramework/v4.5/Facades/System.Net.Requests.dll",
122 "build/.NETFramework/v4.5/Facades/System.ObjectModel.dll",
123 "build/.NETFramework/v4.5/Facades/System.Reflection.Emit.ILGeneration.dll",
124 "build/.NETFramework/v4.5/Facades/System.Reflection.Emit.Lightweight.dll",
125 "build/.NETFramework/v4.5/Facades/System.Reflection.Emit.dll",
126 "build/.NETFramework/v4.5/Facades/System.Reflection.Extensions.dll",
127 "build/.NETFramework/v4.5/Facades/System.Reflection.Primitives.dll",
128 "build/.NETFramework/v4.5/Facades/System.Reflection.dll",
129 "build/.NETFramework/v4.5/Facades/System.Resources.ResourceManager.dll",
130 "build/.NETFramework/v4.5/Facades/System.Runtime.Extensions.dll",
131 "build/.NETFramework/v4.5/Facades/System.Runtime.InteropServices.WindowsRuntime.dll",
132 "build/.NETFramework/v4.5/Facades/System.Runtime.InteropServices.dll",
133 "build/.NETFramework/v4.5/Facades/System.Runtime.Numerics.dll",
134 "build/.NETFramework/v4.5/Facades/System.Runtime.Serialization.Json.dll",
135 "build/.NETFramework/v4.5/Facades/System.Runtime.Serialization.Primitives.dll",
136 "build/.NETFramework/v4.5/Facades/System.Runtime.Serialization.Xml.dll",
137 "build/.NETFramework/v4.5/Facades/System.Runtime.dll",
138 "build/.NETFramework/v4.5/Facades/System.Security.Principal.dll",
139 "build/.NETFramework/v4.5/Facades/System.ServiceModel.Duplex.dll",
140 "build/.NETFramework/v4.5/Facades/System.ServiceModel.Http.dll",
141 "build/.NETFramework/v4.5/Facades/System.ServiceModel.NetTcp.dll",
142 "build/.NETFramework/v4.5/Facades/System.ServiceModel.Primitives.dll",
143 "build/.NETFramework/v4.5/Facades/System.ServiceModel.Security.dll",
144 "build/.NETFramework/v4.5/Facades/System.Text.Encoding.Extensions.dll",
145 "build/.NETFramework/v4.5/Facades/System.Text.Encoding.dll",
146 "build/.NETFramework/v4.5/Facades/System.Text.RegularExpressions.dll",
147 "build/.NETFramework/v4.5/Facades/System.Threading.Tasks.Parallel.dll",
148 "build/.NETFramework/v4.5/Facades/System.Threading.Tasks.dll",
149 "build/.NETFramework/v4.5/Facades/System.Threading.dll",
150 "build/.NETFramework/v4.5/Facades/System.Xml.ReaderWriter.dll",
151 "build/.NETFramework/v4.5/Facades/System.Xml.XDocument.dll",
152 "build/.NETFramework/v4.5/Facades/System.Xml.XmlSerializer.dll",
153 "build/.NETFramework/v4.5/ISymWrapper.dll",
154 "build/.NETFramework/v4.5/ISymWrapper.xml",
155 "build/.NETFramework/v4.5/Microsoft.Activities.Build.dll",
156 "build/.NETFramework/v4.5/Microsoft.Activities.Build.xml",
157 "build/.NETFramework/v4.5/Microsoft.Build.Conversion.v4.0.dll",
158 "build/.NETFramework/v4.5/Microsoft.Build.Conversion.v4.0.xml",
159 "build/.NETFramework/v4.5/Microsoft.Build.Engine.dll",
160 "build/.NETFramework/v4.5/Microsoft.Build.Engine.xml",
161 "build/.NETFramework/v4.5/Microsoft.Build.Framework.dll",
162 "build/.NETFramework/v4.5/Microsoft.Build.Framework.xml",
163 "build/.NETFramework/v4.5/Microsoft.Build.Tasks.v4.0.dll",
164 "build/.NETFramework/v4.5/Microsoft.Build.Tasks.v4.0.xml",
165 "build/.NETFramework/v4.5/Microsoft.Build.Utilities.v4.0.dll",
166 "build/.NETFramework/v4.5/Microsoft.Build.Utilities.v4.0.xml",
167 "build/.NETFramework/v4.5/Microsoft.Build.dll",
168 "build/.NETFramework/v4.5/Microsoft.Build.xml",
169 "build/.NETFramework/v4.5/Microsoft.CSharp.dll",
170 "build/.NETFramework/v4.5/Microsoft.CSharp.xml",
171 "build/.NETFramework/v4.5/Microsoft.JScript.dll",
172 "build/.NETFramework/v4.5/Microsoft.JScript.xml",
173 "build/.NETFramework/v4.5/Microsoft.VisualBasic.Compatibility.Data.dll",
174 "build/.NETFramework/v4.5/Microsoft.VisualBasic.Compatibility.Data.xml",
175 "build/.NETFramework/v4.5/Microsoft.VisualBasic.Compatibility.dll",
176 "build/.NETFramework/v4.5/Microsoft.VisualBasic.Compatibility.xml",
177 "build/.NETFramework/v4.5/Microsoft.VisualBasic.dll",
178 "build/.NETFramework/v4.5/Microsoft.VisualBasic.xml",
179 "build/.NETFramework/v4.5/Microsoft.VisualC.STLCLR.dll",
180 "build/.NETFramework/v4.5/Microsoft.VisualC.STLCLR.xml",
181 "build/.NETFramework/v4.5/Microsoft.VisualC.dll",
182 "build/.NETFramework/v4.5/Microsoft.VisualC.xml",
183 "build/.NETFramework/v4.5/PermissionSets/FullTrust.xml",
184 "build/.NETFramework/v4.5/PermissionSets/Internet.xml",
185 "build/.NETFramework/v4.5/PermissionSets/LocalIntranet.xml",
186 "build/.NETFramework/v4.5/PresentationBuildTasks.dll",
187 "build/.NETFramework/v4.5/PresentationBuildTasks.xml",
188 "build/.NETFramework/v4.5/PresentationCore.dll",
189 "build/.NETFramework/v4.5/PresentationCore.xml",
190 "build/.NETFramework/v4.5/PresentationFramework.Aero.dll",
191 "build/.NETFramework/v4.5/PresentationFramework.Aero.xml",
192 "build/.NETFramework/v4.5/PresentationFramework.Aero2.dll",
193 "build/.NETFramework/v4.5/PresentationFramework.AeroLite.dll",
194 "build/.NETFramework/v4.5/PresentationFramework.Classic.dll",
195 "build/.NETFramework/v4.5/PresentationFramework.Classic.xml",
196 "build/.NETFramework/v4.5/PresentationFramework.Luna.dll",
197 "build/.NETFramework/v4.5/PresentationFramework.Luna.xml",
198 "build/.NETFramework/v4.5/PresentationFramework.Royale.dll",
199 "build/.NETFramework/v4.5/PresentationFramework.Royale.xml",
200 "build/.NETFramework/v4.5/PresentationFramework.dll",
201 "build/.NETFramework/v4.5/PresentationFramework.xml",
202 "build/.NETFramework/v4.5/ReachFramework.dll",
203 "build/.NETFramework/v4.5/ReachFramework.xml",
204 "build/.NETFramework/v4.5/RedistList/FrameworkList.xml",
205 "build/.NETFramework/v4.5/System.Activities.Core.Presentation.dll",
206 "build/.NETFramework/v4.5/System.Activities.Core.Presentation.xml",
207 "build/.NETFramework/v4.5/System.Activities.DurableInstancing.dll",
208 "build/.NETFramework/v4.5/System.Activities.DurableInstancing.xml",
209 "build/.NETFramework/v4.5/System.Activities.Presentation.dll",
210 "build/.NETFramework/v4.5/System.Activities.Presentation.xml",
211 "build/.NETFramework/v4.5/System.Activities.dll",
212 "build/.NETFramework/v4.5/System.Activities.xml",
213 "build/.NETFramework/v4.5/System.AddIn.Contract.dll",
214 "build/.NETFramework/v4.5/System.AddIn.Contract.xml",
215 "build/.NETFramework/v4.5/System.AddIn.dll",
216 "build/.NETFramework/v4.5/System.AddIn.xml",
217 "build/.NETFramework/v4.5/System.ComponentModel.Composition.Registration.dll",
218 "build/.NETFramework/v4.5/System.ComponentModel.Composition.dll",
219 "build/.NETFramework/v4.5/System.ComponentModel.Composition.xml",
220 "build/.NETFramework/v4.5/System.ComponentModel.DataAnnotations.dll",
221 "build/.NETFramework/v4.5/System.ComponentModel.DataAnnotations.xml",
222 "build/.NETFramework/v4.5/System.Configuration.Install.dll",
223 "build/.NETFramework/v4.5/System.Configuration.Install.xml",
224 "build/.NETFramework/v4.5/System.Configuration.dll",
225 "build/.NETFramework/v4.5/System.Configuration.xml",
226 "build/.NETFramework/v4.5/System.Core.dll",
227 "build/.NETFramework/v4.5/System.Core.xml",
228 "build/.NETFramework/v4.5/System.Data.DataSetExtensions.dll",
229 "build/.NETFramework/v4.5/System.Data.DataSetExtensions.xml",
230 "build/.NETFramework/v4.5/System.Data.Entity.Design.dll",
231 "build/.NETFramework/v4.5/System.Data.Entity.Design.xml",
232 "build/.NETFramework/v4.5/System.Data.Entity.dll",
233 "build/.NETFramework/v4.5/System.Data.Entity.xml",
234 "build/.NETFramework/v4.5/System.Data.Linq.dll",
235 "build/.NETFramework/v4.5/System.Data.Linq.xml",
236 "build/.NETFramework/v4.5/System.Data.OracleClient.dll",
237 "build/.NETFramework/v4.5/System.Data.OracleClient.xml",
238 "build/.NETFramework/v4.5/System.Data.Services.Client.dll",
239 "build/.NETFramework/v4.5/System.Data.Services.Client.xml",
240 "build/.NETFramework/v4.5/System.Data.Services.Design.dll",
241 "build/.NETFramework/v4.5/System.Data.Services.Design.xml",
242 "build/.NETFramework/v4.5/System.Data.Services.dll",
243 "build/.NETFramework/v4.5/System.Data.Services.xml",
244 "build/.NETFramework/v4.5/System.Data.SqlXml.dll",
245 "build/.NETFramework/v4.5/System.Data.SqlXml.xml",
246 "build/.NETFramework/v4.5/System.Data.dll",
247 "build/.NETFramework/v4.5/System.Data.xml",
248 "build/.NETFramework/v4.5/System.Deployment.dll",
249 "build/.NETFramework/v4.5/System.Deployment.xml",
250 "build/.NETFramework/v4.5/System.Design.dll",
251 "build/.NETFramework/v4.5/System.Design.xml",
252 "build/.NETFramework/v4.5/System.Device.dll",
253 "build/.NETFramework/v4.5/System.Device.xml",
254 "build/.NETFramework/v4.5/System.DirectoryServices.AccountManagement.dll",
255 "build/.NETFramework/v4.5/System.DirectoryServices.AccountManagement.xml",
256 "build/.NETFramework/v4.5/System.DirectoryServices.Protocols.dll",
257 "build/.NETFramework/v4.5/System.DirectoryServices.Protocols.xml",
258 "build/.NETFramework/v4.5/System.DirectoryServices.dll",
259 "build/.NETFramework/v4.5/System.DirectoryServices.xml",
260 "build/.NETFramework/v4.5/System.Drawing.Design.dll",
261 "build/.NETFramework/v4.5/System.Drawing.Design.xml",
262 "build/.NETFramework/v4.5/System.Drawing.dll",
263 "build/.NETFramework/v4.5/System.Drawing.xml",
264 "build/.NETFramework/v4.5/System.EnterpriseServices.Thunk.dll",
265 "build/.NETFramework/v4.5/System.EnterpriseServices.Wrapper.dll",
266 "build/.NETFramework/v4.5/System.EnterpriseServices.dll",
267 "build/.NETFramework/v4.5/System.EnterpriseServices.xml",
268 "build/.NETFramework/v4.5/System.IO.Compression.FileSystem.dll",
269 "build/.NETFramework/v4.5/System.IO.Compression.FileSystem.xml",
270 "build/.NETFramework/v4.5/System.IO.Compression.dll",
271 "build/.NETFramework/v4.5/System.IO.Compression.xml",
272 "build/.NETFramework/v4.5/System.IO.Log.dll",
273 "build/.NETFramework/v4.5/System.IO.Log.xml",
274 "build/.NETFramework/v4.5/System.IdentityModel.Selectors.dll",
275 "build/.NETFramework/v4.5/System.IdentityModel.Selectors.xml",
276 "build/.NETFramework/v4.5/System.IdentityModel.Services.dll",
277 "build/.NETFramework/v4.5/System.IdentityModel.Services.xml",
278 "build/.NETFramework/v4.5/System.IdentityModel.dll",
279 "build/.NETFramework/v4.5/System.IdentityModel.xml",
280 "build/.NETFramework/v4.5/System.Management.Instrumentation.dll",
281 "build/.NETFramework/v4.5/System.Management.Instrumentation.xml",
282 "build/.NETFramework/v4.5/System.Management.dll",
283 "build/.NETFramework/v4.5/System.Management.xml",
284 "build/.NETFramework/v4.5/System.Messaging.dll",
285 "build/.NETFramework/v4.5/System.Messaging.xml",
286 "build/.NETFramework/v4.5/System.Net.Http.WebRequest.dll",
287 "build/.NETFramework/v4.5/System.Net.Http.WebRequest.xml",
288 "build/.NETFramework/v4.5/System.Net.Http.dll",
289 "build/.NETFramework/v4.5/System.Net.Http.xml",
290 "build/.NETFramework/v4.5/System.Net.dll",
291 "build/.NETFramework/v4.5/System.Net.xml",
292 "build/.NETFramework/v4.5/System.Numerics.dll",
293 "build/.NETFramework/v4.5/System.Numerics.xml",
294 "build/.NETFramework/v4.5/System.Printing.dll",
295 "build/.NETFramework/v4.5/System.Printing.xml",
296 "build/.NETFramework/v4.5/System.Reflection.Context.dll",
297 "build/.NETFramework/v4.5/System.Reflection.Context.xml",
298 "build/.NETFramework/v4.5/System.Runtime.Caching.dll",
299 "build/.NETFramework/v4.5/System.Runtime.Caching.xml",
300 "build/.NETFramework/v4.5/System.Runtime.DurableInstancing.dll",
301 "build/.NETFramework/v4.5/System.Runtime.DurableInstancing.xml",
302 "build/.NETFramework/v4.5/System.Runtime.Remoting.dll",
303 "build/.NETFramework/v4.5/System.Runtime.Remoting.xml",
304 "build/.NETFramework/v4.5/System.Runtime.Serialization.Formatters.Soap.dll",
305 "build/.NETFramework/v4.5/System.Runtime.Serialization.Formatters.Soap.xml",
306 "build/.NETFramework/v4.5/System.Runtime.Serialization.dll",
307 "build/.NETFramework/v4.5/System.Runtime.Serialization.xml",
308 "build/.NETFramework/v4.5/System.Security.dll",
309 "build/.NETFramework/v4.5/System.Security.xml",
310 "build/.NETFramework/v4.5/System.ServiceModel.Activation.dll",
311 "build/.NETFramework/v4.5/System.ServiceModel.Activation.xml",
312 "build/.NETFramework/v4.5/System.ServiceModel.Activities.dll",
313 "build/.NETFramework/v4.5/System.ServiceModel.Activities.xml",
314 "build/.NETFramework/v4.5/System.ServiceModel.Channels.dll",
315 "build/.NETFramework/v4.5/System.ServiceModel.Channels.xml",
316 "build/.NETFramework/v4.5/System.ServiceModel.Discovery.dll",
317 "build/.NETFramework/v4.5/System.ServiceModel.Discovery.xml",
318 "build/.NETFramework/v4.5/System.ServiceModel.Routing.dll",
319 "build/.NETFramework/v4.5/System.ServiceModel.Routing.xml",
320 "build/.NETFramework/v4.5/System.ServiceModel.Web.dll",
321 "build/.NETFramework/v4.5/System.ServiceModel.Web.xml",
322 "build/.NETFramework/v4.5/System.ServiceModel.dll",
323 "build/.NETFramework/v4.5/System.ServiceModel.xml",
324 "build/.NETFramework/v4.5/System.ServiceProcess.dll",
325 "build/.NETFramework/v4.5/System.ServiceProcess.xml",
326 "build/.NETFramework/v4.5/System.Speech.dll",
327 "build/.NETFramework/v4.5/System.Speech.xml",
328 "build/.NETFramework/v4.5/System.Threading.Tasks.Dataflow.xml",
329 "build/.NETFramework/v4.5/System.Transactions.dll",
330 "build/.NETFramework/v4.5/System.Transactions.xml",
331 "build/.NETFramework/v4.5/System.Web.Abstractions.dll",
332 "build/.NETFramework/v4.5/System.Web.ApplicationServices.dll",
333 "build/.NETFramework/v4.5/System.Web.ApplicationServices.xml",
334 "build/.NETFramework/v4.5/System.Web.DataVisualization.Design.dll",
335 "build/.NETFramework/v4.5/System.Web.DataVisualization.dll",
336 "build/.NETFramework/v4.5/System.Web.DataVisualization.xml",
337 "build/.NETFramework/v4.5/System.Web.DynamicData.Design.dll",
338 "build/.NETFramework/v4.5/System.Web.DynamicData.Design.xml",
339 "build/.NETFramework/v4.5/System.Web.DynamicData.dll",
340 "build/.NETFramework/v4.5/System.Web.DynamicData.xml",
341 "build/.NETFramework/v4.5/System.Web.Entity.Design.dll",
342 "build/.NETFramework/v4.5/System.Web.Entity.Design.xml",
343 "build/.NETFramework/v4.5/System.Web.Entity.dll",
344 "build/.NETFramework/v4.5/System.Web.Entity.xml",
345 "build/.NETFramework/v4.5/System.Web.Extensions.Design.dll",
346 "build/.NETFramework/v4.5/System.Web.Extensions.Design.xml",
347 "build/.NETFramework/v4.5/System.Web.Extensions.dll",
348 "build/.NETFramework/v4.5/System.Web.Extensions.xml",
349 "build/.NETFramework/v4.5/System.Web.Mobile.dll",
350 "build/.NETFramework/v4.5/System.Web.Mobile.xml",
351 "build/.NETFramework/v4.5/System.Web.RegularExpressions.dll",
352 "build/.NETFramework/v4.5/System.Web.RegularExpressions.xml",
353 "build/.NETFramework/v4.5/System.Web.Routing.dll",
354 "build/.NETFramework/v4.5/System.Web.Services.dll",
355 "build/.NETFramework/v4.5/System.Web.Services.xml",
356 "build/.NETFramework/v4.5/System.Web.dll",
357 "build/.NETFramework/v4.5/System.Web.xml",
358 "build/.NETFramework/v4.5/System.Windows.Controls.Ribbon.dll",
359 "build/.NETFramework/v4.5/System.Windows.Controls.Ribbon.xml",
360 "build/.NETFramework/v4.5/System.Windows.Forms.DataVisualization.Design.dll",
361 "build/.NETFramework/v4.5/System.Windows.Forms.DataVisualization.dll",
362 "build/.NETFramework/v4.5/System.Windows.Forms.DataVisualization.xml",
363 "build/.NETFramework/v4.5/System.Windows.Forms.dll",
364 "build/.NETFramework/v4.5/System.Windows.Forms.xml",
365 "build/.NETFramework/v4.5/System.Windows.Input.Manipulations.dll",
366 "build/.NETFramework/v4.5/System.Windows.Input.Manipulations.xml",
367 "build/.NETFramework/v4.5/System.Windows.Presentation.dll",
368 "build/.NETFramework/v4.5/System.Windows.Presentation.xml",
369 "build/.NETFramework/v4.5/System.Windows.dll",
370 "build/.NETFramework/v4.5/System.Workflow.Activities.dll",
371 "build/.NETFramework/v4.5/System.Workflow.Activities.xml",
372 "build/.NETFramework/v4.5/System.Workflow.ComponentModel.dll",
373 "build/.NETFramework/v4.5/System.Workflow.ComponentModel.xml",
374 "build/.NETFramework/v4.5/System.Workflow.Runtime.dll",
375 "build/.NETFramework/v4.5/System.Workflow.Runtime.xml",
376 "build/.NETFramework/v4.5/System.WorkflowServices.dll",
377 "build/.NETFramework/v4.5/System.WorkflowServices.xml",
378 "build/.NETFramework/v4.5/System.Xaml.dll",
379 "build/.NETFramework/v4.5/System.Xaml.xml",
380 "build/.NETFramework/v4.5/System.Xml.Linq.dll",
381 "build/.NETFramework/v4.5/System.Xml.Linq.xml",
382 "build/.NETFramework/v4.5/System.Xml.Serialization.dll",
383 "build/.NETFramework/v4.5/System.Xml.dll",
384 "build/.NETFramework/v4.5/System.Xml.xml",
385 "build/.NETFramework/v4.5/System.dll",
386 "build/.NETFramework/v4.5/System.xml",
387 "build/.NETFramework/v4.5/UIAutomationClient.dll",
388 "build/.NETFramework/v4.5/UIAutomationClient.xml",
389 "build/.NETFramework/v4.5/UIAutomationClientsideProviders.dll",
390 "build/.NETFramework/v4.5/UIAutomationClientsideProviders.xml",
391 "build/.NETFramework/v4.5/UIAutomationProvider.dll",
392 "build/.NETFramework/v4.5/UIAutomationProvider.xml",
393 "build/.NETFramework/v4.5/UIAutomationTypes.dll",
394 "build/.NETFramework/v4.5/UIAutomationTypes.xml",
395 "build/.NETFramework/v4.5/WindowsBase.dll",
396 "build/.NETFramework/v4.5/WindowsBase.xml",
397 "build/.NETFramework/v4.5/WindowsFormsIntegration.dll",
398 "build/.NETFramework/v4.5/WindowsFormsIntegration.xml",
399 "build/.NETFramework/v4.5/XamlBuildTask.dll",
400 "build/.NETFramework/v4.5/XamlBuildTask.xml",
401 "build/.NETFramework/v4.5/mscorlib.dll",
402 "build/.NETFramework/v4.5/mscorlib.xml",
403 "build/.NETFramework/v4.5/sysglobl.dll",
404 "build/.NETFramework/v4.5/sysglobl.xml",
405 "build/Microsoft.NETFramework.ReferenceAssemblies.net45.targets",
406 "microsoft.netframework.referenceassemblies.net45.1.0.0.nupkg.sha512",
407 "microsoft.netframework.referenceassemblies.net45.nuspec"
408 ]
409 },
410 "NETStandard.Library/2.0.3": {
411 "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
412 "type": "package",
413 "path": "netstandard.library/2.0.3",
414 "files": [
415 ".nupkg.metadata",
416 ".signature.p7s",
417 "LICENSE.TXT",
418 "THIRD-PARTY-NOTICES.TXT",
419 "build/netstandard2.0/NETStandard.Library.targets",
420 "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll",
421 "build/netstandard2.0/ref/System.AppContext.dll",
422 "build/netstandard2.0/ref/System.Collections.Concurrent.dll",
423 "build/netstandard2.0/ref/System.Collections.NonGeneric.dll",
424 "build/netstandard2.0/ref/System.Collections.Specialized.dll",
425 "build/netstandard2.0/ref/System.Collections.dll",
426 "build/netstandard2.0/ref/System.ComponentModel.Composition.dll",
427 "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll",
428 "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll",
429 "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll",
430 "build/netstandard2.0/ref/System.ComponentModel.dll",
431 "build/netstandard2.0/ref/System.Console.dll",
432 "build/netstandard2.0/ref/System.Core.dll",
433 "build/netstandard2.0/ref/System.Data.Common.dll",
434 "build/netstandard2.0/ref/System.Data.dll",
435 "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll",
436 "build/netstandard2.0/ref/System.Diagnostics.Debug.dll",
437 "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll",
438 "build/netstandard2.0/ref/System.Diagnostics.Process.dll",
439 "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll",
440 "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll",
441 "build/netstandard2.0/ref/System.Diagnostics.Tools.dll",
442 "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll",
443 "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll",
444 "build/netstandard2.0/ref/System.Drawing.Primitives.dll",
445 "build/netstandard2.0/ref/System.Drawing.dll",
446 "build/netstandard2.0/ref/System.Dynamic.Runtime.dll",
447 "build/netstandard2.0/ref/System.Globalization.Calendars.dll",
448 "build/netstandard2.0/ref/System.Globalization.Extensions.dll",
449 "build/netstandard2.0/ref/System.Globalization.dll",
450 "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll",
451 "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll",
452 "build/netstandard2.0/ref/System.IO.Compression.dll",
453 "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll",
454 "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll",
455 "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll",
456 "build/netstandard2.0/ref/System.IO.FileSystem.dll",
457 "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll",
458 "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll",
459 "build/netstandard2.0/ref/System.IO.Pipes.dll",
460 "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll",
461 "build/netstandard2.0/ref/System.IO.dll",
462 "build/netstandard2.0/ref/System.Linq.Expressions.dll",
463 "build/netstandard2.0/ref/System.Linq.Parallel.dll",
464 "build/netstandard2.0/ref/System.Linq.Queryable.dll",
465 "build/netstandard2.0/ref/System.Linq.dll",
466 "build/netstandard2.0/ref/System.Net.Http.dll",
467 "build/netstandard2.0/ref/System.Net.NameResolution.dll",
468 "build/netstandard2.0/ref/System.Net.NetworkInformation.dll",
469 "build/netstandard2.0/ref/System.Net.Ping.dll",
470 "build/netstandard2.0/ref/System.Net.Primitives.dll",
471 "build/netstandard2.0/ref/System.Net.Requests.dll",
472 "build/netstandard2.0/ref/System.Net.Security.dll",
473 "build/netstandard2.0/ref/System.Net.Sockets.dll",
474 "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll",
475 "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll",
476 "build/netstandard2.0/ref/System.Net.WebSockets.dll",
477 "build/netstandard2.0/ref/System.Net.dll",
478 "build/netstandard2.0/ref/System.Numerics.dll",
479 "build/netstandard2.0/ref/System.ObjectModel.dll",
480 "build/netstandard2.0/ref/System.Reflection.Extensions.dll",
481 "build/netstandard2.0/ref/System.Reflection.Primitives.dll",
482 "build/netstandard2.0/ref/System.Reflection.dll",
483 "build/netstandard2.0/ref/System.Resources.Reader.dll",
484 "build/netstandard2.0/ref/System.Resources.ResourceManager.dll",
485 "build/netstandard2.0/ref/System.Resources.Writer.dll",
486 "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll",
487 "build/netstandard2.0/ref/System.Runtime.Extensions.dll",
488 "build/netstandard2.0/ref/System.Runtime.Handles.dll",
489 "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll",
490 "build/netstandard2.0/ref/System.Runtime.InteropServices.dll",
491 "build/netstandard2.0/ref/System.Runtime.Numerics.dll",
492 "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll",
493 "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll",
494 "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll",
495 "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll",
496 "build/netstandard2.0/ref/System.Runtime.Serialization.dll",
497 "build/netstandard2.0/ref/System.Runtime.dll",
498 "build/netstandard2.0/ref/System.Security.Claims.dll",
499 "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll",
500 "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll",
501 "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll",
502 "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll",
503 "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll",
504 "build/netstandard2.0/ref/System.Security.Principal.dll",
505 "build/netstandard2.0/ref/System.Security.SecureString.dll",
506 "build/netstandard2.0/ref/System.ServiceModel.Web.dll",
507 "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll",
508 "build/netstandard2.0/ref/System.Text.Encoding.dll",
509 "build/netstandard2.0/ref/System.Text.RegularExpressions.dll",
510 "build/netstandard2.0/ref/System.Threading.Overlapped.dll",
511 "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll",
512 "build/netstandard2.0/ref/System.Threading.Tasks.dll",
513 "build/netstandard2.0/ref/System.Threading.Thread.dll",
514 "build/netstandard2.0/ref/System.Threading.ThreadPool.dll",
515 "build/netstandard2.0/ref/System.Threading.Timer.dll",
516 "build/netstandard2.0/ref/System.Threading.dll",
517 "build/netstandard2.0/ref/System.Transactions.dll",
518 "build/netstandard2.0/ref/System.ValueTuple.dll",
519 "build/netstandard2.0/ref/System.Web.dll",
520 "build/netstandard2.0/ref/System.Windows.dll",
521 "build/netstandard2.0/ref/System.Xml.Linq.dll",
522 "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll",
523 "build/netstandard2.0/ref/System.Xml.Serialization.dll",
524 "build/netstandard2.0/ref/System.Xml.XDocument.dll",
525 "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll",
526 "build/netstandard2.0/ref/System.Xml.XPath.dll",
527 "build/netstandard2.0/ref/System.Xml.XmlDocument.dll",
528 "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll",
529 "build/netstandard2.0/ref/System.Xml.dll",
530 "build/netstandard2.0/ref/System.dll",
531 "build/netstandard2.0/ref/mscorlib.dll",
532 "build/netstandard2.0/ref/netstandard.dll",
533 "build/netstandard2.0/ref/netstandard.xml",
534 "lib/netstandard1.0/_._",
535 "netstandard.library.2.0.3.nupkg.sha512",
536 "netstandard.library.nuspec"
537 ]
538 },
539 17 "FNA/1.0.0": {
540 18 "type": "project",
541 "path": "../../FNA/FNA.Core.csproj",
542 "msbuildProject": "../../FNA/FNA.Core.csproj"
19 "path": "../../FNA/FNA.csproj",
20 "msbuildProject": "../../FNA/FNA.csproj"
543 21 }
544 22 },
545 23 "projectFileDependencyGroups": {
546 24 ".NETFramework,Version=v4.5": [
547 "FNA >= 1.0.0",
548 "Microsoft.NETFramework.ReferenceAssemblies >= 1.0.0"
549 ],
550 ".NETStandard,Version=v2.0": [
551 "FNA >= 1.0.0",
552 "NETStandard.Library >= 2.0.3"
25 "FNA >= 1.0.0"
553 26 ]
554 27 },
555 28 "packageFolders": {
556 "/home/alys/.nuget/packages/": {},
557 "/usr/share/dotnet/sdk/NuGetFallbackFolder": {}
29 "/home/alys/.nuget/packages/": {}
558 30 },
559 31 "project": {
560 32 "version": "1.0.0",
561 33 "restore": {
562 "projectUniqueName": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.Core.csproj",
34 "projectUniqueName": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.csproj",
563 35 "projectName": "SpriteFontPlus",
564 "projectPath": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.Core.csproj",
36 "projectPath": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.csproj",
565 37 "packagesPath": "/home/alys/.nuget/packages/",
566 38 "outputPath": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/obj/",
567 39 "projectStyle": "PackageReference",
568 "crossTargeting": true,
569 "fallbackFolders": [
570 "/usr/share/dotnet/sdk/NuGetFallbackFolder"
571 ],
572 40 "configFilePaths": [
573 "/home/alys/.nuget/NuGet/NuGet.Config"
41 "/home/alys/.config/NuGet/NuGet.Config"
574 42 ],
575 43 "originalTargetFrameworks": [
576 "net45",
577 "netstandard2.0"
44 "net45"
578 45 ],
579 46 "sources": {
580 47 "https://api.nuget.org/v3/index.json": {}
581 48 },
582 49 "frameworks": {
583 50 "net45": {
584 "targetAlias": "net45",
585 51 "projectReferences": {
586 "/home/alys/repos/isometric-park-fna/FNA/FNA.Core.csproj": {
587 "projectPath": "/home/alys/repos/isometric-park-fna/FNA/FNA.Core.csproj"
588 }
589 }
590 },
591 "netstandard2.0": {
592 "targetAlias": "netstandard2.0",
593 "projectReferences": {
594 "/home/alys/repos/isometric-park-fna/FNA/FNA.Core.csproj": {
595 "projectPath": "/home/alys/repos/isometric-park-fna/FNA/FNA.Core.csproj"
52 "/home/alys/repos/isometric-park-fna/FNA/FNA.csproj": {
53 "projectPath": "/home/alys/repos/isometric-park-fna/FNA/FNA.csproj"
596 54 }
597 55 }
598 56 }
@@ -605,38 +63,7
605 63 },
606 64 "frameworks": {
607 65 "net45": {
608 "targetAlias": "net45",
609 "dependencies": {
610 "Microsoft.NETFramework.ReferenceAssemblies": {
611 "suppressParent": "All",
612 "target": "Package",
613 "version": "[1.0.0, )",
614 "autoReferenced": true
615 }
616 },
617 "runtimeIdentifierGraphPath": "/usr/share/dotnet/sdk/5.0.403/RuntimeIdentifierGraph.json"
618 },
619 "netstandard2.0": {
620 "targetAlias": "netstandard2.0",
621 "dependencies": {
622 "NETStandard.Library": {
623 "suppressParent": "All",
624 "target": "Package",
625 "version": "[2.0.3, )",
626 "autoReferenced": true
627 }
628 },
629 "imports": [
630 "net461",
631 "net462",
632 "net47",
633 "net471",
634 "net472",
635 "net48"
636 ],
637 "assetTargetFallback": true,
638 "warn": true,
639 "runtimeIdentifierGraphPath": "/usr/share/dotnet/sdk/5.0.403/RuntimeIdentifierGraph.json"
66 "runtimeIdentifierGraphPath": "/usr/lib/mono/msbuild/Current/bin/RuntimeIdentifierGraph.json"
640 67 }
641 68 }
642 69 }
@@ -1,13 +1,8
1 1 {
2 2 "version": 2,
3 "dgSpecHash": "rrWB70esJdTf9dAMXa2E6SMBq+jD6SmvcvweYYuLu7Fwj06OkeGl84NRxKWhvOqoLVKcJnfxbh2rNXh6qwNWGg==",
3 "dgSpecHash": "tOnJ1OKHA9fVe0r0rF8SXkY/g6Dsae+u1nunMHJtIiHm2UrxMmZk6x6accdLrAYlwIjYkj7fcv/RHNfOBL/3Kg==",
4 4 "success": true,
5 "projectFilePath": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.Core.csproj",
6 "expectedPackageFiles": [
7 "/home/alys/.nuget/packages/microsoft.netcore.platforms/1.1.0/microsoft.netcore.platforms.1.1.0.nupkg.sha512",
8 "/home/alys/.nuget/packages/microsoft.netframework.referenceassemblies/1.0.0/microsoft.netframework.referenceassemblies.1.0.0.nupkg.sha512",
9 "/home/alys/.nuget/packages/microsoft.netframework.referenceassemblies.net45/1.0.0/microsoft.netframework.referenceassemblies.net45.1.0.0.nupkg.sha512",
10 "/home/alys/.nuget/packages/netstandard.library/2.0.3/netstandard.library.2.0.3.nupkg.sha512"
11 ],
5 "projectFilePath": "/home/alys/repos/isometric-park-fna/SpriteFontPlus/src/SpriteFontPlus.FNA.csproj",
6 "expectedPackageFiles": [],
12 7 "logs": []
13 8 } No newline at end of file
@@ -35,8 +35,11
35 35 Trees:
36 36 - Add basic maintenance cost @milestone(1: Basic Money) @done(2021-01-27)
37 37 - Add basic age simulation
38 - Add water @milestone(6: Trees and Tiles)
38 - Add water @milestone(6: Trees and Tiles) @done(2022-07-24)
39 39 - Biodiversity @maybe @milestone(6: Trees and Tiles)
40 - Tree Types @done(2022-01-27)
41 - Grass?
42 - Biodiversity score?
40 43 - Research agreements @maybe
41 44 - Forest rangers allocatable as law enforcement? @maybe
42 45 Have to think about thematic implications
@@ -44,6 +47,21
44 47 Seems like a good way to get started?
45 48 Reduces cost of vandalism repair?
46 49 - Sell Firewood?
50 - Preserve @milestone(6: Trees and Tiles)
51 - Add preserve tool @done(2021-02-17)
52 - Add bulldozer @done(2022-03-16)
53 - Adjust odds in preserve @done(2021-02-20)
54 - Dialog
55 - Assistant warns when a lot of the map has been made into preserve?
56 Maybe a lot made into preserve at once?
57 - Congratulations when reaching a majority @done(2022-12-14)
58 Maybe 75 percent
59 - Make them less easy to game
60 Right now they are free to add and remove, meaning you could make the whole map preserve until you need it for something else
61 One option: penalize if user switches them too early
62 Another option: charge nominal amount
63 Another option: benefits take time to accrue. Avoids punishment
64 Maybe a combination: benefits accrue after an area has been preserved for a while? Tourism ceases immediately. And you don't get offers to build on that land? Or fewer offers?
47 65 Staff:
48 66 - Ranger staffing? @maybe @milestone(1: Basic Money)
49 67 - Staffing window
@@ -54,6 +72,9
54 72 - Employee training mechanic @maybe
55 73 Leisure:
56 74 - Add way to mark off area for leisure @milestone(7: Leisure)
75 Maybe add leisure items instead?
76 Or both?
77 - Add paths @milestone(7: Leisure)
57 78 - Basic satisfaction @milestone(7: Leisure)
58 79 - Set
59 80 End games/outcomes:
@@ -62,7 +83,7
62 83 - Self-sufficient
63 84 i.e., no need for subsidy
64 85 May not be ending
65 - Forest mismanagement @milestone(5: Events)
86 - Forest mismanagement @milestone(5: Events) @done(2021-12-12)
66 87 - Figure out threshold
67 88 - High biodiversity? @maybe
68 89 - High satisfaction
@@ -83,7 +104,7
83 104 Misc:
84 105 - Assistant commentary @milestone(5: Events)
85 106 Need to ensure it's not annoying
86 - Basic random events
107 - Basic random events
87 108 - Tree planting campaign @done(2021-09-28) @milestone(5: Events)
88 109 - Friends of the park fundraiser @done(2021-11-07) @milestone(5: Events)
89 110 - Federal grant @done(2021-11-27) @milestone(5: Events)
@@ -94,14 +115,21
94 115 would probably have to animate
95 116 - Disease
96 117 - Photos for dialog?
97 - Graphs window
118 - Graphs window @done(2021-01-05)
98 119 Could use ImPlot for this
99 120
100 121 Structure:
101 - Add modes
122 - Add modes
102 123 - Refactor stuff out of FNAGame
103 124 At this point, virtually everything in FNAGame is setting up key Engines or doing drawing
104 125 - Saving @prototyped @milestone(4: Beginning)
126 - Options are duplicated in too many places:
127 - Replace Options with OptionComponent?
128 - Put Options in OptionMessage?
129 - Remove Options from Encompass?
130 Options don't seem like a great fit for th ECS model.
131 - OptionsWindow should use two Options instances instead of recreating each field.
132 Adding an option requires adding variabls
105 133 - Encompass @maybe @done(2021-04-03)
106 134 Currently thinking about a hybrid model where the Simulation class receives a lot of the events from Encompass. so things like Events, Contracts, and Research agreements are handled by Encompass. Perhaps Input, too?
107 135 - Ensure library loads
@@ -144,7 +172,40
144 172 - Additional in-game menu
145 173 - Save
146 174 - Save & Quit
175 - Fix selection
176 Selections require two components to really work, which is messy and doesn't really fit. A Selection without some sort of associated selection that describes what's selected doesn't really work
177 - Turn tools into classes?
178 Creating a shallow hierarchy seems a little nicer than the current setup.
147 179
180 Music and Audio:
181 Sound Effects:
182 - Generic click sound (push button) @done(2022-05-09)
183 - Cheer/boo crowd sound effect
184 This is a sorta easter egg and a reference to SimCity
185 - Explosion effect (for bulldozer)
186
187 Performance:
188 Issues:
189 - Seeing up to 32 ms in update on framework-release? @done(2022-05-16)
190 - Drawing very large areas is very slow. @done(2022-05-16)
191 Sorta fixed
192 - Slows to a halt (~7fps) when drawing many preserve squares.
193 Drawing each tile individually is very silly when it's just a (big) square anyway.
194 For edges: Using a dictionary with counts doesn't work either. (~5 fps) Nor using sets.
195 Instead need to do the fill and edge-drawing as large regions.
196 - Draw slows down after merely leaving it running @done(2022-11-14)
197 Debug issue; could be faster but basically solved
198 Structural improvements:
199 - Button to clear/thin debug buffers?
200 Take every nth to reduce counters to past 100 measurements
201 - Disable some timing code in release mode?
202 Needs some way to enable it.
203 - Avoid redrawing tiles every time?
204 Draw tiles once into buffer
205 Instrumentation:
206 - Time individual sections of update loop @done(2022-05-16)
207 - Time simulation @done(2022-05-16)
208 - Time each engine?
148 209 Other features:
149 210 Accessibility:
150 211 - Verify contrast
@@ -181,29 +242,54
181 242 Internationalization:
182 243 - Probably won't pay to translate or anything, but should consider setting up the structure @maybe @milestone(4: Beginning)
183 244 If nothing else, might be useful for future projects.
245 Balance:
246 - Hard mode is impossible with current map size.
247 Upkeep is too much money.
248 Might be addressed by adding staff instead of fixed upkeep.
184 249 Bugs:
185 250 Graphics:
186 - Trees jump around when pressing show/hide grid
251 - Trees jump around when pressing show/hide grid @done(2022-01-23)
187 252 - Grids sometimes overlap trees, including area overlays
188 - Trees sometimes
253 - Trees sometimes overlap each other @done(2022-01-23)
254 - Area overlays overlap trees @done(2022-01-24)
189 255 - Sometimes framerate jumps to 180-200 fps. (Better than reverse, but kinda weird)
190 256 - Graphics don't adjust for the resolution
191 257 - Scroll area @done(2021-06-23)
192 258 - Ingame Menu @done(2021-06-22)
193 259 - Main Menu
194 260 Simulation:
261 - Can keep playing after losing if you don't acknowledge the loss in the dialog
262 - Create preemption/priority system
263 Have to decide whether to have two levels: normal/preempting or a series of priorities
195 264 - Expired areas can't be reused. @done(2021-08-07)
265 - Trees seem to spawn in lines.
266 Is it only spawning neighbor trees in one direction?
196 267 Dialog:
197 268 - Dialogs don't appear after
269 Crashes/Stability:
270 - News window crashes.
271 - Drawing error when clicking sometimes on main screen. @done(2022-04-27)
272 Tries to draw area?
273 - Crash when extending preserve past bottom. @done(2022-04-27)
274 - Segfault on quit (when it tries to dispose of the sound) or on playing sound on Linux
275 May be due to a quirk of my Linux setup
276 - Weird ImGui crash:
277 dotnet: /home/alys/repos/outside/ImGui.NET-nativebuild/cimgui/imgui/imgui.cpp:6293: bool ImGui::Begin(const char*, bool*, ImGuiWindowFlags): Assertion `name != __null && name[0] != '\0'' failed.
278 - Crashes after exiting a game.
279 Seems to be a draw issue (Batch hasn't begun.)
280 In Area renderer?
281 Also happens when you lose.
282 Unhandled exception: System.InvalidOperationException: Draw was called, but Begin has not yet been called. Begin must be called successfully before you can call Draw.
283 - No handler for Ink errors.
284 There really shouldn't be any way to run into an Ink error, but they will probably slip in.
198 285 Misc:
286 - Starting a game after exiting a previous one doesn't really work, afaict
287 Also crases, but I suspect the crash isn't related.
199 288 - Events may not be deleted
200 289 - Exits are messy (does Encompass add threading?) @done(2021-11-28)
201 Appears to be fixed by using Game.Exit
290 Appears to be fixed by using Game.Exit
202 291 [xcb] Unknown sequence number while appending request
203 292 [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
204 293 [xcb] Aborting, sorry about that.
205 294 dotnet: ../../src/xcb_io.c:145: append_pending_request: Assertion `!xcb_xlib_unknown_seq_number' failed.
206 295 Aborted (core dumped)
207 - Segfault on quit (when it tries to dispose of the sound) or on playing sound on Linux
208 May be due to a quirk of my Linux setup
209
@@ -5,10 +5,6
5 5 MinimumVisualStudioVersion = 10.0.40219.1
6 6 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "isometric-park-fna-core", "isometric-park-fna\isometric-park-fna-core.csproj", "{4BA11D6F-B980-4E5B-99FE-729AD3D34A12}"
7 7 EndProject
8 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImPlot.NET", "ImPlot.NET\ImPlot.NET.csproj", "{50014300-51ED-4F7B-B72E-16BE29FBAE95}"
9 EndProject
10 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImGui.NET.Core", "ImGui.NET\ImGui.NET.Core.csproj", "{E7AB4506-A404-4BE8-AF71-5486AD9EBC71}"
11 EndProject
12 8 Global
13 9 GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 10 Debug|Any CPU = Debug|Any CPU
@@ -13,8 +13,6
13 13 EndProject
14 14 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "encompass-cs", "encompass-cs\encompass-cs\encompass-cs.csproj", "{D0CCEB74-D8A8-446A-AFFC-2B043DAF1E5F}"
15 15 EndProject
16 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImPlot.NET", "ImPlot.NET\ImPlot.NET.csproj", "{11118CB6-165C-4459-B5F4-54843206025E}"
17 EndProject
18 16 Global
19 17 GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 18 Debug|anycpu = Debug|anycpu
@@ -1,18 +1,34
1 using System;
1 using System;
2 2 using System.Collections.Generic;
3 3
4 using Microsoft.Xna.Framework;
5
4 6 namespace isometricparkfna
5 7 {
6 8
7 9 public class CellMap
8 10 {
9 11 public List<List<Cell>> cells;
12 public List<Vector2> WaterCells;
13
14 //Defaults; overridden by settings from FNAGame in practice:
10 15 public int MapWidth = 50;
11 16 public int MapHeight = 50;
12 17
13 18 public int ZoneWidth = 10;
14 19 public int ZoneHeight = 10;
15 20
21
22 //These coefficients modify values I set based on the original 50x50 maps.
23 //Eventually I'll probably allow for multiple map sizes, so instead of changing those constants,
24 //I'm adding a multiplier based on the size of the map.
25 //
26 //What's the difference between these two multipliers?
27 //If you double the sides of the map, the linear multiplier is 2,
28 //but the area multiplier is 4 (2 x 2).
29 public int LinearMultiplier;
30 public int AreaMultiplier;
31
16 32 public int tree_count
17 33 {
18 34 get
@@ -42,7 +58,6
42 58 }
43 59 }
44 60
45
46 61 public CellMap()
47 62 {
48 63 //TileMap(MapWidth, MapHeight);
@@ -55,6 +70,12
55 70
56 71 this.cells = new List<List<Cell>>();
57 72
73 //Cached:
74 this.WaterCells = new List<Vector2>();
75
76 this.LinearMultiplier = (int)(((this.MapWidth / 50) + (this.MapHeight / 50)) / 2);
77 this.AreaMultiplier = (int)((this.MapWidth * this.MapHeight) / (50 * 50));
78
58 79 for (int i = 0; i < height; i++)
59 80 {
60 81 List<Cell> newRow = new List<Cell>();
@@ -74,7 +95,7
74 95 {
75 96 foreach (Cell cell in row)
76 97 {
77 if (cell.hasTree)
98 if (cell.HasTree)
78 99 {
79 100 yield return cell;
80 101 }
@@ -88,7 +109,7
88 109 {
89 110 foreach (Cell cell in row)
90 111 {
91 if (cell.hasTree)
112 if (cell.HasTree)
92 113 {
93 114 yield return cell;
94 115 }
@@ -112,7 +133,7
112 133 return MathUtils.BetweenExclusive(x, 0, MapWidth - 1) && MathUtils.BetweenExclusive(y, 0, MapHeight - 1);
113 134 }
114 135
115 private System.Collections.Generic.IEnumerable<Cell> iterate_neighbors(int x, int y)
136 public System.Collections.Generic.IEnumerable<Cell> iterate_neighbor_cells(int x, int y)
116 137 {
117 138 //iterates over neighbors (clockwise starting at noon/midnight)
118 139 if (inBounds(x, y + 1))
@@ -149,12 +170,61
149 170 }
150 171 }
151 172
173 public System.Collections.Generic.IEnumerable<(int, int)> iterate_neighbor_cell_locations(int x, int y)
174
175 {
176 //iterates over neighbors (clockwise starting at noon/midnight)
177 if (inBounds(x, y + 1))
178 {
179 yield return (x - 1, y);
180 }
181 if (inBounds(x + 1, y + 1))
182 {
183 yield return (x + 1, y + 1);
184 }
185 if (inBounds(x + 1, y))
186 {
187 yield return (x + 1, y);
188 }
189 if (inBounds(x + 1, y - 1))
190 {
191 yield return (x + 1, y - 1);
192 }
193 if (inBounds(x, y - 1))
194 {
195 yield return (x, y - 1);
196 }
197 if (inBounds(x - 1, y-1))
198 {
199 yield return (x - 1, y-1);
200 }
201 if (inBounds(x - 1, y))
202 {
203 yield return (x - 1, y);
204 }
205 if (inBounds(x - 1, y + 1))
206 {
207 yield return (x - 1, y+1);
208 }
209 }
210
211
212 public System.Collections.Generic.IEnumerable<Cell> iterate_neighbors(int x, int y)
213 {
214 foreach (Cell neighbor in this.iterate_neighbor_cells(x, y))
215 {
216 if (neighbor.HasTree) {
217 yield return neighbor;
218 }
219 }
220 }
221
152 222 private int countNeighbors(int x, int y)
153 223 {
154 224 int count = 0;
155 foreach (Cell neighbor in this.iterate_neighbors(x, y))
225 foreach (Cell neighbor in this.iterate_neighbor_cells(x, y))
156 226 {
157 if (neighbor.hasTree) {
227 if (neighbor.HasTree) {
158 228 count++;
159 229 }
160 230 }
@@ -162,6 +232,17
162 232 return count;
163 233 }
164 234
235 public static Vector2 calculateMousegrid(Vector2 normalizedMousePos)
236 {
237 Vector2 adjust = new Vector2(Tile.TileSpriteWidth / 2, Tile.TileSpriteHeight);
238 Vector2 adjustedMousePos = normalizedMousePos - adjust;
239
240 float boardx = ((adjustedMousePos.X / Tile.TileSpriteWidth) + (adjustedMousePos.Y / Tile.TileSpriteHeight));
241 float boardy = ((adjustedMousePos.Y / Tile.TileSpriteHeight) - (adjustedMousePos.X / Tile.TileSpriteWidth));
242
243 return new Vector2((int)boardx, (int)boardy);
244 }
245
165 246 public System.Collections.Generic.IEnumerable<Cell> iterate_cells_with_neighbors(int neighbors)
166 247 {
167 248 for (int i = 0; i < MapHeight; i++)
@@ -175,44 +256,93
175 256 }
176 257 }
177 258 }
259 }
178 260
179
261 public System.Collections.Generic.IEnumerable<(int, int)> iterate_cell_locations_with_neighbors(int neighbors)
262 {
263 for (int i = 0; i < MapHeight; i++)
264 {
265 List<Cell> newRow = new List<Cell>();
266 for (int j = 0; j < MapWidth; j++)
267 {
268 if (this.countNeighbors(i, j) >= neighbors)
269 {
270 yield return (i, j);
271 }
272 }
273 }
180 274 }
181 275
182 276 public enum CellStatus {
183 277 Clear,
184 278 LivingTree,
185 DeadTree
279 DeadTree,
280 Water
281 }
282
283 public enum TreeType {
284 Oak,
285 GenericEvergreen,
286 GenericDeciduous,
287 GenericShrub
186 288 }
187 289
188 290 public class Cell
189 291 {
190 // public Boolean _hasTree = false;
191 public CellStatus status {
292 public CellStatus Status {
293 get;
294 private set;
295 }
296
297 public String StatusAdjective {
298 get {
299 return this.Status.ToString().Replace("Tree", "");
300 }
301 }
302
303 public TreeType Type {
192 304 get;
193 305 private set;
194 306 }
195 307
196 public Boolean hasTree {
308 public String TypeName {
309 get {
310 return this.Type.ToString().Replace("Generic", "");
311 }
312 }
313
314 public Boolean HasTree {
197 315 get {
198 return this.status == CellStatus.LivingTree;
316 return this.Status == CellStatus.LivingTree;
317 }
318 }
319
320 public Boolean HasWater {
321 get {
322 return this.Status == CellStatus.Water;
199 323 }
200 324 }
201 325
202 public DateTime planted;
326 public DateTime Planted;
203 327
204 public void addTree(DateTime datetime) {
205 this.status = CellStatus.LivingTree;
328 public void AddTree(DateTime datetime, TreeType type) {
329 this.Status = CellStatus.LivingTree;
206 330
207 this.planted = datetime;
331 this.Planted = datetime;
332
333 this.Type = type;
208 334 }
209 335
210 public void removeTree() {
211 this.status = CellStatus.Clear;
336 public void AddWater() {
337 this.Status = CellStatus.Water;
212 338 }
213 339
214 public void markTreeDead() {
215 this.status = CellStatus.DeadTree;
340 public void RemoveTree() {
341 this.Status = CellStatus.Clear;
342 }
343
344 public void MarkTreeDead() {
345 this.Status = CellStatus.DeadTree;
216 346 }
217 347 }
218 348 }
@@ -1,4 +1,3
1
2 1 using Microsoft.Xna.Framework;
3 2
4 3 using Encompass;
@@ -7,5 +6,6
7 6
8 7 public struct AreaComponent : IComponent {
9 8 public Vector2[] squares;
9 public Tool Tool;
10 10 }
11 11 }
@@ -5,7 +5,6
5 5
6 6 public struct BudgetLineComponent : IComponent
7 7 {
8
9 8 public string category;
10 9 public decimal amount;
11 10 }
@@ -4,6 +4,8
4 4
5 5 public struct OptionsComponent : IComponent {
6 6 public ProfanityLevel ProfanitySetting;
7 public float SoundEffectVolume;
8 public bool SoundEffectMuted;
7 9
8 10 }
9 11 }
@@ -3,7 +3,15
3 3
4 4 namespace isometricparkfna.Components
5 5 {
6 public enum SelectionType {
7 None,
8 Window, //Selected in a window
9 Area, //Selecting an area
10 Tool //Selecting a tool
11 }
12
6 13 public struct SelectedComponent : IComponent {
7 14 public bool selected;
15 public SelectionType Type;
8 16 }
9 } No newline at end of file
17 }
@@ -2,14 +2,16
2 2 VAR playerSwears = 0
3 3 VAR playerRude = 0
4 4
5
5 6 VAR GovernorOpinion = 0
7 VAR HeadOfParksOpinion = 0
6 8
7 9 LIST assistantTraits = shy, esoteric, sweary
8 10
9 11
10 12 EXTERNAL endGame()
11 13
12
14 EXTERNAL undoPreserve()
13 15
14 16
15 17 //This is needed to make both including and for jumping to dialog sections work:
@@ -50,7 +52,7
50 52 Governor: Welcome to your new park, director!
51 53
52 54 * [Okay]
53 Governor: Make sure that you keep visitors happy and the budget in the black! You're currently getting an annual grant out of my budgetβ€”it'd sure be nice if you park were self-sufficient so we could drop that expense!
55 Governor: Make sure that you keep visitors happy and the budget in the black! You're currently getting an annual grant out of my budgetβ€”it'd sure be nice if you park were self-sufficient so we could drop that expense!
54 56
55 57 * * [And I need to keep the forest healthy, too, right?]
56 58 ~ GovernorOpinion = GovernorOpinion - 1
@@ -299,7 +301,7
299 301 Head of Parks: What the hell do you think you're doing, you absolute piece of shit?!?
300 302
301 303
302 * {- not MeetHeadofPark } Sorry, who are you? -> MeetHeadofPark ->
304 * {- not MeetHeadofPark } [Sorry, who are you?] -> MeetHeadofPark ->
303 305 -> Screwed
304 306
305 307 + [Uhh, what the fuck?]
@@ -311,4 +313,89
311 313 Head of Parks: Look at this park, it has anxiety! You did that you megadick.
312 314 ++ [...]
313 315 Head of Parks: Yeah, you'd better stay quiet. I don't want to hear a single word out of your fucking useless knifewound of a mouth.
314 -> END No newline at end of file
316 -> END
317
318
319 === PreserveProgress ===
320 Head of Parks: Hey, you goddam dunderhead. A quarter of this park is now a preserve! {inc(HeadOfParksOpinion)}
321
322
323 * {- not MeetHeadofPark } [Sorry, who are you?] -> MeetHeadofPark
324 -> WhatPreserves
325
326 + [And you're mad?]
327 Head of Parks: No, you vainglorious buffoon! I'm pretty goddamn pleased. -> WhatPreserves
328 + [Right!]
329 -> WhatPreserves
330
331 = WhatPreserves
332 Head of Parks: I goddamn love preserves. The peach kind. The strawberry kind. But especially the park kind. The trees are left alone. They fucking flourish! Do you think you could fucking photosynthese with people traipsing all over?
333
334 + [No?]
335 Head of Parks: You're goddamn right! You couldn't! Do you know how many preserves have been added since our cuntforsaken governor took office in 2014???
336 ++ [Uh one?]
337 Head of Parks: Not even one! -> Zero
338
339 ++ [None?]
340 Head of Parks: Bingo, my motherfucker -> Zero
341
342 ++ [HellifIknow] {inc(playerSwears)}
343 Head of Parks: Least your honest. -> Zero
344
345 ++ [One dozen]
346 Head of Parks: What? Not even close. -> Zero
347
348 ++ [One Hundred]
349 Head of Parks: What? Not even close. -> Zero
350
351 ++ [One billion]
352 Head of Parks: Fuck off. {dec(HeadOfParksOpinion)} -> HeadofParkSideRant
353 Anyway, it's not a billion!! -> Zero
354
355 = Zero
356 Head of Parks: It's zero! Zero new preserves on God's green earth. Or brown earth. I swear to god...
357 -> END
358
359 === PreserveHalf ===
360 Head of Parks: Hey, you goddam wunderkind. A whole half of this park is now a preserve! {inc(HeadOfParksOpinion)}
361
362 In fact, I want to shake your bloody hand!
363
364 + [Sure!] {inc(HeadOfParksOpinion)}
365 -> PostShake
366
367 + [Umm..okay]
368 -> PostShake
369
370 + [No thanks]
371 -> PostShake
372
373 + [No, you have germs] {dec(HeadOfParksOpinion)}
374 Head of Parks: Bloody hell, I wash! -> PostShake
375
376 = PostShake
377 Head of Parks: Anywyay, you're doing great. If that bloody governor gives you any shit, send him my way. And I think I can scrounge up some money to help you keep the park running.
378
379 + [Thanks]
380 -> END
381
382
383
384 === HeadofParkSideRant ===
385 Head of Parks: Are you fucking with me? Really fucking with me? Listen, you motherfucking piss-eared shit-for-brains backroad bureaucrat, I didn't come hear from the fucking capitol building holding up the whole natural resources administrative state like MiracleGrow Atlas to get scoffed at by a tinpot administrator who think 100 acres and a desk makes you some sort of important person. Aplogize!
386 + [Sorry] ->->
387
388
389 === LargePreserve ===
390 \#assistantName\#: I noticed you reserved quite a bit of space for a nature preserve. Remember that these are unavailable for leisure use or development.
391 + [Isn't it great!]
392 \#assistantName\#: Ummm. Yeah! It is.
393 -> END
394 + [It's fine.]
395 -> END
396 + [Thanks for checking in.]
397 -> END
398 + [I know what I'm doing! Never question me again!] {inc(playerRude)}
399 -> END
400 + [Maybe I've overreached. (Undoes Preserve)] { undoPreserve() }
401 -> END
@@ -1,1 +1,1
1 {"inkVersion":20,"root":[[["done",{"#n":"g-0"}],null],"done",{"placeholder":["end",null],"alter":[{"temp=":"k"},{"temp=":"x"},"ev",{"VAR?":"x"},{"VAR?":"k"},"+","/ev",{"temp=":"x","re":true},null],"inc":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"+","/ev",{"temp=":"x","re":true},null],"dec":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"-","/ev",{"temp=":"x","re":true},null],"endGame":["ev","void","/ev","~ret",null],"Once":[["^Once upon a time...","\n",["ev",{"^->":"Once.0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":2},{"s":["^There were two choices.",{"->":"$r","var":true},null]}],["ev",{"^->":"Once.0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":2},{"s":["^There were four lines of content.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"Once.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},null],"c-1":["ev",{"^->":"Once.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},null],"g-0":["^They lived happily ever after.","\n","end",null]}],null],"IntroGovernor":[["^Governor: Welcome to your new park, director!","\n","ev","str","^Okay","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^Governor: Make sure that you keep visitors happy and the budget in the black! You're currently getting an annual grant out of my budgetβ€”it'd sure be nice if you park were self-sufficient so we could drop that expense!","\n",["ev","str","^And I need to keep the forest healthy, too, right?","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Sounds good!","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","ev",{"VAR?":"GovernorOpinion"},1,"-","/ev",{"VAR=":"GovernorOpinion","re":true},"^Governor: Ummm, yeah","\n",["ev","str","^...","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","end",{"#f":5}]}],{"#f":5}],"c-1":["\n","ev",{"VAR?":"GovernorOpinion"},1,"+","/ev",{"VAR=":"GovernorOpinion","re":true},"^Governor: I'll check in soon.","\n","end",{"#f":5}]}],{"#f":5}]}],null],"IntroAssistant":[["^#assistantName#: Hello. I'm #assistantName#.","\n","ev","str","^Nice to meet you.","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^#assistantName#: You can use the mouse or arrow keys to move around, and the plus and minus keys to zoom in and out. B opens the budget and F lets you adjust Forest Policy.","\n",["ev","str","^Got it, thanks.","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^How are you?","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^#assistantName#: Bye","\n","end",{"#f":5}],"c-1":["\n","^#assistantName#: #howdoing#","\n","end",{"#f":5}]}],{"#f":5}]}],null],"BadNewsReact":[["ev","str","^Damn.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Fuck.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Shoot.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^*Sigh.* Fine.","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^Who cares?","/str","/ev",{"*":".^.c-4","flg":4},{"c-0":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-1":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-2":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-3":["\n","ev","void","/ev","->->",null],"c-4":["\n","ev","void","/ev","->->",null]}],null],"AssistantAcknowlege":[["ev","str","^Thanks.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Mmmm hmm.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Get to it.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^I really appreciate it, #assistantName#","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev","void","/ev","->->",null],"c-1":["\n","ev","void","/ev","->->",null],"c-2":["^ ","ev",{"^var":"playerRude","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-3":["\n",{"->":".^.^.^.Appreciate"},null]}],{"Appreciate":["^#assistantName#: ","ev",{"VAR?":"assistantTraits"},{"VAR?":"shy"},"?","/ev",[{"->":".^.b","c":true},{"b":["^...",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":[["ev","visit",3,"seq","/ev","ev","du",0,"==","/ev",{"->":".^.s0","c":true},"ev","du",1,"==","/ev",{"->":".^.s1","c":true},"ev","du",2,"==","/ev",{"->":".^.s2","c":true},"nop",{"s0":["pop","^No problem.",{"->":".^.^.23"},null],"s1":["pop","^Oh, you're welcome.",{"->":".^.^.23"},null],"s2":["pop","^My pleasure.",{"->":".^.^.23"},null],"#f":5}],{"->":".^.^.^.8"},null]}],"nop","\n","ev","void","/ev","->->",null]}],"MassVandalism":[["^#assistantName#: Bad news, director.","\n","ev","str","^Oh?","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^#assistantName#: A number of trees have been seriously damaged overnight.","\n",["ev","str","^How bad are they?","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^#assistantName#: I'm no botanist, but they're not great. The gouges are pretty deep.","\n",{"->t->":"BadNewsReact"},"^#assistantName#: Yeah, it's ","ev",{"VAR?":"assistantTraits"},{"VAR?":"sweary"},"?","/ev",[{"->":".^.b","c":true},{"b":["^fucking",{"->":".^.^.^.11"},null]}],"nop","^ awful.","\n","^I'll see who's around and get to cleaning.","\n",{"->t->":"AssistantAcknowlege"},"end",null]}],null]}],null],"LowFunds":[["^#assistantName#: Director, our funds are getting dangerously low!","\n","ev","str","^Don't worry about it. I have a plan.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^I know.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Stop bothering me with things I already know!","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Have any ideas?","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^What?","/str","/ev",{"*":".^.c-4","flg":4},{"c-0":["\n","end",null],"c-1":["\n","end",null],"c-2":["^ ","ev",{"^var":"playerRude","ci":-1},{"f()":"inc"},"out","/ev","\n","end",null],"c-3":["\n","^#assistantName#: Consider accepting some contracts. Even if they're not the best terms, they'll keep us from running out of money.","\n","end",null],"c-4":["\n","^#assistantName#: Yes, we have less than $25,000. We're running the risk of a default.","\n",{"->t->":"BadNewsReact"},"^#assistantName#: I know! consider accepting some contracts. Even if they're not the best terms, they'll keep us from running out of money.","\n","end",null]}],null],"VeryLowFunds":[["^Governor: Director, you have almost no reserve funds. This isn't acceptable.","\n","ev",{"CNT?":".^.^"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^ I can't believe I'm having this conversation with you again. ",{"->":".^.^.^.8"},null]}],"nop","\n","ev","str","^I know. I'm working on it.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Have any ideas?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^What happens if I run out of money?","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^What?","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","^Governor: For your sake, I hope so.","\n","end",null],"c-1":["\n","^Governor: Accept some contracts. Now's not the time to worry about sustainability, or whatever you natural resources types care about. Just take the deal. They'll keep you from running out of money.","\n","end",null],"c-2":["\n",{"->":".^.^.^.WhatHappens"},null],"c-3":["\n",{"->":".^.^.^.Surprise"},null]}],{"Surprise":[["^Governor: Is this a *surprise* to you?","\n","ev","str","^Uh, um, no.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Honestly, yes.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^What happens if I run out of money?","/str","/ev",{"*":".^.c-2","flg":4},{"c-0":["\n","^Governor: Well, I hope you have a plan...","\n","^For your sake.","\n","end",null],"c-1":["\n","^Governor: Well! I appreciate your directness. But I hope you have a plan...","\n","^For your sake.","\n","end",null],"c-2":["\n",{"->":".^.^.^.^.WhatHappens"},null]}],null],"WhatHappens":[["^Governor: If you run out of money entirely...","\n","^The park will be fine, in the long run. The state department of natural resources will use its funds to bail the park out. Someone from my office will come in and trim the budget.","\n","^You, however, will be asked to resign.","\n","ev","str","^And if I don't resign?","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^I understand.","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n","^Governor: I'll fire you.","\n",["ev","str","^Oh.","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","end",null]}],null],"c-1":["\n","end",null]}],null],"#f":1}],"EndLowFunds":[["^Governor: I've warned you.","\n","ev","str","^I understand. I resign. (Game Over)","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["^ ","ev",{"x()":"endGame"},"out","/ev","\n","end",null]}],null],"MeetFriendOfThePark":[["^#friendOfThePark#: Hi, I'm the president of the Friends of the Park. Nice to meet you!","\n","ev","str","^Nice to meet you!","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Ahh.","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^I've been expecting you.","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","ev","void","/ev","->->",{"#f":5}],"c-1":["\n","ev","void","/ev","->->",{"#f":5}],"c-2":["\n","^#friendOfThePark#: Huh!","\n","ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"Fundraiser":[["ev",{"CNT?":"MeetFriendOfThePark"},"!","_","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"MeetFriendOfThePark"},{"->":".^.^.^.6"},null]}],"nop","\n","^#friendOfThePark#: I'm happy to announce the completion of our fundraiser! You won't guess how much we made!","\n","ev","str","^Please don't make me guess.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Okay...","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n","^#friendOfThePark#: It's more fun if you guess.","\n",["ev","str","^ Fine.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Well, I don't enjoy it.","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n",{"->":"Fundraiser.Guess"},null],"c-1":["\n",{"->":"Fundraiser.Amount"},null]}],null],"c-1":["\n",{"->":".^.^.^.Guess"},null]}],{"Guess":[["^#friendOfThePark#:","\n","ev","str","^$1,000?","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^$5,000?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^$10,000?","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^$25,000?","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^$1 million?","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^$1 billion?","/str","/ev",{"*":".^.c-5","flg":4},"ev","str","^I give up.","/str","/ev",{"*":".^.c-6","flg":4},{"c-0":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-1":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-2":["\n","^#friendOfThePark#: You're right!","\n",{"->":".^.^.^.^.Amount"},null],"c-3":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-4":["\n","^#friendOfThePark#: No, haha. I wish!","\n",{"->":".^.^.^"},null],"c-5":["\n","^#friendOfThePark#: Not quite that high, heh","\n",{"->":".^.^.^"},null],"c-6":["\n",{"->":".^.^.^.^.Amount"},null]}],null],"Amount":["^#friendOfThePark#: Anyway. we made $10,000!","\n","end",null]}],"GovernmentGrant":[["^Governor: Good news, director. You've been awarded a federal grant.","\n","ev","str","^Awesome","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Sounds good","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n",{"->":".^.^.^.Money"},null],"c-1":["\n",{"->":".^.^.^.Money"},null]}],{"Money":["^Governor: Well, it won't last forever. Don't get dependent on it.","\n","end",null]}],"MeetHeadofPark":["^Head of Parks: I'm the fucking head of parks, that's who I am, you absolute motherfucker. ","ev","void","/ev","->->","\n",{"#f":1}],"PoorTreeHealth":[["^Head of Parks: What the hell do you think you're doing, you absolute piece of shit?!?","\n",["ev",{"^->":"PoorTreeHealth.0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str",{"CNT?":"MeetHeadofPark"},"!","_","/ev",{"*":".^.^.c-0","flg":19},{"s":["^Sorry, who are you? ",{"->":"$r","var":true},null]}],"ev","str","^Uhh, what the fuck?","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["ev",{"^->":"PoorTreeHealth.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],{"->t->":"MeetHeadofPark"},"\n",{"->":".^.^.^.Screwed"},{"#f":5}],"c-1":["\n",{"->":".^.^.^.Screwed"},null]}],{"Screwed":[["^Head of Parks: We're all fucking screwed and it's your fault, you colossal shitheel.","\n","ev","str","^...","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^Head of Parks: Look at this park, it has anxiety! You did that you megadick.","\n",["ev","str","^...","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^Head of Parks: Yeah, you'd better stay quiet. I don't want to hear a single word out of your fucking useless knifewound of a mouth.","\n","end",null]}],null]}],null]}],"global decl":["ev",0,{"VAR=":"playerSwears"},0,{"VAR=":"playerRude"},0,{"VAR=":"GovernorOpinion"},{"list":{},"origins":["assistantTraits"]},{"VAR=":"assistantTraits"},"/ev","end",null]}],"listDefs":{"assistantTraits":{"shy":1,"esoteric":2,"sweary":3}}} No newline at end of file
1 {"inkVersion":20,"root":[[["done",{"#n":"g-0"}],null],"done",{"placeholder":["end",null],"alter":[{"temp=":"k"},{"temp=":"x"},"ev",{"VAR?":"x"},{"VAR?":"k"},"+","/ev",{"temp=":"x","re":true},null],"inc":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"+","/ev",{"temp=":"x","re":true},null],"dec":[{"temp=":"x"},"ev",{"VAR?":"x"},1,"-","/ev",{"temp=":"x","re":true},null],"endGame":["ev","void","/ev","~ret",null],"Once":[["^Once upon a time...","\n",["ev",{"^->":"Once.0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":2},{"s":["^There were two choices.",{"->":"$r","var":true},null]}],["ev",{"^->":"Once.0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":2},{"s":["^There were four lines of content.",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"Once.0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},null],"c-1":["ev",{"^->":"Once.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},null],"g-0":["^They lived happily ever after.","\n","end",null]}],null],"IntroGovernor":[["^Governor: Welcome to your new park, director!","\n","ev","str","^Okay","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^Governor: Make sure that you keep visitors happy and the budget in the black! You're currently getting an annual grant out of my budgetβ€”it'd sure be nice if you park were self-sufficient so we could drop that expense!","\n",["ev","str","^And I need to keep the forest healthy, too, right?","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Sounds good!","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["^ ","\n","ev",{"VAR?":"GovernorOpinion"},1,"-","/ev",{"VAR=":"GovernorOpinion","re":true},"^Governor: Ummm, yeah","\n",["ev","str","^...","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","end",{"#f":5}]}],{"#f":5}],"c-1":["\n","ev",{"VAR?":"GovernorOpinion"},1,"+","/ev",{"VAR=":"GovernorOpinion","re":true},"^Governor: I'll check in soon.","\n","end",{"#f":5}]}],{"#f":5}]}],null],"IntroAssistant":[["^#assistantName#: Hello. I'm #assistantName#.","\n","ev","str","^Nice to meet you.","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^#assistantName#: You can use the mouse or arrow keys to move around, and the plus and minus keys to zoom in and out. B opens the budget and F lets you adjust Forest Policy.","\n",["ev","str","^Got it, thanks.","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^How are you?","/str","/ev",{"*":".^.c-1","flg":20},{"c-0":["\n","^#assistantName#: Bye","\n","end",{"#f":5}],"c-1":["\n","^#assistantName#: #howdoing#","\n","end",{"#f":5}]}],{"#f":5}]}],null],"BadNewsReact":[["ev","str","^Damn.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Fuck.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Shoot.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^*Sigh.* Fine.","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^Who cares?","/str","/ev",{"*":".^.c-4","flg":4},{"c-0":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-1":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-2":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-3":["\n","ev","void","/ev","->->",null],"c-4":["\n","ev","void","/ev","->->",null]}],null],"AssistantAcknowlege":[["ev","str","^Thanks.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Mmmm hmm.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Get to it.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^I really appreciate it, #assistantName#","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev","void","/ev","->->",null],"c-1":["\n","ev","void","/ev","->->",null],"c-2":["^ ","ev",{"^var":"playerRude","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","void","/ev","->->",null],"c-3":["\n",{"->":".^.^.^.Appreciate"},null]}],{"Appreciate":["^#assistantName#: ","ev",{"VAR?":"assistantTraits"},{"VAR?":"shy"},"?","/ev",[{"->":".^.b","c":true},{"b":["^...",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":[["ev","visit",3,"seq","/ev","ev","du",0,"==","/ev",{"->":".^.s0","c":true},"ev","du",1,"==","/ev",{"->":".^.s1","c":true},"ev","du",2,"==","/ev",{"->":".^.s2","c":true},"nop",{"s0":["pop","^No problem.",{"->":".^.^.23"},null],"s1":["pop","^Oh, you're welcome.",{"->":".^.^.23"},null],"s2":["pop","^My pleasure.",{"->":".^.^.23"},null],"#f":5}],{"->":".^.^.^.8"},null]}],"nop","\n","ev","void","/ev","->->",null]}],"MassVandalism":[["^#assistantName#: Bad news, director.","\n","ev","str","^Oh?","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^#assistantName#: A number of trees have been seriously damaged overnight.","\n",["ev","str","^How bad are they?","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^#assistantName#: I'm no botanist, but they're not great. The gouges are pretty deep.","\n",{"->t->":"BadNewsReact"},"^#assistantName#: Yeah, it's ","ev",{"VAR?":"assistantTraits"},{"VAR?":"sweary"},"?","/ev",[{"->":".^.b","c":true},{"b":["^fucking",{"->":".^.^.^.11"},null]}],"nop","^ awful.","\n","^I'll see who's around and get to cleaning.","\n",{"->t->":"AssistantAcknowlege"},"end",null]}],null]}],null],"LowFunds":[["^#assistantName#: Director, our funds are getting dangerously low!","\n","ev","str","^Don't worry about it. I have a plan.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^I know.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Stop bothering me with things I already know!","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Have any ideas?","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^What?","/str","/ev",{"*":".^.c-4","flg":4},{"c-0":["\n","end",null],"c-1":["\n","end",null],"c-2":["^ ","ev",{"^var":"playerRude","ci":-1},{"f()":"inc"},"out","/ev","\n","end",null],"c-3":["\n","^#assistantName#: Consider accepting some contracts. Even if they're not the best terms, they'll keep us from running out of money.","\n","end",null],"c-4":["\n","^#assistantName#: Yes, we have less than $25,000. We're running the risk of a default.","\n",{"->t->":"BadNewsReact"},"^#assistantName#: I know! consider accepting some contracts. Even if they're not the best terms, they'll keep us from running out of money.","\n","end",null]}],null],"VeryLowFunds":[["^Governor: Director, you have almost no reserve funds. This isn't acceptable.","\n","ev",{"CNT?":".^.^"},1,">","/ev",[{"->":".^.b","c":true},{"b":["^ I can't believe I'm having this conversation with you again. ",{"->":".^.^.^.8"},null]}],"nop","\n","ev","str","^I know. I'm working on it.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Have any ideas?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^What happens if I run out of money?","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^What?","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","^Governor: For your sake, I hope so.","\n","end",null],"c-1":["\n","^Governor: Accept some contracts. Now's not the time to worry about sustainability, or whatever you natural resources types care about. Just take the deal. They'll keep you from running out of money.","\n","end",null],"c-2":["\n",{"->":".^.^.^.WhatHappens"},null],"c-3":["\n",{"->":".^.^.^.Surprise"},null]}],{"Surprise":[["^Governor: Is this a *surprise* to you?","\n","ev","str","^Uh, um, no.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Honestly, yes.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^What happens if I run out of money?","/str","/ev",{"*":".^.c-2","flg":4},{"c-0":["\n","^Governor: Well, I hope you have a plan...","\n","^For your sake.","\n","end",null],"c-1":["\n","^Governor: Well! I appreciate your directness. But I hope you have a plan...","\n","^For your sake.","\n","end",null],"c-2":["\n",{"->":".^.^.^.^.WhatHappens"},null]}],null],"WhatHappens":[["^Governor: If you run out of money entirely...","\n","^The park will be fine, in the long run. The state department of natural resources will use its funds to bail the park out. Someone from my office will come in and trim the budget.","\n","^You, however, will be asked to resign.","\n","ev","str","^And if I don't resign?","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^I understand.","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n","^Governor: I'll fire you.","\n",["ev","str","^Oh.","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","end",null]}],null],"c-1":["\n","end",null]}],null],"#f":1}],"EndLowFunds":[["^Governor: I've warned you.","\n","ev","str","^I understand. I resign. (Game Over)","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["^ ","ev",{"x()":"endGame"},"out","/ev","\n","end",null]}],null],"MeetFriendOfThePark":[["^#friendOfThePark#: Hi, I'm the president of the Friends of the Park. Nice to meet you!","\n","ev","str","^Nice to meet you!","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Ahh.","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^I've been expecting you.","/str","/ev",{"*":".^.c-2","flg":20},{"c-0":["\n","ev","void","/ev","->->",{"#f":5}],"c-1":["\n","ev","void","/ev","->->",{"#f":5}],"c-2":["\n","^#friendOfThePark#: Huh!","\n","ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"Fundraiser":[["ev",{"CNT?":"MeetFriendOfThePark"},"!","_","/ev",[{"->":".^.b","c":true},{"b":["\n",{"->t->":"MeetFriendOfThePark"},{"->":".^.^.^.6"},null]}],"nop","\n","^#friendOfThePark#: I'm happy to announce the completion of our fundraiser! You won't guess how much we made!","\n","ev","str","^Please don't make me guess.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Okay...","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n","^#friendOfThePark#: It's more fun if you guess.","\n",["ev","str","^ Fine.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Well, I don't enjoy it.","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n",{"->":"Fundraiser.Guess"},null],"c-1":["\n",{"->":"Fundraiser.Amount"},null]}],null],"c-1":["\n",{"->":".^.^.^.Guess"},null]}],{"Guess":[["^#friendOfThePark#:","\n","ev","str","^$1,000?","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^$5,000?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^$10,000?","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^$25,000?","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^$1 million?","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^$1 billion?","/str","/ev",{"*":".^.c-5","flg":4},"ev","str","^I give up.","/str","/ev",{"*":".^.c-6","flg":4},{"c-0":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-1":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-2":["\n","^#friendOfThePark#: You're right!","\n",{"->":".^.^.^.^.Amount"},null],"c-3":["\n","^#friendOfThePark#: Higher","\n",{"->":".^.^.^"},null],"c-4":["\n","^#friendOfThePark#: No, haha. I wish!","\n",{"->":".^.^.^"},null],"c-5":["\n","^#friendOfThePark#: Not quite that high, heh","\n",{"->":".^.^.^"},null],"c-6":["\n",{"->":".^.^.^.^.Amount"},null]}],null],"Amount":["^#friendOfThePark#: Anyway. we made $10,000!","\n","end",null]}],"GovernmentGrant":[["^Governor: Good news, director. You've been awarded a federal grant.","\n","ev","str","^Awesome","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Sounds good","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["\n",{"->":".^.^.^.Money"},null],"c-1":["\n",{"->":".^.^.^.Money"},null]}],{"Money":["^Governor: Well, it won't last forever. Don't get dependent on it.","\n","end",null]}],"MeetHeadofPark":["^Head of Parks: I'm the fucking head of parks, that's who I am, you absolute motherfucker. ","ev","void","/ev","->->","\n",{"#f":1}],"PoorTreeHealth":[["^Head of Parks: What the hell do you think you're doing, you absolute piece of shit?!?","\n","ev","str","^Sorry, who are you?","/str",{"CNT?":"MeetHeadofPark"},"!","_","/ev",{"*":".^.c-0","flg":21},"ev","str","^Uhh, what the fuck?","/str","/ev",{"*":".^.c-1","flg":4},{"c-0":["^ ",{"->t->":"MeetHeadofPark"},"\n",{"->":".^.^.^.Screwed"},{"#f":5}],"c-1":["\n",{"->":".^.^.^.Screwed"},null]}],{"Screwed":[["^Head of Parks: We're all fucking screwed and it's your fault, you colossal shitheel.","\n","ev","str","^...","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^Head of Parks: Look at this park, it has anxiety! You did that you megadick.","\n",["ev","str","^...","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^Head of Parks: Yeah, you'd better stay quiet. I don't want to hear a single word out of your fucking useless knifewound of a mouth.","\n","end",null]}],null]}],null]}],"PreserveProgress":[["^Head of Parks: Hey, you goddam dunderhead. A quarter of this park is now a preserve! ","ev",{"^var":"HeadOfParksOpinion","ci":-1},{"f()":"inc"},"out","/ev","\n","ev","str","^Sorry, who are you?","/str",{"CNT?":"MeetHeadofPark"},"!","_","/ev",{"*":".^.c-0","flg":21},"ev","str","^And you're mad?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Right!","/str","/ev",{"*":".^.c-2","flg":4},{"c-0":["^ ",{"->":"MeetHeadofPark"},"\n",{"->":".^.^.^.WhatPreserves"},{"#f":5}],"c-1":["\n","^Head of Parks: No, you vainglorious buffoon! I'm pretty goddamn pleased. ",{"->":".^.^.^.WhatPreserves"},"\n",null],"c-2":["\n",{"->":".^.^.^.WhatPreserves"},null]}],{"WhatPreserves":[["^Head of Parks: I goddamn love preserves. The peach kind. The strawberry kind. But especially the park kind. The trees are left alone. They fucking flourish! Do you think you could fucking photosynthese with people traipsing all over?","\n","ev","str","^No?","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","^Head of Parks: You're goddamn right! You couldn't! Do you know how many preserves have been added since our cuntforsaken governor took office in 2014???","\n",["ev","str","^Uh one?","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^None?","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^HellifIknow","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^One dozen","/str","/ev",{"*":".^.c-3","flg":4},"ev","str","^One Hundred","/str","/ev",{"*":".^.c-4","flg":4},"ev","str","^One billion","/str","/ev",{"*":".^.c-5","flg":4},{"c-0":["\n","^Head of Parks: Not even one! ",{"->":".^.^.^.^.^.^.Zero"},"\n",null],"c-1":["\n","^Head of Parks: Bingo, my motherfucker ",{"->":".^.^.^.^.^.^.Zero"},"\n",null],"c-2":["^ ","ev",{"^var":"playerSwears","ci":-1},{"f()":"inc"},"out","/ev","\n","^Head of Parks: Least your honest. ",{"->":".^.^.^.^.^.^.Zero"},"\n",null],"c-3":["\n","^Head of Parks: What? Not even close. ",{"->":".^.^.^.^.^.^.Zero"},"\n",null],"c-4":["\n","^Head of Parks: What? Not even close. ",{"->":".^.^.^.^.^.^.Zero"},"\n",null],"c-5":["\n","^Head of Parks: Fuck off. ","ev",{"^var":"HeadOfParksOpinion","ci":-1},{"f()":"dec"},"out","/ev","^ ",{"->":"HeadofParkSideRant"},"\n","^Anyway, it's not a billion!! ",{"->":".^.^.^.^.^.^.Zero"},"\n",null]}],null]}],null],"Zero":["^Head of Parks: It's zero! Zero new preserves on God's green earth. Or brown earth. I swear to god...","\n","end",null]}],"PreserveHalf":[["^Head of Parks: Hey, you goddam wunderkind. A whole half of this park is now a preserve! ","ev",{"^var":"HeadOfParksOpinion","ci":-1},{"f()":"inc"},"out","/ev","\n","^In fact, I want to shake your bloody hand!","\n","ev","str","^Sure!","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Umm..okay","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^No thanks","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^No, you have germs","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["^ ","ev",{"^var":"HeadOfParksOpinion","ci":-1},{"f()":"inc"},"out","/ev","\n",{"->":".^.^.^.PostShake"},null],"c-1":["\n",{"->":".^.^.^.PostShake"},null],"c-2":["\n",{"->":".^.^.^.PostShake"},null],"c-3":["^ ","ev",{"^var":"HeadOfParksOpinion","ci":-1},{"f()":"dec"},"out","/ev","\n","^Head of Parks: Bloody hell, I wash! ",{"->":".^.^.^.PostShake"},"\n",null]}],{"PostShake":[["^Head of Parks: Anywyay, you're doing great. If that bloody governor gives you any shit, send him my way. And I think I can scrounge up some money to help you keep the park running.","\n","ev","str","^Thanks","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["\n","end",null]}],null]}],"HeadofParkSideRant":[["^Head of Parks: Are you fucking with me? Really fucking with me? Listen, you motherfucking piss-eared shit-for-brains backroad bureaucrat, I didn't come hear from the fucking capitol building holding up the whole natural resources administrative state like MiracleGrow Atlas to get scoffed at by a tinpot administrator who think 100 acres and a desk makes you some sort of important person. Aplogize!","\n","ev","str","^Sorry","/str","/ev",{"*":".^.c-0","flg":4},{"c-0":["^ ","ev","void","/ev","->->","\n",null]}],null],"LargePreserve":[["^#assistantName#: I noticed you reserved quite a bit of space for a nature preserve. Remember that these are unavailable for leisure use or development.","\n","ev","str","^Isn't it great!","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Thanks for checking in.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^I know what I'm doing!","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Maybe I've overreached. (Undoes Preserve)","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","^#assistantName#: Ummm. Yeah! It is.","\n","end",null],"c-1":["\n","end",null],"c-2":["^ ","ev",{"^var":"playerRude","ci":-1},{"f()":"inc"},"out","/ev","\n","end",null],"c-3":["^ ","ev",{"x()":"undoPreserve"},"out","/ev","\n","end",null]}],null],"global decl":["ev",0,{"VAR=":"playerSwears"},0,{"VAR=":"playerRude"},0,{"VAR=":"GovernorOpinion"},0,{"VAR=":"HeadOfParksOpinion"},{"list":{},"origins":["assistantTraits"]},{"VAR=":"assistantTraits"},"/ev","end",null]}],"listDefs":{"assistantTraits":{"shy":1,"esoteric":2,"sweary":3}}} No newline at end of file
@@ -6,6 +6,6
6 6 ~ assistantTraits = (shy, sweary)
7 7
8 8
9 -> EndLowFunds
9 -> PreserveHalf
10 10
11 11 -> END No newline at end of file
@@ -103,7 +103,7
103 103 object1: "#object#"
104 104 object2: "#object#"
105 105 object3: "#object#"
106 - hed: "How the people of #subject_area.capitalize# are fighting #subject_problem.capitalize#"
106 - hed: "How the people of #subject_area.capitalize# are fighting #subject_problem#"
107 107 contents: "#femaleCodedName# #surname#, an #occupation#, stares out at the wilderness of #subject_area#.
108 108
109 109 Like many places, it has not been spared by #subject_problem#."
@@ -132,9 +132,27
132 132 - hed: "Are Comets Real?"
133 133 contents: ""
134 134 source: "True"
135 - hed: "Scientists Attached an Ear to the Back of a Mouse?? What the Hell???"
136 contents: ""
137 source: "True"
138 - hed: "EDITOR'S NOTE: Mole People are Just Like Us"
139 contents: "Many independent journalists report breathlessly on moleperson sightings. Take The Weekly Wolrd News. Despite uncovering such important stories as the Batboy and raising merfolk awareness, they also have perpetuated stigma against the moleperson community.
140
141 This is wrong. And for the 129 stories, anonymous poem and three unsigned letters, sensationalizing the molepeople I filled while an intern, I apologize.
142
143 In fact one of my best friends is a mole person. #moleperson_first_name# #moleperson_surname# was born underground to a loving mole family, who even took me in when my dad worked nights at the #object# factory.
144
145 While there are definite cultural differences between my normal, All-American family and his abnormal, All-Mole family, like their affinity for dirt and snouts instead of noses, we're all just people. Kumbyah, right?"
146 source: "True"
147 variables:
148 moleperson_first_name: "#maleCodedName#"
149 moleperson_surname: "#surname#"
150 - hed: "MYSTERY: Can Guys and Girls Just Be Friends?"
151 contents: ""
152 source: "True"
135 153 - hed: "Protester Struck After Bullet Emerges From Gun Held by Police Officer"
136 154 contents: "Local #protestor_first_name# #protestor_surname# was protesting when they were struck by a bullet
137 that came from a gun held by a police officer. They died later at #town# Memorial Hospital.
155 that emerged from a gun held by a police officer. They died later at #town# Memorial Hospital.
138 156
139 157 #protestor_surname#'s family insists the police take responsibility.
140 158
@@ -104,9 +104,6
104 104 AddComponent(fundraiserEntity, new EventComponent { EndEventDate = simulationDate.AddMonths(12) });
105 105 SendMessage(new SpawnDialogMessage { Path = "GovernmentGrant" });
106 106 }
107
108
109
110 107 }
111 108 #endregion
112 109
@@ -1,4 +1,5
1 1
2 using System.Collections.Generic;
2 3 using System.IO;
3 4
4 5 using Microsoft.Xna.Framework.Input;
@@ -19,22 +20,38
19 20 typeof(SetFontMessage),
20 21 typeof(QuitGameMessage))]
21 22 [Reads(typeof(AreaComponent),
22 typeof(ContractStatusComponent),
23 typeof(OptionsComponent))]
23 typeof(PointComponent),
24 typeof(ContractStatusComponent),
25 typeof(OptionsComponent),
26 typeof(PreserveComponent))]
27 [Sends(typeof(UndoPreserveMessage))]
24 28 class GameBridgeEngine : Engine
25 29 {
26 30
27 31 public FNAGame game;
28 32
33 public List<UndoPreserveMessage> undoPreserveMessages;
34
29 35 public GameBridgeEngine(FNAGame game)
30 36 {
31 37 this.game = game;
38
39 this.undoPreserveMessages = new List<UndoPreserveMessage>();
32 40 }
33 41
34 42 public override void Update(double dt)
35 43 {
36 44
37 45 ProfanityLevel profanity_setting = default;
46 float sound_effect_volume = 1.0f; //full volume
47 bool sound_effect_muted = false;
48
49 foreach (var message in undoPreserveMessages)
50 {
51 SendMessage<UndoPreserveMessage>(message);
52 }
53
54 this.undoPreserveMessages.Clear();
38 55
39 56 foreach (ref readonly var windowMessage in ReadMessages<ToggleWindowTypeMessage>())
40 57 {
@@ -77,40 +94,67
77 94 var component = GetComponent<OptionsComponent>(entity);
78 95
79 96 profanity_setting = component.ProfanitySetting;
97 sound_effect_volume = component.SoundEffectVolume;
98 sound_effect_muted = component.SoundEffectMuted;
80 99 }
100
81 101 foreach (ref readonly var fontMessage in ReadMessages<SetFontMessage>())
82 102 {
83 103 game.setFont(fontMessage.fontName, fontMessage.fontSize);
84 104 Options.writeOptions(fontMessage.fontName, fontMessage.fontSize,
85 profanity_setting);
105 profanity_setting, sound_effect_volume, sound_effect_muted);
106 }
86 107
87 }
88 108
89 109 game.in_zone = false;
90 110 game.in_active_zone = false;
111 game.in_preserve = false;
112 game.has_tower = false;
91 113 foreach (ref readonly var entity in ReadEntities<AreaComponent>())
92 114 {
93 115 var areaComponent = GetComponent<AreaComponent>(entity);
94 var contractStatusComponent = GetComponent<ContractStatusComponent>(entity);
95 foreach (var square in areaComponent.squares)
116
117 if (HasComponent<ContractStatusComponent>(entity))
96 118 {
97 if (game.mouseGrid == square)
119 var contractStatusComponent = GetComponent<ContractStatusComponent>(entity);
120 foreach (var square in areaComponent.squares)
98 121 {
99 game.in_zone = true;
100 if ((contractStatusComponent.status == ContractStatus.Active)
101 || (contractStatusComponent.status == ContractStatus.Accepted))
122 if (game.mouseGrid == square)
102 123 {
103 game.in_active_zone = true;
124 game.in_zone = true;
125 if ((contractStatusComponent.status == ContractStatus.Active)
126 || (contractStatusComponent.status == ContractStatus.Accepted))
127 {
128 game.in_active_zone = true;
129 }
104 130 }
105 131 }
106 132 }
133 else if (HasComponent<PreserveComponent>(entity)) {
134 foreach (var square in areaComponent.squares) {
135 if (game.mouseGrid == square)
136 {
137
138 game.in_preserve = true;
139 }
140
141 }
142 }
143 }
144 foreach (ref readonly var entity in ReadEntities<PointComponent>())
145 {
146 var point_component = GetComponent<PointComponent>(entity);
147
148 if (game.mouseGrid == point_component.Square)
149 {
150 game.has_tower = true;
151 }
107 152 }
108 153
109 154 foreach (ref readonly var message in ReadMessages<QuitGameMessage>())
110 155 {
111 156 this.game.quit = true;
112 157 }
113
114 158 }
115 159 }
116 160 }
@@ -26,7 +26,7
26 26 foreach (var entity in ReadEntities<GameStateComponent>())
27 27 {
28 28 var state = GetComponent<GameStateComponent>(entity).isPlaying;
29 Logging.Spy(state, "state");
29 Logging.Debug("Changing state: " + state.ToString());
30 30
31 31 SetComponent(entity, new GameStateComponent { isPlaying = message.isPlaying });
32 32 }
@@ -27,14 +27,19
27 27 typeof(SetDialogMessage),
28 28 typeof(DialogChoiceMessage),
29 29 typeof(SetOptionMessage),
30 typeof(QuitGameMessage))]
30 typeof(QuitGameMessage),
31 typeof(ToggleToolMessage),
32 typeof(PlaySoundMessage),
33 typeof(DebugAlterTreesMessage))]
31 34 [Reads(typeof(VisibilityComponent),
32 35 typeof(WindowTypeComponent),
33 36 typeof(TrespassingPolicyComponent),
34 37 typeof(ContractStatusComponent),
35 38 typeof(RelatedOrganizationComponent),
36 39 typeof(NameAndDescriptionComponent),
37 typeof(OptionsComponent))]
40 typeof(OptionsComponent),
41 typeof(ToolComponent),
42 typeof(SelectedComponent))]
38 43 [Writes(typeof(OptionsComponent))]
39 44 public class ImGuiWindowBridgeEngine : Engine
40 45 {
@@ -54,6 +59,9
54 59 public List<SetOptionMessage> setOptionMessages;
55 60 public List<GameRateMessage> gameRateMessages;
56 61 public List<QuitGameMessage> quitGameMessages;
62 public List<ToggleToolMessage> toggleToolMessages;
63 public List<PlaySoundMessage> playSoundMessages;
64 public List<DebugAlterTreesMessage> debugAlterTreesMessages;
57 65
58 66 bool showBudget { get; }
59 67 bool showForest { get; }
@@ -62,6 +70,7
62 70 bool showTrees { get; }
63 71
64 72 public Dictionary<Window, bool> windowStatuses { get; }
73 public Dictionary<Tool, bool> toolStatuses { get; }
65 74
66 75 public bool showContractIndicator;
67 76 public List<string> contracts;
@@ -103,8 +112,12
103 112 this.setOptionMessages = new List<SetOptionMessage>();
104 113 this.gameRateMessages = new List<GameRateMessage>();
105 114 this.quitGameMessages = new List<QuitGameMessage>();
115 this.toggleToolMessages = new List<ToggleToolMessage>();
116 this.playSoundMessages = new List<PlaySoundMessage>();
117 this.debugAlterTreesMessages = new List<DebugAlterTreesMessage>();
106 118
107 119 this.windowStatuses = new Dictionary<Window, bool>();
120 this.toolStatuses = new Dictionary<Tool, bool>();
108 121
109 122 this.showContractIndicator = false;
110 123 this.showBudgetLow = false;
@@ -124,6 +137,11
124 137 {
125 138 windowStatuses.Add((Window)type, false);
126 139 }
140
141 foreach (var type in System.Enum.GetValues(typeof(Tool)))
142 {
143 toolStatuses.Add((Tool)type, false);
144 }
127 145 }
128 146
129 147 public override void Update(double dt)
@@ -209,6 +227,11
209 227 SendMessage(message);
210 228 }
211 229
230 foreach (var message in this.toggleToolMessages)
231 {
232 SendMessage(message);
233 }
234
212 235 foreach (var message in this.setOptionMessages)
213 236 {
214 237 foreach (var entity in ReadEntities<OptionsComponent>())
@@ -216,12 +239,22
216 239
217 240 SetComponent(entity, new OptionsComponent
218 241 {
219 ProfanitySetting = message.NewProfanitySetting
242 ProfanitySetting = message.NewProfanitySetting,
243 SoundEffectVolume = message.NewSoundEffectVolume,
244 SoundEffectMuted = message.NewSoundEffectMuted
220 245 });
221 246 }
222 247
223 248 }
224 249
250 foreach (var message in this.playSoundMessages) {
251 SendMessage(message);
252 }
253
254 foreach (var message in this.debugAlterTreesMessages) {
255 SendMessage(message);
256 }
257
225 258 foreach (var entity in ReadEntities<WindowTypeComponent>())
226 259 {
227 260 var type = GetComponent<WindowTypeComponent>(entity).type;
@@ -229,6 +262,12
229 262 windowStatuses[type] = visibility;
230 263 }
231 264
265 foreach (var entity in ReadEntities<ToolComponent>()) {
266 var tool = GetComponent<ToolComponent>(entity).Tool;
267 var selected = HasComponent<SelectedComponent>(entity) ? GetComponent<SelectedComponent>(entity).selected : false;
268 toolStatuses[tool] = selected;
269 }
270
232 271 //reset
233 272 this.showContractIndicator = false;
234 273 this.contracts.Clear();
@@ -277,6 +316,9
277 316 this.gameRateMessages.Clear();
278 317 this.setOptionMessages.Clear();
279 318 this.quitGameMessages.Clear();
319 this.toggleToolMessages.Clear();
320 this.playSoundMessages.Clear();
321 this.debugAlterTreesMessages.Clear();
280 322 }
281 323 }
282 324 }
@@ -1,9 +1,12
1 1
2 2 using System;
3 3 using Microsoft.Xna.Framework;
4 using Microsoft.Xna.Framework.Audio;
4 5 using Microsoft.Xna.Framework.Graphics;
5 6 using Microsoft.Xna.Framework.Input;
6 7
8 using ImGuiNET;
9
7 10 using Encompass;
8 11
9 12 using isometricparkfna.Messages;
@@ -20,10 +23,15
20 23 typeof(TogglePauseMessage),
21 24 typeof(GameRateMessage),
22 25 typeof(GameStateMessage),
23 typeof(QuitGameMessage))]
26 typeof(QuitGameMessage),
27 typeof(SpawnSelection),
28 typeof(AdjustSelection),
29 typeof(PlaySoundMessage))]
24 30 [Reads(typeof(WindowTypeComponent),
25 31 typeof(GameStateComponent),
26 typeof(VisibilityComponent))]
32 typeof(VisibilityComponent),
33 typeof(CursorComponent))]
34 [Writes(typeof(CursorComponent))]
27 35 public class InputEngine : Engine
28 36 {
29 37 private KeyboardState keyboardPrev;
@@ -35,15 +43,31
35 43
36 44 //Area to ignore:
37 45 private int menuBarHeight;
46 private int height;
47 private int width;
38 48
39 49 public InputEngine(int menuBarHeight, Camera camera,
40 GraphicsDeviceManager gdm) {
50 GraphicsDeviceManager gdm, int height, int width) {
41 51 //initialize to blank for now
42 52 this.keyboardPrev = new KeyboardState();
43 53 this.menuBarHeight = menuBarHeight;
44 54 this.camera = camera;
45 55 this.gdm = gdm;
46 56 this.graphicsDevice = gdm.GraphicsDevice;
57 this.height = height;
58 this.width = width;
59 }
60
61
62 Vector2 calculateMousegrid(Vector2 normalizedMousePos)
63 {
64 Vector2 adjust = new Vector2(Tile.TileSpriteWidth / 2, Tile.TileSpriteHeight);
65 Vector2 adjustedMousePos = normalizedMousePos - adjust;
66
67 float boardx = ((adjustedMousePos.X / Tile.TileSpriteWidth) + (adjustedMousePos.Y / Tile.TileSpriteHeight));
68 float boardy = ((adjustedMousePos.Y / Tile.TileSpriteHeight) - (adjustedMousePos.X / Tile.TileSpriteWidth));
69
70 return new Vector2((int)boardx, (int)boardy);
47 71 }
48 72
49 73 public override void Update(double dt) {
@@ -52,12 +76,13
52 76 var mouseCur = Mouse.GetState();
53 77 var original_point = Vector2.Transform(new Vector2(mouseCur.X, mouseCur.Y),
54 78 Matrix.Invert(this.camera.get_transformation(this.graphicsDevice)));
55
56 79 bool isPlaying = false;
57 80
58 81 var viewWidth = gdm.PreferredBackBufferWidth;
59 82 var viewHeight = gdm.PreferredBackBufferHeight;
60 83
84 ImGuiIOPtr io = ImGui.GetIO();
85
61 86 foreach (var entity in ReadEntities<GameStateComponent>())
62 87 {
63 88 var state = GetComponent<GameStateComponent>(entity).isPlaying;
@@ -187,7 +212,15
187 212 {
188 213 SendMessage(new ToggleWindowTypeMessage {Window = Window.InGameMenu});
189 214 SendMessage(new GameRateMessage { paused = true, rate = null });
215 //People will probably expect escape to clear, even though its primary purpose
216 //is to open the menu:
217 SendMessage(new AdjustSelection {Type = AdjustmentType.Clear });
190 218 }
219
220 //Back => Backspace
221 if (keyboardCur.IsKeyDown(Keys.Back) && keyboardPrev.IsKeyUp(Keys.Back)) {
222 SendMessage(new AdjustSelection {Type = AdjustmentType.Clear });
223 }
191 224 }
192 225
193 226 if (keyboardCur.IsKeyDown(Keys.OemBackslash) && keyboardPrev.IsKeyUp(Keys.OemBackslash))
@@ -233,10 +266,52
233 266 #endregion
234 267 #region mouse_click
235 268
236 if (mouseCur.RightButton == ButtonState.Pressed && mousePrev.RightButton == ButtonState.Released)
269 if (isPlaying && !io.WantCaptureMouse) {
270 if (mouseCur.RightButton == ButtonState.Pressed && mousePrev.RightButton == ButtonState.Released)
271 {
272 SendMessage(new PlaySoundMessage { SoundName = "Click" });
273 SendMessage(new JumpCameraMessage {Movement = original_point});
274 }
275
276 if (mouseCur.LeftButton == ButtonState.Pressed && mousePrev.LeftButton == ButtonState.Released
277 // && keyboardCur.IsKeyDown(Keys.LeftShift)
278 )
279 {
280 SendMessage(new SpawnSelection {Start = CellMap.calculateMousegrid(original_point)});
281 }
282
283 if ( mouseCur.LeftButton == ButtonState.Released && mousePrev.LeftButton == ButtonState.Pressed)
284 {
285 SendMessage(new AdjustSelection {Type = AdjustmentType.Complete });
286 // SendMessage(new
287 }
288
289 if (mouseCur.LeftButton == ButtonState.Pressed && mousePrev.LeftButton == ButtonState.Pressed)
290 {
291 SendMessage(new AdjustSelection {End = CellMap.calculateMousegrid(original_point)});
292 }
293
294 var transformedPosition = Vector2.Transform(new Vector2(mouseCur.X, mouseCur.Y), Matrix.Invert(camera.get_transformation(this.graphicsDevice)));
295 var gridPosition = calculateMousegrid(transformedPosition);
296 if (MathUtils.Between(gridPosition.X, 0, this.width)
297 && MathUtils.Between(gridPosition.Y, 0, this.height))
237 298 {
238 SendMessage(new JumpCameraMessage {Movement = original_point});
299 foreach (ref readonly var entity in ReadEntities<CursorComponent>()) {
300 var cursorComponent = GetComponent<CursorComponent>(entity);
301
302 SetComponent(entity, new CursorComponent { position = gridPosition,
303 size = 1 });
304 }
239 305 }
306 }
307 else if (ImGui.IsAnyItemHovered()) {
308 if (mouseCur.LeftButton == ButtonState.Pressed && mousePrev.LeftButton == ButtonState.Released) {
309 SendMessage(new PlaySoundMessage { SoundName = "ClickPart1" });
310 }
311 else if (mouseCur.LeftButton == ButtonState.Released && mousePrev.LeftButton == ButtonState.Pressed) {
312 SendMessage(new PlaySoundMessage { SoundName = "ClickPart2" });
313 }
314 }
240 315
241 316 #endregion
242 317 this.keyboardPrev = keyboardCur;
@@ -12,48 +12,42
12 12 [Reads(typeof(TrespassingPolicyComponent))]
13 13 [Writes(typeof(TrespassingPolicyComponent),
14 14 typeof(BudgetLineComponent))]
15 public class PolicyEngine : Engine
15 public class PolicyEngine : Engine
16 16 {
17
18 17 public PolicyEngine()
19 18 {
20 19 }
21 20
22
23 21 public override void Update(double dt)
24 22 {
25 23 foreach (ref readonly var message
26 in ReadMessages<SetTrespassingPolicyMessage>())
24 in ReadMessages<SetTrespassingPolicyMessage>())
27 25 {
28 26 foreach (ref readonly var entity
29 in ReadEntities<TrespassingPolicyComponent>())
27 in ReadEntities<TrespassingPolicyComponent>())
30 28 {
31 29
32 30 SetComponent<TrespassingPolicyComponent>(entity,
33 31 new TrespassingPolicyComponent
34 {
35 tresspassingPolicy
36 = message.newEnforcementLevel
37 });
32 {
33 tresspassingPolicy
34 = message.newEnforcementLevel
35 });
38 36
39 37 var newCost = message.newEnforcementLevel switch {
40 38 EnforcementLevel.Unspecified => 0,
41 EnforcementLevel.NoEnforcement => 0,
42 EnforcementLevel.EnforcedWithWarnings => 100,
43 EnforcementLevel.EnforcedWithFines => 100,
44 _ => 0 //C# enums can take on non-declared vaues. Sigh.
45 };
39 EnforcementLevel.NoEnforcement => 0,
40 EnforcementLevel.EnforcedWithWarnings => 100,
41 EnforcementLevel.EnforcedWithFines => 100,
42 _ => 0 //C# enums can take on non-declared vaues. Sigh.
43 };
46 44
47 SetComponent<BudgetLineComponent>(entity,
48 new BudgetLineComponent
49 {
50 category = "Enforcement",
51 amount = newCost
52 });
45 SetComponent<BudgetLineComponent>(entity,
46 new BudgetLineComponent
47 {category = "Enforcement",
48 amount = newCost});
53 49 }
54 50 }
55
56 51 }
57
58 52 }
59 53 }
@@ -1,4 +1,5
1 1 using System;
2 using System.Diagnostics;
2 3 using System.Linq;
3 4 using System.Collections.Generic;
4 5
@@ -17,8 +18,10
17 18 typeof(BudgetComponent),
18 19 typeof(BudgetLineComponent),
19 20 typeof(ContractStatusComponent),
20 typeof(TreeDeltaComponent))]
21 typeof(TreeDeltaComponent),
22 typeof(PreserveComponent))]
21 23 [Writes(typeof(BudgetComponent))]
24 [Receives(typeof(SingleExpenseMessage), typeof(DebugAlterTreesMessage))]
22 25 public class SimulationBridgeEngine : Engine
23 26 {
24 27 public Simulation simulation;
@@ -53,6 +56,11
53 56 public override void Update(double dt)
54 57 {
55 58
59 foreach (ref readonly var message in ReadMessages<SingleExpenseMessage>())
60 {
61 this.simulation.AddConstruction(message.amount);
62 }
63
56 64 foreach (ref readonly var entity in ReadEntities<BudgetComponent>())
57 65 {
58 66 ref readonly var budgetComponent = ref GetComponent<BudgetComponent>(entity);
@@ -67,7 +75,6
67 75 decimal new_contract_amount = 0M;
68 76 decimal new_enforcement_amount = 0M;
69 77 decimal new_misc_amount = 0M;
70 // decimal new_upkeep_amount = 0M;
71 78
72 79 foreach (ref readonly var entity in ReadEntities<BudgetLineComponent>())
73 80 {
@@ -91,14 +98,11
91 98 new_misc_amount += budgetComponent.amount;
92 99 break;
93 100 }
94
95 101 }
96 102
97 103
98
99 104 if (this.ticksToSend > 0)
100 105 {
101
102 106 Logging.Trace(String.Format("{0} ticks to send in update", this.ticksToSend));
103 107 }
104 108 if (this.ticksToSend > 1)
@@ -107,36 +111,106
107 111 }
108 112 for (int i = ticksToSend; i > 0; i--)
109 113 {
110 SendMessage<TickMessage>(new TickMessage { SimulationDateTime = simulation.DateTime });
111 //For now:
112 SendMessage<SpawnContractMessage>(new SpawnContractMessage
113 { //max_squares = 100,
114 name = string.Format("#logging_company.capitalizeAll# {0}", this.simulation.DateTime.ToShortDateString())
115 });
114
115 #region calculate_preserve_cells
116 var preserve_cell_coordinates = new List<(int, int)>();
117
118 Stopwatch iterPreserves = new Stopwatch();
119 iterPreserves.Start();
120
121 foreach (ref readonly var entity in ReadEntities<PreserveComponent>()) {
122 ref readonly var areaComponent = ref GetComponent<AreaComponent>(entity);
123
124 foreach (var square in areaComponent.squares) {
125 preserve_cell_coordinates.Add(((int)square.X, (int)square.Y));
126 }
127 }
128 iterPreserves.Stop();
129 Logging.Info(String.Format("Preserve entities: {0:F3}", iterPreserves.Elapsed.TotalMilliseconds.ToString()));
130
131
132 Stopwatch iterCells = new Stopwatch();
133 iterCells.Start();
134
135 //This takes about 30ms versus the .0002 ms with no preserve.
136 //When the map is filled up with preserve, about 35ms and 9ms.
137 //With a handful of cells, it's more like 0.8ms
138 /*
139 for (int j = 0; j < this.simulation.PreserveCounts.GetLength(0); j++) {
140 for (int k = 0; k < this.simulation.PreserveCounts.GetLength(0); k++) {
141 count = 0;
142 foreach (var cell in this.simulation.map.iterate_neighbor_cells(j, k)) {
143 if (preserve_cells.Contains(cell)) {
144 count++;
145 }
146 }
147 this.simulation.PreserveCounts[j, k] = count;
148 }
149 }
150 //*/
151
152 //*
153 foreach ((var x, var y) in preserve_cell_coordinates) {
154 foreach ((var newx, var newy) in this.simulation.map.iterate_neighbor_cell_locations(x, y)) {
155 this.simulation.PreserveCounts[newx, newy] += 1;
156 }
157 }
158 //*/
159 iterCells.Stop();
160 Logging.Info(String.Format("Cell loop: {0:F3}", iterCells.Elapsed.TotalMilliseconds.ToString()));
161
162 #endregion
163 SendMessage<TickMessage>(new TickMessage { SimulationDateTime = simulation.DateTime });
164 //For now:
165 SendMessage<SpawnContractMessage>(new SpawnContractMessage {name = string.Format("#logging_company.capitalizeAll# {0}",
166 this.simulation.DateTime.ToShortDateString()) });
116 167
117 168 #region events
118 169 if (simulation.latestBudget.DateTime != default)
119 170 {
120 171
172 var tree_count_threshold = (int)(0.05 * this.simulation.map.tree_capacity);
173
121 174 if (simulation.latestBudget.money < 0M
122 175 && simulation.previousBudget.money >= 0M)
123 176 {
124 177 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "EndLowFunds"});
125 178 }
126 179 else if (simulation.latestBudget.money < 10_000M
127 && simulation.previousBudget.money >= 10_000M)
180 && simulation.previousBudget.money >= 10_000M)
128 181 {
129 182 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "VeryLowFunds"});
130 183 }
131 184 else if (simulation.latestBudget.money < 25_000M
132 && simulation.previousBudget.money >= 25_000M)
185 && simulation.previousBudget.money >= 25_000M)
133 186 {
134 187 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "LowFunds"});
135 188 }
136 if (simulation.map.tree_count < 400)
189
190 if ((simulation.latestBudget.trees < tree_count_threshold)
191 && (simulation.previousBudget.trees >= tree_count_threshold))
137 192 {
138 193 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "PoorTreeHealth"});
139 194 }
195
196 Logging.Spy(new {count = preserve_cell_coordinates.Count(), half = (simulation.map.tree_capacity * 0.5)} );
197
198 if ((simulation.latestBudget.preserve_cells > (simulation.map.tree_capacity * 0.5))
199 && (simulation.previousBudget.preserve_cells <= (simulation.map.tree_capacity * 0.5)))
200 {
201 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "PreserveHalf"});
202 var fundraiserEntity = CreateEntity();
203
204 AddComponent(fundraiserEntity, new BudgetLineComponent {
205 category = "Misc",
206 amount = 20_000M });
207 }
208 else if ((simulation.latestBudget.preserve_cells > (simulation.map.tree_capacity * 0.25))
209 && (simulation.previousBudget.preserve_cells <= (simulation.map.tree_capacity * 0.25)))
210 {
211 SendMessage<SpawnDialogMessage>(new SpawnDialogMessage {Path = "PreserveProgress"});
212 }
213
140 214 }
141 215
142 216 #endregion
@@ -151,7 +225,7
151 225 var squares = HasComponent<AreaComponent>(entity) ? GetComponent<AreaComponent>(entity).squares : this.all_squares;
152 226 var removed = 0;
153 227 var added = 0;
154 var tree_squares = squares.Where((square) => simulation.map.cells[(int)square.X][(int)square.Y].hasTree);
228 var tree_squares = squares.Where((square) => simulation.map.cells[(int)square.X][(int)square.Y].HasTree);
155 229 var to_remove = Math.Abs(delta.deltaTrees.Value);
156 230
157 231 //calculate the probability in order to get the expected number of removed trees
@@ -162,17 +236,18
162 236 foreach (var square in tree_squares)
163 237 {
164 238 var cell = simulation.map.cells[(int)square.X][(int)square.Y];
165 if (cell.hasTree
239 if (cell.HasTree
166 240 && random_generator.NextDouble() < probability)
167 241 {
168 242 if (delta.deltaTrees.Value < 0)
169 243 {
170 cell.removeTree();
244 cell.RemoveTree();
171 245 removed++;
172 246 }
173 247 else if (delta.deltaTrees.Value > 0)
174 248 {
175 cell.addTree(this.simulation.DateTime);
249 var random_type = random_generator.Next(0, 3);
250 cell.AddTree(this.simulation.DateTime, (CellMap.TreeType)random_type);
176 251 added++;
177 252 }
178 253 }
@@ -185,6 +260,7
185 260 Logging.Info(String.Format("Planted {0} trees, expected {1}, P(destroy)= {2}", added, (expected / 12.0), probability));
186 261 }
187 262 }
263 simulation.preserve_cells = preserve_cell_coordinates.Count();
188 264 }
189 265 this.ticksToSend = 0;
190 266
@@ -192,8 +268,26
192 268 simulation.enforcement = new_enforcement_amount;
193 269 simulation.misc = new_misc_amount;
194 270
271 #region debug
272
273 foreach (ref readonly var message in ReadMessages<DebugAlterTreesMessage>())
274 {
275 var trees = message.DeltaTrees;
276
277 //Probaby not very performant; used only for debug.
278 foreach (CellMap.Cell cell in this.simulation.map.iterate_cells().Where(c => c.HasTree).ToList().Shuffle())
279 {
280 if (trees > 0) {
281 trees -= 1;
282 cell.RemoveTree();
283 }
284 }
285 }
286 #endregion
287
195 288 //Move this here?
196 289 // this.simulation.update(dt);
197 290 }
291
198 292 }
199 293 }
@@ -24,7 +24,6
24 24 private Random random_generator;
25 25
26 26 public const int DEFAULT_MIN_SQUARES = 75;
27 // public const int DEFAULT_SQUARES = 25;
28 27 public const int DEFAULT_SQUARES = 100;
29 28 public const int CONTRACT_MINIMUM = 50;
30 29 public const int CONTRACT_MAXIMUM = 400;
@@ -45,6 +44,7
45 44
46 45 this.simulation = simulation;
47 46 this.grammar = grammar;
47
48 48 }
49 49 private Vector2 FindStart(HashSet<Vector2> occupied_squares)
50 50 {
@@ -53,14 +53,13
53 53
54 54 for (int i = 0; i < 5; i++)
55 55 {
56 new_square = new Vector2(random_generator.Next(0, 50), random_generator.Next(0, 50));
56 new_square = new Vector2(random_generator.Next(0, this.MapHeight), random_generator.Next(0, this.MapWidth));
57 57
58 58 if (!occupied_squares.Contains(new_square))
59 59 {
60 60 return new_square;
61 61 }
62 62 }
63 // return null;
64 63 return Vector2.Zero;
65 64 }
66 65
@@ -70,7 +69,7
70 69 var squares_to_add = new HashSet<Vector2>();
71 70
72 71 var attempts = 0;
73 var maxAttempts = max_size * 10;
72 var maxAttempts = max_size * this.simulation.map.LinearMultiplier * 10;
74 73
75 74 while (squares.Count < max_size)
76 75 {
@@ -113,8 +112,6
113 112
114 113 protected override void Spawn(in SpawnContractMessage message)
115 114 {
116
117
118 115 //for now:
119 116 var occupied = new List<Vector2>();
120 117
@@ -132,7 +129,9
132 129 Logging.Debug(String.Format("Creating contract {0} without organizations.", message.name ));
133 130 }
134 131
135 foreach (var (entity, status) in ReadEntities<AreaComponent>().SelectWhereF((e) => (e, GetComponent<ContractStatusComponent>(e)), (e) => ((e.Item2.status != ContractStatus.Broken) && (e.Item2.status != ContractStatus.Rejected) && (e.Item2.status != ContractStatus.Expired)))) {
132 foreach (var (entity, status) in ReadEntities<AreaComponent>()
133 .WhereF((e) => HasComponent<ContractStatusComponent>(e))
134 .SelectWhereF((e) => (e, GetComponent<ContractStatusComponent>(e)), (e) => ((e.Item2.status != ContractStatus.Broken) && (e.Item2.status != ContractStatus.Rejected) && (e.Item2.status != ContractStatus.Expired)))) {
136 135 var entitySquares = GetComponent<AreaComponent>(entity).squares;
137 136 occupied.AddRange(entitySquares);
138 137 }
@@ -143,15 +142,11
143 142
144 143 var image_index = random_generator.Next(1, 7);
145 144
146 // int max_squares = (message.max_squares == 0) ? DEFAULT_SQUARES : message.max_squares;
147 // int min_squares = (message.min_squares == null) ? DEFAULT_MIN_SQUARES : (int)message.min_squares;
148
149
150 145 int max_squares = (organization_type, message.min_squares) switch {
151 (OrganizationType.Family, null) => random_generator.Next(50, 100),
152 (OrganizationType.LargeCorporation, null) => random_generator.Next(90, 250),
153 (OrganizationType.Cooperative, null) => random_generator.Next(50, 75),
154 (_, null) => random_generator.Next(DEFAULT_MIN_SQUARES, DEFAULT_SQUARES),
146 (OrganizationType.Family, null) => random_generator.Next(50, 100 * this.simulation.map.LinearMultiplier),
147 (OrganizationType.LargeCorporation, null) => random_generator.Next(90, 250 * this.simulation.map.LinearMultiplier),
148 (OrganizationType.Cooperative, null) => random_generator.Next(50, 75 * this.simulation.map.LinearMultiplier),
149 (_, null) => random_generator.Next(DEFAULT_MIN_SQUARES, DEFAULT_SQUARES * this.simulation.map.LinearMultiplier),
155 150 _ => (message.max_squares == 0) ? DEFAULT_SQUARES : message.max_squares
156 151 };
157 152
@@ -213,7 +208,7
213 208 AddComponent(contract, new AreaComponent { squares = squares });
214 209 var nameAndDescription = new NameAndDescriptionComponent { DisplayName = this.grammar.Flatten(message.name) };
215 210 AddComponent(contract, nameAndDescription);
216 AddComponent(contract, new SelectedComponent { selected = false });
211 AddComponent(contract, new SelectedComponent { selected = false, Type = SelectionType.Window });
217 212 AddComponent(contract, new ContractStatusComponent { status = ContractStatus.Proposed, date = this.simulation.DateTime });
218 213 AddComponent(contract, new TreeDeltaComponent { deltaTrees = new Fact<int>(deltaTrees) });
219 214 AddComponent(contract, new BudgetLineComponent
@@ -41,19 +41,83
41 41 protected override void Spawn(in SpawnGameMessage message)
42 42 {
43 43
44 #region generate_water
45
46 /*
47 * Differs from code in ContractSpawner in a few ways:
48 * β€”Not concerned with existing tilesβ€”this is one of the first things we're doing to the new map
49 * β€”Doesn't keep track of attempts (should be few and far betweet.)
50 * β€”No logging (not sure what logging is necessary here)
51 *
52 * These notes are mostly for myself in the future if I decide to unify these implementations.
53 */
54 for (int i = 0; i < Simulation.NUM_WATER_FEATURES; i++) {
55 var water_x = this.random_generator.Next(0, this.simulation.map.MapWidth);
56 var water_y = this.random_generator.Next(0, this.simulation.map.MapHeight);
57
58
59 var water_squares = new List<Vector2>(new[] { new Vector2(water_x, water_y) });
60 var squares_to_add = new HashSet<Vector2>();
61 var odds = 0.50;
62
63 var water_size = random_generator.Next(50, 250);
64
65 while (water_squares.Count < water_size) {
66 foreach (var square in water_squares)
67 {
68 foreach (var new_square in new[] {new Vector2(square.X + 1, square.Y),
69 new Vector2(square.X, square.Y + 1),
70 new Vector2(square.X - 1, square.Y),
71 new Vector2(square.X, square.Y - 1)
72 })
73 {
74 if (random_generator.NextDouble() < odds
75 && !water_squares.Contains(new_square)
76 && MathUtils.Between(new_square.X, 0, this.simulation.map.MapWidth)
77 && MathUtils.Between(new_square.Y, 0, this.simulation.map.MapHeight)
78 )
79 {
80 squares_to_add.Add(new_square);
81 }
82 }
83 }
84 water_squares.AddRange(squares_to_add);
85 squares_to_add.Clear();
86 }
87 this.simulation.map.WaterCells.AddRange(water_squares);
88
89 foreach (var square in water_squares) {
90 this.simulation.map.cells[(int)square.X][(int)square.Y].AddWater();
91
92 }
93 }
94
95 for (int i = 0; i < Simulation.NUM_PONDS; i++) {
96 var water_x = this.random_generator.Next(0, this.simulation.map.MapWidth);
97 var water_y = this.random_generator.Next(0, this.simulation.map.MapHeight);
98 this.simulation.map.WaterCells.Add(new Vector2(water_x, water_y));
99 this.simulation.map.cells[water_x][water_y].AddWater();
100 Logging.Info(String.Format("Adding water at {0},{1}", water_x, water_y));
101 }
102
103
104 #endregion
44 105 #region generate_trees
45 106
46 107 foreach (List<Cell> row in this.simulation.map.cells)
47 108 {
48 109 foreach (Cell cell in row)
49 110 {
50 if (this.random_generator.NextDouble() > 0.75)
111 var next = this.random_generator.NextDouble();
112 if (next > 0.75 && !cell.HasWater)
51 113 {
52 114 int random_year = (int)MathHelper.Clamp((float)MathUtils.NextNormal(random_generator, 2010.0f, 40.0f), 1800, Simulation.START_YEAR);
53 int random_month = random_generator.Next(1, 12);
115 int random_month = random_generator.Next(1, 13);
54 116 DateTime random_date = new DateTime(random_year, random_month, 1);
55 117
56 cell.addTree(random_date);
118 int random_type = random_generator.Next(0, 4);
119
120 cell.AddTree(random_date, (TreeType)random_type);
57 121 }
58 122 }
59 123 }
@@ -123,18 +187,27
123 187 #endregion
124 188 this.simulation.Subsidy = message.Difficulty switch {
125 189 DifficultyLevel.Hard => 0M,
126 DifficultyLevel.Medium => 760M,
127 DifficultyLevel.Easy => 1000M,
190 DifficultyLevel.Medium => 12_550M,
191 DifficultyLevel.Easy => 15_000M,
128 192 _ => 1000M
129 193 };
130 194
131 195 this.simulation.SubsidyDelta = message.Difficulty switch {
132 196 DifficultyLevel.Hard => 0M,
133 DifficultyLevel.Medium => -10M,
197 DifficultyLevel.Medium => -50M,
134 198 DifficultyLevel.Easy => 0M,
135 199 _ => 1000M
136 200 };
137 201
202 #region
203
204 var cursorEntity = CreateEntity();
205 AddComponent(cursorEntity,
206 new CursorComponent { position = new Vector2(20, 20),
207 size = 1 });
208
209 #endregion
210
138 211 Logging.Success("Spawned new game.");
139 212 }
140 213 }
@@ -20,11 +20,14
20 20 typeof(SetWindowVisibilityMessage),
21 21 typeof(SelectMessage),
22 22 typeof(SetDialogMessage),
23 typeof(DialogChoiceMessage))]
23 typeof(DialogChoiceMessage),
24 typeof(AdjustSelection),
25 typeof(ToggleToolMessage))]
24 26 [Reads(typeof(DialogComponent),
25 27 typeof(WindowTypeComponent),
26 28 typeof(VisibilityComponent),
27 typeof(SelectedComponent))]
29 typeof(SelectedComponent),
30 typeof(ToolComponent))]
28 31 [Writes(typeof(VisibilityComponent),
29 32 typeof(SelectedComponent))]
30 33 class UIEngine : Engine
@@ -40,15 +43,14
40 43 {
41 44 foreach (var entity in ReadEntities<SelectedComponent>())
42 45 {
43 SetComponent(entity, new SelectedComponent { selected = false });
46 var selected = GetComponent<SelectedComponent>(entity);
47 if (selected.Type == SelectionType.Window) {
48 SetComponent(entity, new SelectedComponent { selected = false });
49 }
44 50 }
45 51
46 52 foreach (ref readonly var windowMessage in ReadMessages<SetWindowVisibilityMessage>())
47 53 {
48 Logging.Spy(windowMessage, "message");
49 Logging.Spy(windowMessage.Entity, "message.Entity");
50 Logging.Spy(windowMessage.Entity.ID, "message.Entity.ID");
51 Logging.Spy(windowMessage.Visibility, "message.Visibility");
52 54 foreach (ref readonly var entity in ReadEntities<WindowTypeComponent>())
53 55 {
54 56 Logging.Spy(entity.ID, "ID");
@@ -62,9 +64,6
62 64 }
63 65 foreach (ref readonly var windowMessage in ReadMessages<ToggleWindowMessage>())
64 66 {
65 Logging.Spy(windowMessage, "message");
66 Logging.Spy(windowMessage.Window, "message.Window");
67 Logging.Spy(windowMessage.Entity, "message.Entity");
68 67 foreach (ref readonly var entity in ReadEntities<WindowTypeComponent>())
69 68 {
70 69 if (EntityExists(windowMessage.Entity) && entity.ID == windowMessage.Entity.ID)
@@ -77,8 +76,6
77 76 }
78 77 foreach (ref readonly var windowMessage in ReadMessages<ToggleWindowTypeMessage>())
79 78 {
80 Logging.Spy(windowMessage, "message");
81 Logging.Spy(windowMessage.Window, "message.Window");
82 79 foreach (ref readonly var entity in ReadEntities<WindowTypeComponent>())
83 80 {
84 81
@@ -88,7 +85,30
88 85 var visibilityComponent = GetComponent<VisibilityComponent>(entity);
89 86 SetComponent(entity, new VisibilityComponent { visible = !visibilityComponent.visible });
90 87 }
88 }
89 }
91 90
91
92 //Set tool
93 foreach (ref readonly var toolMessage in ReadMessages<ToggleToolMessage>())
94 {
95 foreach (ref readonly var entity in ReadEntities<ToolComponent>())
96 {
97
98 var tool_type = GetComponent<ToolComponent>(entity).Tool;
99 if (tool_type == toolMessage.Tool)
100 {
101 //Clear selections
102 foreach (ref readonly var inner_entity in ReadEntities<ToolComponent>())
103 {
104 var inner_selected_component = GetComponent<SelectedComponent>(inner_entity);
105 inner_selected_component.selected = false;
106 SetComponent(inner_entity, inner_selected_component);
107 }
108 var selectedComponent = GetComponent<SelectedComponent>(entity);
109 selectedComponent.selected = !selectedComponent.selected;
110 SetComponent(entity, selectedComponent);
111 }
92 112 }
93 113 }
94 114
@@ -98,7 +118,19
98 118 new SelectedComponent { selected = true });
99 119 }
100 120
101
102 }
103 }
121 foreach (ref readonly var message in ReadMessages<AdjustSelection>()) {
122 if(message.Type == AdjustmentType.Complete) {
123 foreach (ref readonly var entity in ReadEntities<SelectedComponent>()) {
124 var selection = GetComponent<SelectedComponent>(entity);
125 if(selection.Type == SelectionType.Area
126 && selection.selected) {
127 SetComponent(entity, new SelectedComponent {Type = SelectionType.Area,
128 selected = false
129 });
130 }
131 }
132 }
133 }
134 }
135 }
104 136 }
@@ -11,6 +11,7
11 11 using System.Collections.Generic;
12 12 using System.Linq;
13 13 using SpriteFontPlus;
14 using JM.LinqFaster;
14 15
15 16 using isometricparkfna;
16 17 using static isometricparkfna.CellMap;
@@ -25,7 +26,6
25 26
26 27 using ImGuiNET.SampleProgram.XNA;
27 28 using ImGuiNET;
28 using ImPlotNET;
29 29 using TraceryNet;
30 30 using Encompass;
31 31 using Ink.Runtime;
@@ -43,11 +43,13
43 43 private MouseState mousePrev = new MouseState();
44 44
45 45 private SpriteBatch batch;
46 #if DEBUG
46 private SpriteBatch tileBatch;
47 // #if DEBUG
47 48 private SoundEffect sound;
48 #endif
49 // #endif
49 50 private SpriteFont monoFont;
50 51 private SpriteFont largeMonoFont;
52 private SpriteFont ocrFont;
51 53
52 54 private Camera camera = new Camera(new float[] {0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f });
53 55
@@ -55,15 +57,23
55 57
56 58 int frameRate = 0;
57 59 int frameCounter = 0;
60 long totalFrameCounter = 0; //Will cover over a billion years at 60 fps
58 61 TimeSpan elapsedTime = TimeSpan.Zero;
59 62 TimeSpan drawTime = TimeSpan.Zero;
60 63 TimeSpan tileDrawTime = TimeSpan.Zero;
61 64 TimeSpan gridDrawTime = TimeSpan.Zero;
62 65 TimeSpan treeDrawTime = TimeSpan.Zero;
66 TimeSpan rendererDrawTime = TimeSpan.Zero;
67 TimeSpan miscUIDrawTime = TimeSpan.Zero;
68 TimeSpan debugDrawTime = TimeSpan.Zero;
63 69 TimeSpan updateTime = TimeSpan.Zero;
70 TimeSpan worldUpdateTime = TimeSpan.Zero;
71 TimeSpan simulationUpdateTime = TimeSpan.Zero;
64 72
65 73 Queue<float> past_fps = new Queue<float>(100);
66 Queue<TimeSpan> past_draw = new Queue<TimeSpan>(100);
74 List<float> past_fps_sorted = new List<float>(100);
75 // Queue<TimeSpan> past_draw = new Queue<TimeSpan>(100);
76 List<float> past_draw_millis = new List<float>(100);
67 77 int tilesDrawn = 0;
68 78
69 79 private static int width = 1280;
@@ -81,6 +91,8
81 91 //for now
82 92 public bool in_zone;
83 93 public bool in_active_zone;
94 public bool in_preserve;
95 public bool has_tower;
84 96
85 97 public bool isPlaying = false;
86 98
@@ -116,8 +128,7
116 128
117 129 public bool quit = false;
118 130
119
120
131 [STAThread]
121 132 private static void Main(string[] args)
122 133 {
123 134 #if NETCOREAPP
@@ -148,8 +159,6
148 159 {
149 160 Logging.Debug("Loaded: " + assembly.ToString() + "\n");
150 161 }
151 ;
152
153 162 #endif
154 163 this.gdm = new GraphicsDeviceManager(this) {
155 164 // Typically you would load a config here...
@@ -162,7 +171,6
162 171
163 172 this.simulation = new Simulation(this.squaresAcross, this.squaresDown, new float[] {16.66667f*240, 16.66667f*120, 16.66667f*60, 16.66667f*30, 16.66667f*1 });
164 173
165
166 174 showBudget = false;
167 175 showGrid = true;
168 176 showTrees = true;
@@ -188,12 +196,17
188 196 protected override void LoadContent()
189 197 {
190 198 // Create the batch...
191 batch = new SpriteBatch(GraphicsDevice);
199 this.batch = new SpriteBatch(GraphicsDevice);
200 this.tileBatch = new SpriteBatch(GraphicsDevice);
192 201
193 #if DEBUG
194 sound = Content.Load<SoundEffect>("FNASound");
195 #endif
196 Tile.TileSetTexture = Content.Load<Texture2D>(@"part4_tileset");
202 this.sound = SoundEffectEngine.LoadSound(Content, "FNASound");
203 SoundEffectEngine.LoadSound(Content, "Click");
204 SoundEffectEngine.LoadSound(Content, "ClickPart1");
205 SoundEffectEngine.LoadSound(Content, "ClickPart2");
206 SoundEffectEngine.LoadSound(Content, "Construction");
207 SoundEffectEngine.LoadSound(Content, "ConstructionShort");
208 SoundEffectEngine.LoadSound(Content, "Bell");
209 Tile.TileSetTexture = Content.Load<Texture2D>(@"merged_tileset");
197 210 var texture = Content.Load<Texture2D>(@"solid_tileset");
198 211
199 212 var imageMapTexture = Content.Load<Texture2D>(@"photos_converted3");
@@ -238,8 +251,25
238 251 new CharacterRange((char) 0x00B7)
239 252 }
240 253 );
254
255 var bakedOCR = TtfFontBaker.Bake(File.OpenRead(@"Content/OCRA.ttf"),
256 18,
257 1024,
258 1024,
259 new[]
260 {
261 CharacterRange.BasicLatin,
262 CharacterRange.Latin1Supplement,
263 CharacterRange.LatinExtendedA,
264 CharacterRange.Cyrillic,
265 CharacterRange.LatinExtendedB,
266 new CharacterRange((char) 0x00B7)
267 }
268 );
269
241 270 monoFont = bakedMono.CreateSpriteFont(GraphicsDevice);
242 271 largeMonoFont = bakedMonoLarge.CreateSpriteFont(GraphicsDevice);
272 ocrFont = bakedOCR.CreateSpriteFont(GraphicsDevice);
243 273
244 274 //Has to happen before Encompass stuff, because the Encompass machinery around ImGui requires debugWindow's monoFont to be loaded:
245 275 this.debugWindow = new DebugWindow(this._imGuiRenderer, GraphicsDevice, this.imageMap);
@@ -260,15 +290,20
260 290 this.imGuiWindowBridgeEngine.typeMessages.Add(new ToggleWindowTypeMessage {Window = isometricparkfna.Messages.Window.MainMenu});
261 291 });
262 292
263 Logging.Debug(this.Story.ContinueMaximally());
293 var gameBridgeEngine = new GameBridgeEngine(this);
294 Story.BindExternalFunction("undoPreserve", () => {
295 gameBridgeEngine.undoPreserveMessages.Add(new UndoPreserveMessage {});
296 });
264 297
265 WorldBuilder.AddEngine(new InputEngine(Menu.MENU_BAR_HEIGHT, this.camera, gdm));
298 Logging.Debug("Continuing Maximally: " + this.Story.ContinueMaximally().ToString());
299
300 WorldBuilder.AddEngine(new InputEngine(Menu.MENU_BAR_HEIGHT, this.camera, gdm,
301 this.simulation.map.MapHeight, this.simulation.map.MapWidth));
266 302 WorldBuilder.AddEngine(new UIEngine(this.Story));
267 303 WorldBuilder.AddEngine(new DialogEngine(this.Story, this.grammar));
268 304
269 305 WorldBuilder.AddEngine(new EventEngine());
270 306
271 var gameBridgeEngine = new GameBridgeEngine(this);
272 307
273 308 WorldBuilder.AddEngine(gameBridgeEngine);
274 309 WorldBuilder.AddEngine(new GameStateEngine());
@@ -285,10 +320,13
285 320 WorldBuilder.AddEngine(new PolicyEngine());
286 321 WorldBuilder.AddEngine(new TraceryBridgeEngine(this.grammar));
287 322 WorldBuilder.AddEngine(new SimulationGameRateBridgeEngine(this.simulation));
288
323 WorldBuilder.AddEngine(new BuildToolEngine(this.simulation));
324 WorldBuilder.AddEngine(new SoundEffectEngine());
289 325
290 WorldBuilder.AddGeneralRenderer(new AreaRenderer(this.batch, this.monoFont), 1);
326 WorldBuilder.AddGeneralRenderer(new AreaRenderer(this.tileBatch, this.monoFont), 1);
291 327 WorldBuilder.AddGeneralRenderer(new ImGuiWindowRenderer(this, this.simulation, this.imGuiWindowBridgeEngine, this.gdm), 2);
328 WorldBuilder.AddGeneralRenderer(new CursorRenderer(this.tileBatch, this.monoFont), 3);
329 WorldBuilder.AddGeneralRenderer(new StructureRenderer(this.tileBatch, this.monoFont), 4);
292 330 var contractWindow = WorldBuilder.CreateEntity();
293 331 WorldBuilder.SetComponent(contractWindow, new VisibilityComponent { visible = false });
294 332 WorldBuilder.SetComponent(contractWindow, new WindowTypeComponent { type = isometricparkfna.Messages.Window.Contracts });
@@ -322,6 +360,14
322 360 WorldBuilder.SetComponent(graphWindow, new VisibilityComponent { visible = false });
323 361 WorldBuilder.SetComponent(graphWindow, new WindowTypeComponent { type = isometricparkfna.Messages.Window.Graph });
324 362
363 //Create a tool for each tool type.
364 foreach (var tool in System.Enum.GetValues(typeof(Tool))) {
365 if ((Tool)tool != Tool.None) {
366 var toolEntity = WorldBuilder.CreateEntity();
367 WorldBuilder.SetComponent(toolEntity, new ToolComponent { Tool = (Tool)tool });
368 WorldBuilder.SetComponent(toolEntity, new SelectedComponent {Type = SelectionType.Tool, selected = ((Tool)tool == Tool.Preserve)});
369 }
370 }
325 371
326 372 var gameEntity = WorldBuilder.CreateEntity();
327 373
@@ -341,9 +387,12
341 387 fontName = options.fontName
342 388 });
343 389
344 WorldBuilder.SetComponent(gameEntity, new OptionsComponent {ProfanitySetting = options.profanitySetting});
390 WorldBuilder.SetComponent(gameEntity, new OptionsComponent {ProfanitySetting = options.profanitySetting,
391 SoundEffectVolume = options.SoundEffectVolume,
392 SoundEffectMuted = options.SoundEffectMuted
393 });
345 394
346 OptionsWindow.Initialize(new Vector2(FNAGame.width, FNAGame.height), gdm.IsFullScreen, options.profanitySetting);
395 OptionsWindow.Initialize(new Vector2(FNAGame.width, FNAGame.height), gdm.IsFullScreen, options.profanitySetting, options);
347 396 Logging.Success("Loaded options.");
348 397
349 398 }
@@ -352,6 +401,8
352 401 Logging.Error(String.Format("Error loading file: {0}", e.ToString()));
353 402 }
354 403
404 this.debugWindow.engine = this.imGuiWindowBridgeEngine;
405
355 406 World = WorldBuilder.Build();
356 407
357 408 this.output = grammar.Flatten("#greeting#");
@@ -379,7 +430,7
379 430 }
380 431 this.simulation.LoadContent(this.newsItems, this.grammar);
381 432
382 this.budgetWindow = new BudgetWindow(new Budget { }, this.monoFont, 0, 0);
433 this.budgetWindow = new BudgetWindow(new Budget { }, this.ocrFont, 0, 0);
383 434
384 435 Logging.Success("Content loaded.");
385 436 }
@@ -411,9 +462,11
411 462 protected override void UnloadContent()
412 463 {
413 464 batch.Dispose();
414 #if DEBUG
465 // #if DEBUG
415 466 sound.Dispose();
416 #endif
467 SoundEffectEngine.DisposeSounds();
468
469 // #endif
417 470 Tile.TileSetTexture.Dispose();
418 471 Logging.Success("Disposed of Tile texture.");
419 472 if (Quad.PixelTexture != null)
@@ -439,10 +492,28
439 492 }
440 493
441 494
495 private String CurrentStatus() {
496
497 if (this.in_active_zone) {
498 return "Contracted";
499 }
500 else if (this.in_zone) {
501 return "Proposed Contract";
502 }
503 else if (this.in_preserve) {
504 return "Preserve";
505 }
506 else {
507 return "Unused";
508 }
509 }
510
511
442 512
443 513 protected override void Update(GameTime gameTime)
444 514 {
445 515 Stopwatch stopWatch = new Stopwatch();
516 Stopwatch stopWatch2 = new Stopwatch();
446 517 stopWatch.Start();
447 518
448 519 #if DEBUG
@@ -468,15 +539,22
468 539 #endregion misc_keys
469 540 #endregion input
470 541
542 stopWatch2.Start();
471 543 World.Update(gameTime.ElapsedGameTime.TotalSeconds);
544 stopWatch2.Stop();
545 this.worldUpdateTime = stopWatch2.Elapsed;
546
547 stopWatch2 = new Stopwatch();
548 stopWatch2.Start();
472 549 this.simulation.update(gameTime.ElapsedGameTime);
550 stopWatch2.Stop();
551 this.simulationUpdateTime = stopWatch2.Elapsed;
473 552
474 553 if (this.showBudget)
475 554 {
476 555 this.showBudget = this.budgetWindow.update(mouseCur, this.simulation.latestBudget, this.simulation.previousBudget);
477 556 }
478 557
479
480 558 this.original_point = Vector2.Transform(new Vector2(mouseCur.X, mouseCur.Y), Matrix.Invert(camera.get_transformation(GraphicsDevice)));
481 559
482 560 this.mouseGrid = this.calculateMousegrid(this.original_point);
@@ -519,23 +597,108
519 597 && MathUtils.BetweenExclusive(original.Y, -Tile.TileSpriteHeight, FNAGame.height)));
520 598 }
521 599
600
522 601 //Convenience method I'm not super sure about anymore.
523 protected void drawTileAt(int x, int y, int tileIndex, int height)
602 protected void drawTileAt(int x, int y, int tileIndex, int height, Color color, SpriteBatch batch)
524 603 {
525 604 float maxdepth = ((this.squaresAcross + 1) + ((this.squaresDown + 1) * Tile.TileWidth)) * 10;
526 605
527 float depthOffset = 0.7f - ((0 + (0 * Tile.TileWidth)) / maxdepth);
606 float depthOffset = 0.7f - ((x + (y * Tile.TileWidth)) / maxdepth);
607
608 Tile.drawTileAt(batch, x, y, tileIndex, height, depthOffset, color);
609 }
610
611 protected void drawTileAt(int x, int y, int tileIndex, int height, Color color) {
612 drawTileAt(x, y, tileIndex, height, Color.White, this.tileBatch);
613 }
614
615 protected void drawTileAt(int x, int y, int tileIndex, int height) {
616 drawTileAt(x, y, tileIndex, height, Color.White);
617 }
618
619 protected void drawWaterTileAt(int x, int y, int height) {
620 drawWaterTileAt(x, y, height, this.tileBatch);
621 }
622
623 protected void drawWaterTileAt(int x, int y, int height, SpriteBatch batch) {
624 var tile_index = 85;
625 var cells = this.simulation.map.cells;
626
627 //Unfortunately this is tileset dependent and pretty awkward to type out :(
628 var northwest = (x != 0 && (cells[x-1][y].Status == CellStatus.Water));
629 var northeast = (y != 0 && (cells[x][y-1].Status == CellStatus.Water));
630 var southwest = (y < (this.simulation.map.MapHeight-1) && cells[x][y+1].Status == CellStatus.Water);
631 var southeast = (x < (this.simulation.map.MapWidth-1) && cells[x+1][y].Status == CellStatus.Water);
632
528 633
529 Tile.drawTileAt(this.batch, x, y, tileIndex, height, depthOffset);
634 if (northwest && northeast && southwest && southeast) {
635 //There are two "open water" squares
636 if (((y % 5) == 0) && ((x % 3) == 0)) {
637 tile_index = 84;
638 }
639 else {
640 tile_index = 85;
641 }
642 }
643 else if (northwest && northeast && southwest && !southeast) {
644 tile_index = 82;
645 }
646 else if (northwest && northeast && !southwest && southeast) {
647 tile_index = 81;
648 }
649 else if (northwest && northeast && !southwest && !southeast) {
650 tile_index = 80;
651 }
652 else if (northwest && !northeast && southwest && southeast) {
653 tile_index = 88;
654 }
655 else if (northwest && !northeast && southwest && !southeast) {
656 tile_index = 86;
657 }
658 else if (northwest && !northeast && !southwest && southeast) {
659 tile_index = 91;
660 }
661 else if (northwest && !northeast && !southwest && !southeast) {
662 tile_index = 90; //Not really correct
663 }
664 else if (!northwest && northeast && southwest && southeast) {
665 tile_index = 87;
666 }
667 else if (!northwest && northeast && southwest && !southeast) {
668 tile_index = 92;
669 }
670 else if (!northwest && northeast && !southwest && southeast) {
671 tile_index = 83;
672 }
673 else if (!northwest && northeast && !southwest && !southeast) {
674 tile_index = 95; //not really correct
675 }
676 else if (!northwest && !northeast && southwest && southeast) {
677 tile_index = 89;
678 }
679 else if (!northwest && !northeast && southwest && !southeast) {
680 tile_index = 95;
681 }
682 else if (!northwest && !northeast && !southwest && southeast) {
683 tile_index = 95;
684 }
685 //Shouldn't really exist:
686 else if (!northwest && !northeast && !southwest && !southeast) {
687 tile_index = 101;
688 }
689
690 drawTileAt(x, y, tile_index, height, Color.White, batch);
530 691 }
531 692
532 693
533 694 protected override void Draw(GameTime gameTime)
534 695 {
535 696 frameCounter++;
697 totalFrameCounter++;
536 698
537 699 string fps = string.Format("fps: {0}", frameRate);
538 700 bool has_tree = false;
701 Stopwatch stopWatch2 = new Stopwatch();
539 702
540 703 Stopwatch stopWatch = new Stopwatch();
541 704 stopWatch.Start();
@@ -554,48 +717,28
554 717
555 718
556 719 #region draw_tiles
557 Stopwatch stopWatch2 = new Stopwatch();
558 720 stopWatch2.Start();
559 721 //reset
560 722 this.tilesDrawn = 0;
561 723
562 var scale_factor = 1;
563 var x_adjust = scale_factor > 1 ? -scale_factor : 0;
564 var y_adjust = scale_factor > 1 ? -scale_factor/2 : 0;
565
566 for (int y = y_adjust; y < this.squaresDown + y_adjust; y += scale_factor)
724 for (int i = 0; i < this.simulation.map.MapHeight; i++)
567 725 {
568 for (int x = x_adjust; x < this.squaresAcross + x_adjust; x += scale_factor)
726 for (int j = 0; j < this.simulation.map.MapWidth; j += 1)
569 727 {
570 int screenx = (x - y) * (Tile.TileSpriteWidth) / 2 - 3*scale_factor;
571 int screeny = (x + y) * (Tile.TileSpriteHeight) / 2;
572
573 // if (this.cull(x, y))
574 // {
575 batch.Draw(
576 Tile.TileSetTexture,
577 new Rectangle(
578 screenx,
579 screeny,
580 Tile.TileWidth * scale_factor, Tile.TileHeight * scale_factor),
581 Tile.GetSourceRectangle(1),
582 Color.White,
583 0.0f,
584 Vector2.Zero,
585 SpriteEffects.None,
586 0.9f);
587
588 this.tilesDrawn++;
589 // }
728 drawTileAt(i, j, 1, 1, Color.White, batch);
729 this.tilesDrawn++;
590 730 }
591 731 }
732 foreach (var cell in this.simulation.map.WaterCells) {
733 drawWaterTileAt((int)cell.X, (int)cell.Y, 1, batch);
734 }
592 735 batch.End();
593 736 stopWatch2.Stop();
594 737 this.tileDrawTime = stopWatch2.Elapsed;
595 738 #endregion draw_tiles
596 739
597 740 #region draw_gridlines
598 batch.Begin(SpriteSortMode.BackToFront,
741 batch.Begin(SpriteSortMode.Deferred,
599 742 BlendState.AlphaBlend,
600 743 null,
601 744 null,
@@ -616,7 +759,6
616 759 Line.drawLine(batch,
617 760 new Vector2(((0 - y) * Tile.TileSpriteWidth / 2),
618 761 (0 + y) * Tile.TileSpriteHeight / 2) + adjust,
619 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
620 762 new Vector2((this.squaresAcross - (y)) * Tile.TileSpriteWidth / 2,
621 763 (this.squaresAcross + (y)) * Tile.TileSpriteHeight / 2) + adjust,
622 764
@@ -631,95 +773,66
631 773
632 774 Line.drawLine(batch,
633 775 new Vector2(((x - 0) * Tile.TileSpriteWidth / 2), (x + 0) * Tile.TileSpriteHeight / 2) + adjust,
634 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
635 776 new Vector2((x - this.squaresDown) * Tile.TileSpriteWidth / 2, (x + this.squaresDown) * Tile.TileSpriteHeight / 2) + adjust,
636 777 Color.White, 0.81f);
637 778
638 779 }
639 780 }
781 batch.End();
640 782 stopWatch2.Stop();
641 783 this.gridDrawTime = stopWatch2.Elapsed;
642 784 #endregion draw_gridlines
643 785
644
645 //Gridlines
646 //Lines going down and to the right:
647 /*
648 for (int x = (int)(-this.squaresAcross/2); x < this.squaresAcross; x++)
649 {
650 int rowOffset = 0;
651
652 float startX = (x * Tile.TileStepX) + baseOffsetX - (Tile.TileStepX / 2);
653
654 Vector2 start = new Vector2(startX, -baseOffsetY+4);
655 Vector2 stop = new Vector2(startX + this.squaresAcross* Tile.TileStepX/2,
656 this.squaresDown*Tile.TileStepY- baseOffsetY+4);
657
658
786 tileBatch.Begin(SpriteSortMode.BackToFront,
787 BlendState.AlphaBlend,
788 null,
789 null,
790 null,
791 null,
792 camera.get_transformation(GraphicsDevice));
793 #if DEBUG
659 794
660 Line.drawLine(batch,
661 Line.departurePoint(stop, start, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
662 Line.departurePoint(start, stop, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
663 Color.White, 0.8f);
664
665 }
666 //Lines going down and to the left:
667 for (int x = 0; x < (int)(1.5*this.squaresAcross); x++)
668 {
669
670 float startX = (x * Tile.TileStepX) + baseOffsetX - (Tile.TileStepX / 2);
795 var translucent = new Color(1.0f, 1.0f, 1.0f, 0.25f);
796 drawTileAt(4, 4, 140, 3, translucent);
797 drawTileAt(6, 4, 141, 3, translucent);
798 drawTileAt(8, 4, 142, 2, translucent);
799 drawTileAt(10, 4, 142, 3, translucent);
671 800
672 Vector2 start_reverse = new Vector2(startX, -baseOffsetY + 4);
673 Vector2 stop_reverse = new Vector2(startX + -(this.squaresAcross * Tile.TileStepX / 2),
674 (this.squaresDown * Tile.TileStepY) - baseOffsetY + 4);
675
676 Line.drawLine(batch,
677 Line.departurePoint(stop_reverse, start_reverse, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
678 Line.departurePoint(start_reverse, stop_reverse, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
679 Color.White, 0.8f);
680
681 }
682 */
801 for (int i = 10; i < 199; i++) {
802 drawTileAt(10, i, 281, 1, translucent);
803 }
804 drawTileAt(10, 199, 284, 1, translucent);
805 drawTileAt(11, 199, 280, 1, translucent);
806 drawTileAt(12, 199, 280, 1, translucent);
807 drawTileAt(13, 199, 283, 1, translucent);
808 drawTileAt(13, 198, 281, 1, translucent);
809 drawTileAt(13, 197, 282, 1, translucent);
810 drawTileAt(12, 197, 285, 1, translucent);
811 drawTileAt(12, 25, 300, 2, translucent);
812 #endif
683 813
684 814 #if DEBUG
685 drawTileAt(4, 4, 140, 3);
686 drawTileAt(6, 4, 141, 3);
687 drawTileAt(8, 4, 142, 2);
688 drawTileAt(10, 4, 142, 3);
689 #endif
690
691 #region draw_cursor
692
693 if (MathUtils.Between(this.mouseGrid.X, 0, this.simulation.map.MapWidth)
694 && MathUtils.Between(this.mouseGrid.Y, 0, this.simulation.map.MapHeight))
695 {
696 Tile.OutlineSquare(batch, this.mouseGrid.X, this.mouseGrid.Y, Color.Yellow, 1);
697 }
698
699 #if DEBUG
700 Tile.OutlineSquare(batch, 1, 1, Color.Red, 2);
701 Tile.OutlineSquare(batch, 3, 1, Color.Blue, 2);
702 Tile.OutlineSquare(batch, 5, 1, Color.Green, 2);
703 Tile.OutlineSquare(batch, 7, 1, Color.Orange, 2);
704 Tile.OutlineSquare(batch, 9, 1, Color.Orange, 3);
815 Tile.OutlineSquare(tileBatch, 1, 1, Color.Red, 2);
816 Tile.OutlineSquare(tileBatch, 3, 1, Color.Blue, 2);
817 Tile.OutlineSquare(tileBatch, 5, 1, Color.Green, 2);
818 Tile.OutlineSquare(tileBatch, 7, 1, Color.Orange, 2);
819 Tile.OutlineSquare(tileBatch, 9, 1, Color.Orange, 3);
705 820
706 821 //donut
707 Tile.DrawOutlinedSquares(batch, new Vector2[] {new Vector2(19, 1), new Vector2(19, 2), new Vector2(20, 1), new Vector2(21, 1),
822 Tile.DrawOutlinedSquares(tileBatch, new Vector2[] {new Vector2(19, 1), new Vector2(19, 2), new Vector2(20, 1), new Vector2(21, 1),
708 823 new Vector2(21, 2), new Vector2(19, 3), new Vector2(20, 3), new Vector2(21, 3)
709 824 }, Color.Purple);
710 825
711 Quad.FillSquare2(batch, 7, 4, Color.Orange, 1.0f, 0.79f);
712 Quad.FillSquare2(batch, 7, 3, Color.Yellow, 1.0f, 0.79f);
713 Quad.FillSquare2(batch, 7, 5, Color.Yellow, .5f, 0.79f);
714 Quad.FillSquare2(batch, 7, 6, Color.Yellow, .25f, 0.79f);
715 Quad.FillSquare2(batch, 7, 7, Color.Yellow, .125f, 0.79f);
716 Quad.FillSquare2(batch, 8, 5, Color.Teal, .5f, 0.79f);
717 Quad.FillSquare2(batch, 8, 6, Color.Teal, .25f, 0.79f);
718 Quad.FillSquare2(batch, 8, 7, Color.Teal, .125f, 0.79f);
826 Quad.FillSquare2(tileBatch, 7, 4, Color.Orange, 1.0f, 0.79f);
827 Quad.FillSquare2(tileBatch, 7, 3, Color.Yellow, 1.0f, 0.79f);
828 Quad.FillSquare2(tileBatch, 7, 5, Color.Yellow, .5f, 0.79f);
829 Quad.FillSquare2(tileBatch, 7, 6, Color.Yellow, .25f, 0.79f);
830 Quad.FillSquare2(tileBatch, 7, 7, Color.Yellow, .125f, 0.79f);
831 Quad.FillSquare2(tileBatch, 8, 5, Color.Teal, .5f, 0.79f);
832 Quad.FillSquare2(tileBatch, 8, 6, Color.Teal, .25f, 0.79f);
833 Quad.FillSquare2(tileBatch, 8, 7, Color.Teal, .125f, 0.79f);
719 834 #endif
720 835
721 #endregion draw_cursor
722
723 836 stopWatch2 = new Stopwatch();
724 837 stopWatch2.Start();
725 838 #region draw_trees
@@ -728,21 +841,23
728 841 {
729 842 for (int j = 0; j < this.simulation.map.MapWidth; j += 1)
730 843 {
731 if (this.simulation.map.cells[i][j].hasTree)
844 if (this.simulation.map.cells[i][j].HasTree)
732 845 { //until we actually simulate:
733 drawTileAt(i, j, 142, 2);
734 // if ((i + j) % 8 == 0)
735 // {
736 // drawTileAt(i, j, 141, 2);
737 // }
738 // else
739 // {
740 // drawTileAt(i, j, 142, 2);
741 // }
846 if (this.simulation.map.cells[i][j].Type == TreeType.GenericDeciduous) {
847 drawTileAt(i, j, 252, 2); // 142, , 262
848 }
849 else if (this.simulation.map.cells[i][j].Type == TreeType.Oak) {
850 drawTileAt(i, j, 142, 2);
851 }
852 else if (this.simulation.map.cells[i][j].Type == TreeType.GenericShrub) {
853 drawTileAt(i, j, 210, 2);
854 }
855 else {
856 drawTileAt(i, j, 122, 2); //122, 203, 221
857 }
742 858 }
743 else if (this.simulation.map.cells[i][j].status == CellStatus.DeadTree) {
859 else if (this.simulation.map.cells[i][j].Status == CellStatus.DeadTree) {
744 860 drawTileAt(i, j, 141, 2);
745 // System.Console.WriteLine(String.Format("Drew Dead Tree at {0},{1}", i, j));
746 861 }
747 862 }
748 863 }
@@ -757,11 +872,17
757 872 drawTileAt(3, 2, 140, 2);
758 873 #endif
759 874
875 stopWatch2 = new Stopwatch();
876 stopWatch2.Start();
760 877 World.Draw();
761 878 // _imGuiRenderer.AfterLayout();
762 batch.End();
879 tileBatch.End();
880 stopWatch2.Stop();
881 this.rendererDrawTime = stopWatch2.Elapsed;
763 882
764 883 #region draw_header
884 stopWatch2 = new Stopwatch();
885 stopWatch2.Start();
765 886 batch.Begin(SpriteSortMode.BackToFront,
766 887 BlendState.AlphaBlend,
767 888 null,
@@ -772,16 +893,37
772 893 if (MathUtils.BetweenExclusive(this.mouseGrid.X, 0, this.squaresAcross)
773 894 && MathUtils.BetweenExclusive(this.mouseGrid.Y, 0, this.squaresAcross))
774 895 {
775 has_tree = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].hasTree;
896 has_tree = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].HasTree;
776 897 }
777 898
778 899 String status_left = "";
779 900 if (MathUtils.BetweenExclusive(this.mouseGrid.X, -1, this.simulation.map.MapWidth)
780 901 && MathUtils.BetweenExclusive(this.mouseGrid.Y, -1, this.simulation.map.MapHeight))
781 902 {
782 status_left = String.Format("{0:},{1:} {2} ({3})", this.mouseGrid.X, this.mouseGrid.Y,
783 this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].status,
784 this.in_active_zone ? "Contracted" : (this.in_zone ? "Proposed Contract": "Unused"));
903 var cellStatus = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].Status;
904 var treeStatusAdjective = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].StatusAdjective;
905 var treeType = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].TypeName;
906 var useStatus = this.CurrentStatus();
907 if (cellStatus == CellStatus.Water) {
908
909 status_left = String.Format("{0:},{1:} Water ({2})", this.mouseGrid.X, this.mouseGrid.Y, useStatus);
910 }
911 else if (cellStatus != CellStatus.Clear)
912 {
913 status_left = String.Format("{0:},{1:} {2} {3} ({4})", this.mouseGrid.X, this.mouseGrid.Y,
914 treeStatusAdjective,
915 treeType,
916 useStatus);
917 }
918 else if (this.has_tower) {
919 status_left = String.Format("{0:},{1:} Watch Tower ({2})", this.mouseGrid.X, this.mouseGrid.Y,
920 useStatus);
921 }
922 else {
923 status_left = String.Format("{0:},{1:} {2} ({3})", this.mouseGrid.X, this.mouseGrid.Y,
924 treeStatusAdjective,
925 useStatus);
926 }
785 927 }
786 928
787 929 String header_left = String.Format("${0:}|{1:} \ue124", this.simulation.money, this.simulation.map.tree_count);
@@ -804,22 +946,26
804 946 batch.DrawString(monoFont, status_left, new Vector2(1, top), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
805 947 batch.DrawString(monoFont, header_left, new Vector2(1, 1), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
806 948 batch.DrawString(monoFont, header_middle, new Vector2(middle_start, 1), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
949
807 950 #endregion draw_header
808 951
952
953
954 #region window
955 Menu.Render(debugWindow.monoFont, FNAGame.width, this.imGuiWindowBridgeEngine, ref quit, ref this.simulation.paused, ref this.simulation.currentRate, ref this.showBudget, header_left);
956 stopWatch2.Stop();
957 this.miscUIDrawTime = stopWatch2.Elapsed;
958
809 959 #region budget
810 960
811 961 if (this.showBudget)
812 962 {
813 963 budgetWindow.draw(batch);
814 964 }
965 batch.End();
815 966
816 967 #endregion budget
817 968
818 batch.End();
819
820 #region window
821 Menu.Render(debugWindow.monoFont, FNAGame.width, this.imGuiWindowBridgeEngine, ref quit, ref this.simulation.paused, ref this.simulation.currentRate, ref this.showBudget, header_left);
822
823 969 if (quit) {
824 970 System.Environment.Exit(0);
825 971 }
@@ -866,12 +1012,17
866 1012
867 1013
868 1014 #region debug_window
1015 stopWatch2 = new Stopwatch();
1016 stopWatch2.Start();
869 1017 //Calcs for debug window:
870 past_draw.Enqueue(this.drawTime);
871 if ((this.frameCounter % 15) == 0)
1018 // past_draw.Enqueue(this.drawTime);
1019 if (this.totalFrameCounter > 60 && ((this.frameCounter % 15) == 0))
872 1020 {
1021 past_draw_millis.Add((float)this.drawTime.TotalMilliseconds);
1022 past_draw_millis.Sort();
873 1023 past_fps.Enqueue(this.frameRate);
874
1024 past_fps_sorted.Add(this.frameRate);
1025 past_fps_sorted.Sort();
875 1026
876 1027 /*
877 1028 if (this.frameRate > 60.0)
@@ -903,7 +1054,12
903 1054 treeDrawTime = this.treeDrawTime,
904 1055 gridDrawTime = this.gridDrawTime,
905 1056 tileDrawTime = this.tileDrawTime,
1057 rendererDrawTime = this.rendererDrawTime,
1058 miscUIDrawTime = this.miscUIDrawTime,
1059 debugDrawTime = this.debugDrawTime,
906 1060 updateTime = this.updateTime,
1061 worldUpdateTime = this.worldUpdateTime,
1062 simulationUpdateTime = this.simulationUpdateTime,
907 1063 treeCount = this.simulation.map.tree_count,
908 1064 mouseGrid = this.mouseGrid,
909 1065 hasTree = has_tree,
@@ -940,15 +1096,16
940 1096 additionalInfo.Add("Dialog entries", entries);
941 1097 additionalInfo.Add("Metadata entries", descriptions);
942 1098
943 if (past_fps.Count() > 5) {
944 additionalInfo.Add(".01%% fps", MathUtils.Percentile(past_fps.Skip(5).ToArray(), 0.0001f).ToString());
945 additionalInfo.Add(".1%% fps", MathUtils.Percentile(past_fps.Skip(5).ToArray(), 0.001f).ToString());
946 additionalInfo.Add("1%% fps", MathUtils.Percentile(past_fps.Skip(5).ToArray(), 0.01f).ToString());
947 additionalInfo.Add("50%% fps", MathUtils.Percentile(past_fps.Skip(5).ToArray(), 0.50f).ToString());
1099 if ((past_fps_sorted.Count() > 5) && show_another_window) {
1100 var past_fps_floats = past_fps_sorted.ToArray();
1101 additionalInfo.Add(".01%% fps", MathUtils.Percentile(past_fps_floats, 0.0001f).ToString());
1102 additionalInfo.Add(".1%% fps", MathUtils.Percentile(past_fps_floats, 0.001f).ToString());
1103 additionalInfo.Add("1%% fps", MathUtils.Percentile(past_fps_floats, 0.01f).ToString());
1104 additionalInfo.Add("50%% fps", MathUtils.Percentile(past_fps_floats, 0.50f).ToString());
948 1105 }
949 1106
950 if (past_draw.Count() > 5) {
951 var past_draw_floats = past_draw.Skip(5).Select(ts => ts.TotalMilliseconds).ToArray();
1107 if ((past_draw_millis.Count() > 5) && show_another_window) {
1108 var past_draw_floats = past_draw_millis.ToArray();
952 1109 additionalInfo.Add(".01%% draw", MathUtils.Percentile(past_draw_floats, 0.0001f).ToString());
953 1110 additionalInfo.Add(".1%% draw", MathUtils.Percentile(past_draw_floats, 0.001f).ToString());
954 1111 additionalInfo.Add("1%% draw", MathUtils.Percentile(past_draw_floats, 0.01f).ToString());
@@ -958,10 +1115,15
958 1115 additionalInfo.Add("99.99%% draw", MathUtils.Percentile(past_draw_floats, 0.9999f).ToString());
959 1116 }
960 1117
1118 additionalInfo.Add("Total frames", totalFrameCounter.ToString());
1119
961 1120 debugWindow.Layout(debugInfo, additionalInfo, ref show_another_window);
962 1121
963 1122 _imGuiRenderer.AfterLayout();
964 1123
1124 stopWatch2.Stop();
1125 this.debugDrawTime = stopWatch2.Elapsed;
1126
965 1127 #endregion debug_window
966 1128
967 1129 stopWatch.Stop();
@@ -5,7 +5,6
5 5 using System.Collections.Generic;
6 6 using System.Runtime.InteropServices;
7 7
8 using ImPlotNET;
9 8
10 9 namespace ImGuiNET.SampleProgram.XNA
11 10 {
@@ -45,9 +44,6
45 44 {
46 45 var context = ImGui.CreateContext();
47 46 ImGui.SetCurrentContext(context);
48 var plotContext = ImPlot.CreateContext();
49 ImPlot.SetCurrentContext(plotContext);
50 ImPlot.SetImGuiContext(context);
51 47
52 48 _game = game ?? throw new ArgumentNullException(nameof(game));
53 49 _graphicsDevice = game.GraphicsDevice;
@@ -52,12 +52,12
52 52 private static Dictionary<LogLevel, (ConsoleColor, ConsoleColor)> mappings = new Dictionary<LogLevel, (ConsoleColor, ConsoleColor)>
53 53 {
54 54 {LogLevel.Critical, (ConsoleColor.White, ConsoleColor.Red)},
55 {LogLevel.Error, (ConsoleColor.Red, ConsoleColor.Black)},
56 {LogLevel.Warning, (ConsoleColor.Yellow, ConsoleColor.Black)},
57 {LogLevel.Success, (ConsoleColor.Green, ConsoleColor.Black)},
58 {LogLevel.Info, (ConsoleColor.Blue, ConsoleColor.Black)},
59 {LogLevel.Debug, (ConsoleColor.White, ConsoleColor.Cyan)},
60 {LogLevel.Trace, (ConsoleColor.White, ConsoleColor.Yellow)},
55 {LogLevel.Error, (ConsoleColor.Black, ConsoleColor.Red)},
56 {LogLevel.Warning, (ConsoleColor.Black, ConsoleColor.Yellow)},
57 {LogLevel.Success, (ConsoleColor.White, ConsoleColor.Green)},
58 {LogLevel.Info, (ConsoleColor.White, ConsoleColor.Blue)},
59 {LogLevel.Debug, (ConsoleColor.Blue, ConsoleColor.Black)},
60 {LogLevel.Trace, (ConsoleColor.Magenta, ConsoleColor.Black)},
61 61 {LogLevel.Spy, (ConsoleColor.Black, ConsoleColor.White)},
62 62
63 63 };
@@ -6,5 +6,7
6 6 public struct SetOptionMessage : IMessage
7 7 {
8 8 public ProfanityLevel NewProfanitySetting;
9 public float NewSoundEffectVolume;
10 public bool NewSoundEffectMuted;
9 11 }
10 12 }
@@ -1,4 +1,3
1
2 1 using Encompass;
3 2
4 3 namespace isometricparkfna.Messages
@@ -17,7 +16,7
17 16 Options,
18 17 NewGame,
19 18 Dialog,
20 Graph,
19 Graph,
21 20 }
22 21
23 22
@@ -10,28 +10,34
10 10 Uncensored,
11 11 Minced,
12 12 Removed
13
14 13 }
15 14
16 15 public class Options
17 16 {
18
19 17 public string fontName;
20 18 public int fontSize;
21 19 public ProfanityLevel profanitySetting;
22 20
23 public Options(string fontName, int fontSize, ProfanityLevel profanitySetting)
21 //Sound
22 public float SoundEffectVolume;
23 public bool SoundEffectMuted;
24
25 public Options(string fontName, int fontSize, ProfanityLevel profanitySetting,
26 float soundEffectVolume, bool soundEffectMuted)
24 27 {
25 28 this.fontName = fontName;
26 29 this.fontSize = fontSize;
27 30 this.profanitySetting = profanitySetting;
28 31
32 this.SoundEffectVolume = soundEffectVolume;
33 this.SoundEffectMuted = soundEffectMuted;
29 34 }
30 35
31 public static void writeOptions(string fontName, int fontSize, ProfanityLevel profanitySetting)
36 public static void writeOptions(string fontName, int fontSize, ProfanityLevel profanitySetting,
37 float soundEffectVolume, bool soundEffectMuted)
32 38 {
33
34 var options = new Options(fontName, fontSize, profanitySetting);
39 var options = new Options(fontName, fontSize, profanitySetting, soundEffectVolume,
40 soundEffectMuted);
35 41
36 42 string json = JsonConvert.SerializeObject(options,
37 43 Formatting.Indented);
@@ -44,19 +50,13
44 50 public static Options readOptions()
45 51 {
46 52 var json = File.ReadAllText(@"options.json");
47 Logging.Spy(new {json=json});
53 Logging.Debug(new {json=json}.ToString());
48 54
49 55 Options options = JsonConvert.DeserializeObject<Options>(json);
50 56
51 Logging.Spy(new {name=options.fontName,
52 size=options.fontSize
53 });
54 57 Logging.Success("Read options.");
55 58
56 59 return options;
57 60 }
58
59
60
61 61 }
62 62 }
@@ -1,4 +1,3
1
2 1 using Microsoft.Xna.Framework;
3 2 using Microsoft.Xna.Framework.Graphics;
4 3
@@ -15,7 +14,6
15 14 private SpriteBatch batch;
16 15 private SpriteFont font;
17 16
18
19 17 public AreaRenderer(SpriteBatch batch, SpriteFont font)
20 18 {
21 19 this.batch = batch;
@@ -26,32 +24,38
26 24 public override void Render()
27 25 {
28 26
29 var budgetWindow = new BudgetWindow(new Budget { }, this.font, 0, 0);
27 var budgetWindow = new BudgetWindow(new Budget {}, this.font, 0, 0);
30 28
31 29 foreach (ref readonly var entity in ReadEntities<AreaComponent>())
32 30 {
33 31 var areaComponent = GetComponent<AreaComponent>(entity);
34 32 // var SelectedComponent = GetComponent<SelectedComponent>(entity);
33 var selected = GetComponent<SelectedComponent>(entity).selected;
35 34
36 if (!HasComponent<ContractStatusComponent>(entity)
37 || GetComponent<ContractStatusComponent>(entity).status == ContractStatus.Accepted
38 )
35 if (HasComponent<PreserveComponent>(entity) || areaComponent.Tool == Tool.Preserve)
36 {
37 Quad.FillSquares(batch, areaComponent.squares, Color.Blue, 0.5f, 0.79f);
38 Tile.DrawOutlinedSquares(batch, areaComponent.squares, Color.Blue);
39 }
40 else if (!HasComponent<ContractStatusComponent>(entity))
41 {
42 Quad.FillSquares(batch, areaComponent.squares, Color.Red, 0.5f, 0.79f);
43 Tile.DrawOutlinedSquares(batch, areaComponent.squares, Color.Red);
44 }
45 else if ((!HasComponent<ContractStatusComponent>(entity)
46 || GetComponent<ContractStatusComponent>(entity).status == ContractStatus.Accepted)
47 && !selected)
39 48 {
40 49 Tile.DrawOutlinedSquares(batch, areaComponent.squares, Color.Teal);
41 Quad.FillSquares(batch, areaComponent.squares, Color.Teal, 0.5f, 0.79f);
50 Quad.FillSquares(batch, areaComponent.squares, Color.Teal, 0.5f, 0.78f);
42 51 }
43
44 var selected = GetComponent<SelectedComponent>(entity).selected;
45
46 if (HasComponent<ContractStatusComponent>(entity)
47 && selected
48 // && GetComponent<SelectedComponent>(entity).selected
49 )
52 else if (HasComponent<ContractStatusComponent>(entity)
53 && selected)
50 54 {
51 55 Tile.DrawOutlinedSquares(batch, areaComponent.squares, Color.Teal);
52 Quad.FillSquares(batch, areaComponent.squares, Color.Gray, 0.5f, 0.80f);
56 Quad.FillSquares(batch, areaComponent.squares, Color.Gray, 0.5f, 0.78f);
53 57 }
54 58 }
55 59 }
56 60 }
57 } No newline at end of file
61 }
@@ -93,10 +93,12
93 93 var dialog_open = false;
94 94
95 95 ProfanityLevel profanityLevel = default;
96 OptionsComponent options_component = default;
96 97
97 98 foreach (ref readonly var entity in ReadEntities<OptionsComponent>())
98 99 {
99 profanityLevel = GetComponent<OptionsComponent>(entity).ProfanitySetting;
100 options_component = GetComponent<OptionsComponent>(entity);
101 profanityLevel = options_component.ProfanitySetting;
100 102 }
101 103
102 104
@@ -116,7 +118,9
116 118
117 119 foreach (var e in contracts)
118 120 {
119 contract_data.Add(getContractDetails(e));
121 if(HasComponent<ContractStatusComponent>(e)) {
122 contract_data.Add(getContractDetails(e));
123 }
120 124 }
121 125
122 126 ContractsWindow.Render(this.BridgeEngine.font, this.BridgeEngine, contract_data);
@@ -143,13 +147,13
143 147 InGameMenu.Render(this.BridgeEngine.font, this.BridgeEngine, width);
144 148 break;
145 149 case Window.Options:
146 OptionsWindow.Render(this.BridgeEngine.font, this.BridgeEngine.italicFont, this.BridgeEngine, width, profanityLevel);
150 OptionsWindow.Render(this.BridgeEngine.font, this.BridgeEngine.italicFont, this.BridgeEngine, width);
147 151 break;
148 152 case Window.NewGame:
149 153 NewGameWindow.Render(this.BridgeEngine.font, this.BridgeEngine.italicFont, this.BridgeEngine);
150 break;
151 case Window.Graph:
152 GraphWindow.Render(this.BridgeEngine.font, this.simulation, this.BridgeEngine);
154 break;
155 case Window.Graph:
156 GraphWindow.Render(this.BridgeEngine.font, this.simulation, this.BridgeEngine);
153 157 break;
154 158 case Window.Dialog:
155 159 dialog_count++;
@@ -29,6 +29,7
29 29 public decimal tree_clearing;
30 30 public decimal miscellaneous;
31 31 public decimal enforcement;
32 public decimal construction;
32 33
33 34
34 35 public decimal final_money;
@@ -39,6 +40,8
39 40 public int trees;
40 41 public int dead_trees;
41 42 public int crowded_trees;
43 public int preserve_cells;
44 //Kind of a hack but allows for tracking figures over time without creating a whole new infrastructure
42 45
43 46 }
44 47
@@ -54,16 +57,24
54 57 }
55 58 }
56 59
57
58 60 private const float SPONTANEOUS_NEW_TREE_CHANCE = 0.9995f;
59 61 private const float NEIGHBOR_NEW_TREE_CHANCE = 0.995f;
60 62 private const float NEIGHBOR_CROWDS_TREE_CHANCE = 0.995f;
61 63
64 private const float PRESERVE_SPONTANEOUS_NEW_TREE_CHANCE = 0.9990f;
65 private const float PRESERVE_NEIGHBOR_NEW_TREE_CHANCE = 0.995f;
66 private const float PRESERVE_NEIGHBOR_CROWDS_TREE_CHANCE = 0.9990f;
67
62 68 public const int TREE_PLANT_COST = 500;
63 69 public const int TREE_CLEAR_COST = 250;
64 70
65 public const int MAX_TREES_TO_PLANT = 25;
66 public const int MAX_TREES_TO_CLEAR = 25;
71 public const int MAX_TREES_TO_PLANT = 50;
72 public const int MAX_TREES_TO_CLEAR = 50;
73
74 public const decimal STARTING_FUNDS = 100_000M;
75
76 public const int NUM_WATER_FEATURES = 5;
77 public const int NUM_PONDS = 12;
67 78
68 79 public SimulationBridgeEngine BridgeEngine { get; private set; }
69 80
@@ -102,6 +113,8
102 113 public decimal enforcement;
103 114 public decimal misc;
104 115
116 public int preserve_cells;
117
105 118 public Budget latestBudget
106 119 {
107 120 get
@@ -123,7 +136,6
123 136 {
124 137 if (this.budgets.Count >= 2) {
125 138 return this.budgets[this.budgets.Count - 2];
126
127 139 }
128 140 else
129 141 {
@@ -134,10 +146,10
134 146
135 147 public System.Collections.Generic.IEnumerable<Budget> allBudgets()
136 148 {
137 foreach(var budget in this.budgets)
138 {
139 yield return budget;
140 }
149 foreach(var budget in this.budgets)
150 {
151 yield return budget;
152 }
141 153
142 154 }
143 155 private Grammar grammar;
@@ -169,6 +181,8
169 181
170 182 public CellMap map;
171 183
184 public int[,] PreserveCounts;
185
172 186 public int ticksPerAdvance;
173 187 private float lastAdvance;
174 188 public bool paused;
@@ -201,22 +215,21
201 215 public int crowded_trees
202 216 {
203 217 get {
204 return this.map.iterate_cells_with_neighbors(7).Where(c => c.hasTree).Count();
205
218 return this.map.iterate_cells_with_neighbors(7).Where(c => c.HasTree).Count();
206 219 }
207 220 }
208 221
209 222 public int dead_trees
210 223 {
211 224 get {
212 return this.map.iterate_cells().Where(c => (c.status == CellStatus.DeadTree)).Count();
225 return this.map.iterate_cells().Where(c => (c.Status == CellStatus.DeadTree)).Count();
213 226 }
214 227 }
215 228
216 229 public float healthy_percent
217 230 {
218 231 get {
219 return (float)(this.map.tree_count - this.map.iterate_cells_with_neighbors(7).Where(c => c.hasTree).Count()) / this.map.tree_count * 100;
232 return (float)(this.map.tree_count - this.map.iterate_cells_with_neighbors(7).Where(c => c.HasTree).Count()) / this.map.tree_count * 100;
220 233 }
221 234 }
222 235
@@ -224,7 +237,7
224 237 {
225 238 get
226 239 {
227 return this.map.iterate_cells().Where(c => c.hasTree).Select(c => (this.DateTime - c.planted).Days / 365.0).Average();
240 return this.map.iterate_cells().Where(c => c.HasTree).Select(c => (this.DateTime - c.Planted).Days / 365.0).Average();
228 241 }
229 242 }
230 243
@@ -232,13 +245,10
232 245 {
233 246 get
234 247 {
235 return this.map.iterate_cells().Where(c => c.hasTree).Select(c => (this.DateTime - c.planted).Days / 365.0).Max();
248 return this.map.iterate_cells().Where(c => c.HasTree).Select(c => (this.DateTime - c.Planted).Days / 365.0).Max();
236 249 }
237 250 }
238 251
239 //Historical counts
240 // public List<int> tree_count
241
242 252 public Simulation(int width, int height, float[] millisecondsPerAdvance)
243 253 {
244 254 this.random = new Random();
@@ -246,7 +256,7
246 256 this.DateTime = new DateTime(START_YEAR, START_MONTH, START_DAY);
247 257
248 258 this.map = new CellMap(width, height);
249 this.money = 100000M;
259 this.money = STARTING_FUNDS;
250 260 this.millisecondsPerAdvance = millisecondsPerAdvance;
251 261
252 262 this.paused = true;
@@ -254,6 +264,16
254 264 this.budgets = new List<Budget>();
255 265
256 266 this.BridgeEngine = new SimulationBridgeEngine(this);
267
268 this.PreserveCounts = new int[this.map.MapWidth, this.map.MapHeight];
269 }
270
271 private double interpolate(double percent, double start, double end) {
272 var low = Math.Min(start, end);
273 var high = Math.Max(start, end);
274 var range = high - low;
275
276 return range * percent + low;
257 277 }
258 278
259 279 private void advanceSimulation()
@@ -266,30 +286,42
266 286
267 287 this.BridgeEngine.addTick();
268 288
269 foreach (Cell cell in this.map.iterate_cells())
289 // foreach (Cell cell in this.map.iterate_cells())
290 for(int i = 0; i < this.map.MapWidth; i++)
270 291 {
271 if (random.NextDouble() > SPONTANEOUS_NEW_TREE_CHANCE)
292 for(int j = 0; j < this.map.MapHeight; j++)
272 293 {
273 cell.addTree(this.DateTime);
294 var cell = this.map.cells[i][j];
295 var rate = interpolate(8 - (double)this.PreserveCounts[i, j] / 8.0d, PRESERVE_SPONTANEOUS_NEW_TREE_CHANCE, SPONTANEOUS_NEW_TREE_CHANCE);
296 if (random.NextDouble() > rate)
297 {
298 var random_type = random.Next(0, 4);
299 cell.AddTree(this.DateTime, (TreeType)random_type);
300 }
274 301 }
275 302 }
276 303
277 304 int new_planted = 0;
278 foreach (Cell cell in this.map.iterate_cells_with_neighbors(4))
305 foreach (var (x, y) in this.map.iterate_cell_locations_with_neighbors(4))
279 306 {
280 if (random.NextDouble() > NEIGHBOR_NEW_TREE_CHANCE)
307 var neighbor = this.map.iterate_neighbors(x, y).First();
308
309 if (random.NextDouble() > (this.PreserveCounts[x, y] > 0 ? PRESERVE_NEIGHBOR_NEW_TREE_CHANCE : NEIGHBOR_NEW_TREE_CHANCE ))
281 310 {
282 cell.addTree(this.DateTime);
311 var cell = this.map.cells[x][y];
312 var random_type = random.Next(0, 4);
313 cell.AddTree(this.DateTime, neighbor.Type);
283 314 new_planted += 1;
284 315 }
285 316 }
286 317
287 318 int crowded_out = 0;
288 foreach (Cell cell in this.map.iterate_cells_with_neighbors(7))
319 foreach (var (x, y) in this.map.iterate_cell_locations_with_neighbors(7))
289 320 {
290 if (random.NextDouble() > NEIGHBOR_CROWDS_TREE_CHANCE)
321 if (random.NextDouble() > (this.PreserveCounts[x, y] > 0 ? PRESERVE_NEIGHBOR_CROWDS_TREE_CHANCE : NEIGHBOR_CROWDS_TREE_CHANCE ) )
291 322 {
292 cell.markTreeDead();
323 var cell = this.map.cells[x][y];
324 cell.MarkTreeDead();
293 325 crowded_out += 1;
294 326 }
295 327 }
@@ -301,18 +333,19
301 333 int x = random.Next(0, this.map.MapWidth);
302 334 Cell chosen_cell = this.map.cells[x][y];
303 335
304 if (!chosen_cell.hasTree) {
305 chosen_cell.addTree(this.DateTime);
336 if (!chosen_cell.HasTree) {
337 var random_type = random.Next(0, 4);
338 chosen_cell.AddTree(this.DateTime, (TreeType)random_type);
306 339 trees_to_plant -= 1;
307 340 }
308 341 }
309 342
310 343 int trees_to_clear = this.tree_clearing;
311 foreach (Cell cell in this.map.iterate_cells_with_neighbors(7).Where(c => c.hasTree))
344 foreach (Cell cell in this.map.iterate_cells_with_neighbors(7).Where(c => c.HasTree))
312 345 {
313 346 if (trees_to_clear > 0) {
314 cell.removeTree();
315 347 trees_to_clear -= 1;
348 cell.RemoveTree();
316 349 }
317 350 }
318 351
@@ -329,7 +362,8
329 362 upkeep = (int)(this.map.tree_count * 1.5),
330 363 tree_planting = this.tree_planting * Simulation.TREE_PLANT_COST,
331 364 tree_clearing = this.tree_clearing * Simulation.TREE_CLEAR_COST,
332 misc = this.misc
365 misc = this.misc,
366 preserve_cells = this.preserve_cells
333 367 };
334 368
335 369 newBudget = this.applyBudget(newBudget); ;
@@ -342,12 +376,10
342 376
343 377 public Budget applyBudget(Budget budget)
344 378 {
345
346 379 this.money = budget.money
347 380 - (budget.upkeep + budget.tree_planting + budget.tree_clearing + budget.enforcement)
348 381 + (budget.subsidy + budget.contracts + budget.misc);
349 382
350
351 383 budget.final_money = this.money;
352 384 budget.cashflow = budget.final_money - budget.money;
353 385
@@ -360,6 +392,19
360 392 }
361 393 }
362 394
395 public void AddConstruction(decimal construction_amount)
396 {
397 if (this.budgets.Count >= 1) {
398 var budget = this.budgets[this.budgets.Count - 1];
399
400 budget.final_money -= construction_amount;
401 budget.construction += construction_amount;
402 budget.cashflow -= construction_amount;
403 this.budgets[this.budgets.Count - 1] = budget;
404 }
405 this.money -= construction_amount;
406 }
407
363 408 public void updateNews() {
364 409 this.latestNewsItems = this.sourceNewsItems.Select(s => s.Flatten(this.grammar)).ToList().Shuffle();
365 410 }
@@ -371,6 +416,7
371 416 this.updateNews();
372 417 }
373 418
419
374 420 public void update(TimeSpan deltaTime)
375 421 {
376 422 if (!this.paused)
@@ -394,7 +440,6
394 440 //through t=120, so that's what we want to track in lastAdvance.
395 441 this.lastAdvance += advancesToSimulate * millisecondsPerAdvance;
396 442 }
397
398 443 }
399 444 }
400 445 }
@@ -1,4 +1,5
1 1 using System;
2 using System.Diagnostics;
2 3 using System.Collections.Generic;
3 4 using System.Linq;
4 5
@@ -46,7 +47,7
46 47
47 48 static public Texture2D TileSetTexture;
48 49
49
50 public const float DEPTH = 0.79f;
50 51
51 52
52 53 public Tile()
@@ -55,7 +56,6
55 56 }
56 57
57 58
58
59 59 static public Rectangle GetSourceRectangle(int tileIndex)
60 60 {
61 61 int tileY = tileIndex / (TileSetTexture.Width / TileWidth);
@@ -91,26 +91,26
91 91 new Vector2(((x - y) * Tile.TileSpriteWidth / 2), (x + y) * Tile.TileSpriteHeight / 2) + adjust2,
92 92 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
93 93 new Vector2(((x - y + size) * Tile.TileSpriteWidth / 2), (x + y + size) * Tile.TileSpriteHeight / 2) + adjust2,
94 color, 0.79f);
94 color, 0.77f);
95 95
96 96 //Bottom right
97 97 Line.drawLine(batch,
98 98 new Vector2(((x + size - y) * Tile.TileSpriteWidth / 2), (x + size + y) * Tile.TileSpriteHeight / 2) + adjust2,
99 99 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
100 100 new Vector2(((x + size - (y + size)) * Tile.TileSpriteWidth / 2), (x + size + (y + size)) * Tile.TileSpriteHeight / 2) + adjust2,
101 color, 0.79f);
101 color, 0.77f);
102 102 //Bottom left
103 103 Line.drawLine(batch,
104 104 new Vector2(((x - (y + size)) * Tile.TileSpriteWidth / 2), (x + y + size) * Tile.TileSpriteHeight / 2) + adjust2,
105 105 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
106 106 new Vector2(((x + size - (y + size)) * Tile.TileSpriteWidth / 2), (x + size + (y + size)) * Tile.TileSpriteHeight / 2) + adjust2,
107 color, 0.79f);
107 color, 0.77f);
108 108 //Upper left
109 109 Line.drawLine(batch,
110 110 new Vector2(((x - y) * Tile.TileSpriteWidth / 2), (x + y) * Tile.TileSpriteHeight / 2) + adjust2,
111 111 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
112 112 new Vector2(((x - (y + size)) * Tile.TileSpriteWidth / 2), (x + (y + size)) * Tile.TileSpriteHeight / 2) + adjust2,
113 color, 0.79f);
113 color, 0.77f);
114 114 }
115 115
116 116
@@ -128,26 +128,26
128 128 new Vector2(((x - y) * Tile.TileSpriteWidth / 2), (x + y) * Tile.TileSpriteHeight / 2) + adjust2,
129 129 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
130 130 new Vector2(((x - y + size_less_one) * Tile.TileSpriteWidth / 2), (x + y + size_less_one) * Tile.TileSpriteHeight / 2) + adjust2,
131 color, 0.79f);
131 color, Tile.DEPTH);
132 132
133 133 //Bottom right
134 134 Line.drawLine(batch,
135 135 new Vector2(((x + size - y) * Tile.TileSpriteWidth / 2), (x + size_less_one + y) * Tile.TileSpriteHeight / 2) + adjust2,
136 136 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
137 137 new Vector2(((x + size - (y + size)) * Tile.TileSpriteWidth / 2), (x + size_less_one + (y + size_less_one)) * Tile.TileSpriteHeight / 2) + adjust2,
138 color, 0.79f);
138 color, Tile.DEPTH);
139 139 //Bottom left
140 140 Line.drawLine(batch,
141 141 new Vector2(((x - (y + size)) * Tile.TileSpriteWidth / 2), (x + y + size) * Tile.TileSpriteHeight / 2) + adjust2,
142 142 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
143 143 new Vector2(((x + size - (y + size)) * Tile.TileSpriteWidth / 2), (x + size + (y + size)) * Tile.TileSpriteHeight / 2) + adjust2,
144 color, 0.79f);
144 color, Tile.DEPTH);
145 145 //Upper left
146 146 Line.drawLine(batch,
147 147 new Vector2(((x - y) * Tile.TileSpriteWidth / 2), (x + y) * Tile.TileSpriteHeight / 2) + adjust2,
148 148 //new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
149 149 new Vector2(((x - (y + size)) * Tile.TileSpriteWidth / 2), (x + (y + size)) * Tile.TileSpriteHeight / 2) + adjust2,
150 color, 0.79f);
150 color, Tile.DEPTH);
151 151 }
152 152
153 153 public static void drawOutline(SpriteBatch batch, Color color) {
@@ -193,14 +193,20
193 193 edges.Add(new Edge {Start=square, End=square + new Vector2(0, 1)});
194 194 }
195 195
196 //Seems to be v. slow
196 197 edges = edges.GroupBy(x => x).Where(grp => grp.Count() == 1).Select(grp => grp.Key).ToList<Edge>();
197 198
198 199 drawEdges(batch, edges.ToArray(), color);
199 200 }
200 201
202 public static void drawTileAt(SpriteBatch batch, int x, int y, int tileIndex, int height, float depth) {
203 drawTileAt(batch, x, y, tileIndex, height, depth, Color.White);
204 }
201 205
202 public static void drawTileAt(SpriteBatch batch, int x, int y, int tileIndex, int height, float depth)
203 {
206
207 public static void drawTileAt(SpriteBatch batch, int x, int y, int tileIndex, int height, float depth, Color color)
208 {
209 //new Color(100, 100, 100, 100)
204 210
205 211 int height_adjust = 0;
206 212
@@ -224,7 +230,7
224 230 screeny,
225 231 Tile.TileWidth, Tile.TileHeight * height),
226 232 Tile.GetExtendedSourceRectangle(tileIndex, height),
227 Color.White,
233 color,
228 234 0.0f,
229 235 Vector2.Zero,
230 236 SpriteEffects.None,
@@ -36,10 +36,10
36 36 this.budget = budget;
37 37 this.previous_budget = previous_budget;
38 38
39 if ((mouseCur.LeftButton == ButtonState.Pressed)
40 && MathUtils.BetweenExclusive(mouseCur.X, width+x-20, width+x)
41 && MathUtils.BetweenExclusive(mouseCur.Y, y+bar_height, y+bar_height+20)
42 ) {
39 if ((mouseCur.LeftButton == ButtonState.Released)
40 && (mousePrev.LeftButton == ButtonState.Pressed)
41 && MathUtils.BetweenExclusive(mouseCur.X, width+x-20, width+x)
42 && MathUtils.BetweenExclusive(mouseCur.Y, y+bar_height, y+bar_height+20)) {
43 43
44 44 return false;
45 45
@@ -68,6 +68,17
68 68 return true;
69 69 }
70 70
71 public String line_format(String name, decimal first, decimal second) {
72 var between_name_col = 20 - name.Length;
73 int between_cols = 6;
74 var first_formatted = String.Format("${0:}", first).PadLeft(6, '.');
75 var second_formatted = String.Format("${0:}", second).PadLeft(6, '.');
76
77 var formatted = String.Format("{0:}{1:}{2,6:}{3:}{4,6:}", name, new String('.', between_name_col), first_formatted, new String('.', between_cols), second_formatted);
78
79 return formatted;
80 }
81
71 82 public void draw(SpriteBatch batch)
72 83 {
73 84
@@ -93,24 +104,25
93 104 }
94 105 }
95 106
107 Vector2 dimensions = font.MeasureString("X");
108 batch.DrawString(font, "X", new Vector2(x+width -20 + (dimensions.X/2), y+bar_height), Color.Black);
96 109 FilledRectangle.drawFilledRectangle(batch, new Rectangle(x + width - 20, y+bar_height, 20, 20), Color.LightGray);
97 Vector2 dimensions = font.MeasureString("X");
98 batch.DrawString(font, "X", new Vector2(x+width -20 + (dimensions.X/2), y+bar_height), Color.Black);
99 110
100 111 batch.DrawString(font, String.Format("BUDGET REPORT FOR {0:MMMMM yyyy}", this.budget.DateTime), new Vector2(x, bar_height * 1 + y), Color.Black);
101 112
102 113 batch.DrawString(font, String.Format("Starting Funds.........${0:}", this.budget.money), new Vector2(x, bar_height * 2 + y), Color.Black);
103 114
104 115 batch.DrawString(font, String.Format("REVENUE", this.budget.upkeep), new Vector2(x, bar_height * 4 + y), Color.Black);
105 batch.DrawString(font, String.Format("Subsidy................${0:}....${1:}", this.budget.subsidy, this.previous_budget.subsidy), new Vector2(x, bar_height * 5 + y), Color.Black);
106 batch.DrawString(font, String.Format("Contracts..............${0:}....${1:}", this.budget.contracts, this.previous_budget.contracts), new Vector2(x, bar_height * 6 + y), Color.Black);
107 batch.DrawString(font, String.Format("Misc...................${0:}....${1:}", this.budget.misc, this.previous_budget.misc), new Vector2(x, bar_height * 7 + y), Color.Black);
116 batch.DrawString(font, line_format("Subsidy", this.budget.subsidy, this.previous_budget.subsidy), new Vector2(x, bar_height * 5 + y), Color.Black);
117 batch.DrawString(font, line_format("Contracts", this.budget.contracts, this.previous_budget.contracts), new Vector2(x, bar_height * 6 + y), Color.Black);
118 batch.DrawString(font, line_format("Misc", this.budget.misc, this.previous_budget.misc), new Vector2(x, bar_height * 7 + y), Color.Black);
108 119
109 batch.DrawString(font, String.Format("EXPENSES", this.budget.upkeep), new Vector2(x, bar_height * 10 + y), Color.Black);
110 batch.DrawString(font, String.Format("Upkeep.................${0:}....${1:}", this.budget.upkeep, this.previous_budget.upkeep), new Vector2(x, bar_height * 11 + y), Color.Black);
111 batch.DrawString(font, String.Format("Tree Planting.1........${0:}....${1:}", this.budget.tree_planting, this.previous_budget.tree_planting), new Vector2(x, bar_height * 12 + y), Color.Black);
112 batch.DrawString(font, String.Format("Tree Clearing..........${0:}....${1:}", this.budget.tree_clearing, this.previous_budget.tree_clearing), new Vector2(x, bar_height * 13 + y), Color.Black);
113 batch.DrawString(font, String.Format("Enforcement............${0:}....${1:}", this.budget.enforcement, this.previous_budget.enforcement), new Vector2(x, bar_height * 14 + y), Color.Black);
120 batch.DrawString(font, "EXPENSES", new Vector2(x, bar_height * 10 + y), Color.Black);
121 batch.DrawString(font, line_format("Upkeep", this.budget.upkeep, this.previous_budget.upkeep), new Vector2(x, bar_height * 11 + y), Color.Black);
122 batch.DrawString(font, line_format("Tree Planting", this.budget.tree_planting, this.previous_budget.tree_planting), new Vector2(x, bar_height * 12 + y), Color.Black);
123 batch.DrawString(font, line_format("Tree Clearing", this.budget.tree_clearing, this.previous_budget.tree_clearing), new Vector2(x, bar_height * 13 + y), Color.Black);
124 batch.DrawString(font, line_format("Enforcement", this.budget.enforcement, this.previous_budget.enforcement), new Vector2(x, bar_height * 14 + y), Color.Black);
125 batch.DrawString(font, line_format("Construction", this.budget.construction, this.previous_budget.construction), new Vector2(x, bar_height * 15 + y), Color.Black);
114 126
115 127 Color cashflow_color = Color.Black;
116 128 if (this.budget.cashflow < 0) {
@@ -121,8 +133,8
121 133 final_color = Color.Red;
122 134 }
123 135
124 batch.DrawString(font, String.Format("Cashflow.............${0:}....${1:}", this.budget.cashflow, this.previous_budget.cashflow), new Vector2(x, bar_height * 16 + y), cashflow_color);
125 batch.DrawString(font, String.Format("Ending Funds.........${0:}....${1:}", this.budget.final_money, this.previous_budget.final_money), new Vector2(x, bar_height * 17 + y), final_color);
136 batch.DrawString(font, line_format("Cashflow", this.budget.cashflow, this.previous_budget.cashflow), new Vector2(x, bar_height * 17 + y), cashflow_color);
137 batch.DrawString(font, line_format("Ending Funds", this.budget.final_money, this.previous_budget.final_money), new Vector2(x, bar_height * 18 + y), final_color);
126 138
127 139
128 140 FilledRectangle.drawFilledRectangle(batch, new Rectangle(50, 50, 50, 50), new Color (0, 0,0, 0), 0.99f);
@@ -1,7 +1,6
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using ImGuiNET;
4 using ImPlotNET;
5 4 using ImGuiNET.SampleProgram.XNA;
6 5
7 6 using Num = System.Numerics;
@@ -9,6 +8,9
9 8 using Microsoft.Xna.Framework.Graphics;
10 9 using System.Runtime.InteropServices;
11 10
11 using isometricparkfna.Engines;
12 using isometricparkfna.Messages;
13
12 14 namespace isometricparkfna.UI
13 15 {
14 16
@@ -20,12 +22,18
20 22 public TimeSpan treeDrawTime;
21 23 public TimeSpan gridDrawTime;
22 24 public TimeSpan tileDrawTime;
25 public TimeSpan rendererDrawTime;
26 public TimeSpan miscUIDrawTime;
27 public TimeSpan debugDrawTime;
23 28 public Vector2 cameraPosition;
24 29 public int treeCount;
25 30 public Vector2 mouseGrid;
26 31 public Boolean hasTree;
27 32 public int tilesDrawn;
28 33 public TimeSpan updateTime;
34 public TimeSpan worldUpdateTime;
35 public TimeSpan simulationUpdateTime;
36
29 37 }
30 38
31 39 public class DebugWindow
@@ -34,13 +42,22
34 42 private Texture2D _xnaTexture;
35 43 private IntPtr _imGuiTexture;
36 44 private bool show_test_window;
37 private bool show_implot_test_window;
38 45
39 46 public ImFontPtr monoFont;
40 47 public ImFontPtr italicFont;
41 48
42 49 public ImageMap map;
43 50
51 private ImGuiWindowBridgeEngine _engine;
52 public ImGuiWindowBridgeEngine engine {
53 get {
54 return this._engine;
55 }
56 set {
57 this._engine = value;
58 }
59 }
60
44 61 private ImGuiRenderer renderer;
45 62
46 63 public static Dictionary<string, string> fonts = new Dictionary<String, string> {{"Roboto", @"Content/Roboto-Regular.ttf"},
@@ -92,6 +109,7
92 109
93 110
94 111 this.map = map;
112 this.engine = engine;
95 113 _xnaTexture = map.ImageMapTexture;
96 114 // _xnaTexture = CreateTexture(graphicsDevice, 300, 150, pixel =>
97 115 // {
@@ -103,6 +121,8
103 121 _imGuiTexture = _imGuiRenderer.BindTexture(_xnaTexture);
104 122 }
105 123
124
125
106 126 public void swap()
107 127 {
108 128 ImGuiIOPtr io = ImGui.GetIO();
@@ -187,7 +207,6
187 207 float f = 0.0f;
188 208
189 209 bool show_test_window = false;
190 bool show_implot_test_window = false;
191 210 bool show_another_window = false;
192 211 Num.Vector3 clear_color = new Num.Vector3(114f / 255f, 144f / 255f, 154f / 255f);
193 212 byte[] _textBuffer = new byte[100];
@@ -201,7 +220,6
201 220 ImGui.SliderFloat("float", ref f, 0.0f, 1.0f, string.Empty);
202 221 ImGui.ColorEdit3("clear color", ref clear_color);
203 222 if (ImGui.Button("Test Window")) show_test_window = !show_test_window;
204 if (ImGui.Button("Implot Test Window")) show_implot_test_window = !show_implot_test_window;
205 223 if (ImGui.Button("Another Window")) show_another_window = !show_another_window;
206 224 ImGui.Text(string.Format("Application average {0:F3} ms/frame ({1:F1} FPS)", 1000f / ImGui.GetIO().Framerate, ImGui.GetIO().Framerate));
207 225
@@ -227,11 +245,17
227 245
228 246 ImGui.Text(string.Format("fps: {0:F3}", debugInfo.fps));
229 247 ImGui.Text(string.Format("Draw Time: {0:F3}", debugInfo.drawTime.TotalMilliseconds.ToString()));
230 ImGui.Text(string.Format("\tTree: {0:F3}; Grid: {1:F3}; Tile: {2:F3}",
231 debugInfo.treeDrawTime.TotalMilliseconds.ToString(),
232 debugInfo.gridDrawTime.TotalMilliseconds.ToString(),
233 debugInfo.tileDrawTime.TotalMilliseconds.ToString()));
248 ImGui.Text(string.Format("\tTree: {0,7:F3}; Grid: {1,7:F3}; Tile: {2,7:F3}\n\tRenderer: {3,7:F3}; Misc UI: {4,7:F3}; Debug: {5,7:F3}",
249 debugInfo.treeDrawTime.TotalMilliseconds.ToString(),
250 debugInfo.gridDrawTime.TotalMilliseconds.ToString(),
251 debugInfo.tileDrawTime.TotalMilliseconds.ToString(),
252 debugInfo.rendererDrawTime.TotalMilliseconds.ToString(),
253 debugInfo.miscUIDrawTime.TotalMilliseconds.ToString(),
254 debugInfo.debugDrawTime.TotalMilliseconds.ToString()));
234 255 ImGui.Text(string.Format("Update Time: {0:F3}", debugInfo.updateTime.TotalMilliseconds.ToString()));
256 ImGui.Text(string.Format("\tWorld: {0:F3}; Simulation: {1:F3}",
257 debugInfo.worldUpdateTime.TotalMilliseconds.ToString(),
258 debugInfo.simulationUpdateTime.TotalMilliseconds.ToString()));
235 259 ImGui.Text(string.Format("Tiles Drawn: {0:F}", debugInfo.tilesDrawn));
236 260
237 261
@@ -245,9 +269,6
245 269 this.show_test_window = !this.show_test_window;
246 270 }
247 271
248 if (ImGui.Button("Implot Test Window")){
249 show_implot_test_window = !show_implot_test_window;
250 }
251 272 if (ImGui.Button("Test Logging"))
252 273 {
253 274 Logging.Log(LogLevel.Critical, "Test");
@@ -310,6 +331,21
310 331
311 332 ImGui.EndTabItem();
312 333 }
334
335 if(ImGui.BeginTabItem("Debug Controls"))
336 {
337 if (ImGui.Button("Cull 100 Trees"))
338 {
339 this.engine.debugAlterTreesMessages.Add(new DebugAlterTreesMessage {
340 DeltaTrees = 100});
341 }
342 if (ImGui.Button("Cull 1000 Trees"))
343 {
344 this.engine.debugAlterTreesMessages.Add(new DebugAlterTreesMessage {
345 DeltaTrees = 1000});
346 }
347 ImGui.EndTabItem();
348 }
313 349 ImGui.EndTabBar();
314 350 ImGui.End();
315 351 }
@@ -319,10 +355,6
319 355 ImGui.SetNextWindowPos(new Num.Vector2(650, 20), ImGuiCond.FirstUseEver);
320 356 ImGui.ShowDemoWindow(ref show_test_window);
321 357 }
322 if (this.show_implot_test_window)
323 {
324 ImPlot.ShowDemoWindow(ref this.show_implot_test_window);
325 }
326 358 }
327 359 }
328 360 }
@@ -6,7 +6,6
6 6 using System.Collections.Generic;
7 7
8 8 using ImGuiNET;
9 using ImPlotNET;
10 9
11 10 using JM.LinqFaster;
12 11
@@ -26,147 +25,371
26 25 public static bool show_subsidies = false;
27 26 public static bool show_upkeep = false;
28 27
29 private static string[] money_series = { "Total Funds",
30 "Subsidies", "Upkeep", "Contracts", "Cashflow", "Misc"};
31 private static string[] tree_series = { "Total trees", "Dead trees", "Crowded trees"};
28 public static bool always_show_zero = false;
29 public static bool logarithmic = false;
30
31 private static string[] money_series = {"Total Funds",
32 "Subsidies", "Upkeep", "Contracts", "Cashflow", "Misc"};
33 private static string[] tree_series = {"Total trees", "Dead trees", "Crowded trees"};
32 34
33 35 public static Dictionary<string, IEnumerable<double>> data_sets = new Dictionary<string, IEnumerable<double>>();
34 36
35 public static Dictionary<String, bool> data_sets_show = new List<string>()
36 .Concat(money_series)
37 .Concat(tree_series)
38 .Select(e => (e, false))
39 .ToDictionary(t => t.Item1, t=> t.Item2);
37 public static Dictionary<string, bool> data_sets_show = new List<string>()
38 .Concat(money_series)
39 .Concat(tree_series)
40 .Select(e => (e, false))
41 .ToDictionary(t => t.Item1, t=> t.Item2);
42
43 public static ImGuiColor[] colors = {ImGuiColor.BLACK, ImGuiColor.RED, ImGuiColor.GREEN,
44 ImGuiColor.BLUE, ImGuiColor.DARKGREY, ImGuiColor.LIGHTRED, ImGuiColor.LIGHTGREEN,
45 ImGuiColor.LIGHTBLUE, ImGuiColor.BLACK };
46
47 public static Dictionary<string, ImGuiColor> data_sets_color = new List<string>()
48 .Concat(money_series)
49 .Concat(tree_series)
50 .Zip(colors, (first, second) => (first, second))
51 .ToDictionary(t => t.Item1, t => t.Item2);
52
53 public static void DrawLinearAxis(ImDrawListPtr draw_list, Num.Vector2 range, bool vertical, int points, Num.Vector2 starting_position) {
54 //See DrawLinearLabels for explanation
55 var tick_spacing = (int)Math.Abs((range.Y - range.X) / (points - 1));
56 var tick_length = 5;
57 var tick_adjust = vertical ? new Num.Vector2(tick_length, 0) : new Num.Vector2(0, tick_length);
58
59 var tick_position = starting_position;
60
61 for(int i = 0; i < points; i++) {
62 draw_list.AddLine(tick_position, Num.Vector2.Add(tick_position, tick_adjust), (uint)ImGuiColor.DARKGREY, 1.0f);
63
64 if (vertical) {
65 tick_position = new Num.Vector2(starting_position.X, starting_position.Y + ((i + 1) * tick_spacing));
66 }
67 else {
68 //We increment one, otherwise the first tick is
69 tick_position = new Num.Vector2(starting_position.X + ((i + 1) * tick_spacing), starting_position.Y);
70 }
71 }
72 }
73
74 public static void DrawLinearLabels(ImFontPtr font, ImDrawListPtr draw_list, Num.Vector2 domain, Num.Vector2 range, bool vertical, int labels, Num.Vector2 starting_position) {
75 //We need to increment by one in order to cover the entire range.
76 //For example, if our range is 0 - 100, and we want 11 ticks, 100 / 10 gives us a spacing o 10
77 //So our 11 labels become 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100.
78 var tick_spacing = (int)Math.Abs((range.Y - range.X) / (labels - 1));
79 var tick_length = 5;
80 var tick_adjust = vertical ? new Num.Vector2(tick_length, 0) : new Num.Vector2(0, tick_length);
81
82 var tick_position = new Num.Vector2(0, range.Y);
83 var tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
84
85 for(int i = 0; i < labels; i++) {
86 var value = Scale(range, domain, (int)(vertical ? tick_position.Y : tick_position.X));
87 var label = String.Format("{0}", value);
88 var height_adjust = ImGui.CalcTextSize(label).Y / 2;
89 var adjusted_position = Num.Vector2.Add(tick_absolute_position,
90 new Num.Vector2(0, -height_adjust));
91
92 draw_list.AddText(font, 11.0f, adjusted_position, (uint)ImGuiColor.BLACK, label);
93 //Logging.Info(String.Format("Drawing {0:} at {1} ({2})", label, tick_absolute_position, tick_position));
94
95 if (vertical) {
96 tick_position = new Num.Vector2(0, range.Y + ((i + 1) * tick_spacing));
97 }
98 else {
99 tick_position = new Num.Vector2(range.X + ((i + 1) * tick_spacing), 0);
100 }
101
102 tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
103 }
104 }
105
106 public static void DrawLogrithmicLabels(ImFontPtr font, ImDrawListPtr draw_list, Num.Vector2 domain, Num.Vector2 range, bool vertical, int labels, Num.Vector2 starting_position) {
107 //We need to increment by one in order to cover the entire range.
108 //For example, if our range is 0 - 100, and we want 11 ticks, 100 / 10 gives us a spacing o 10
109 //So our 11 labels become 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100.
110 var tick_spacing = (int)Math.Abs((range.Y - range.X) / (labels - 1));
111 var tick_length = 5;
112 var tick_adjust = vertical ? new Num.Vector2(tick_length, 0) : new Num.Vector2(0, tick_length);
113
114 var tick_position = new Num.Vector2(0, range.Y);
115 var tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
116
117 for(int i = 0; i < labels; i++) {
118 var value = ScaleLogarithmic(range, domain, (int)(vertical ? tick_position.Y : tick_position.X));
119 var label = String.Format("{0}", value);
120 var height_adjust = ImGui.CalcTextSize(label).Y / 2;
121 var adjusted_position = Num.Vector2.Add(tick_absolute_position,
122 new Num.Vector2(0, -height_adjust));
123
124 draw_list.AddText(font, 11.0f, adjusted_position, (uint)ImGuiColor.BLACK, label);
125 //Logging.Info(String.Format("Drawing {0:} at {1} ({2})", label, tick_absolute_position, tick_position));
40 126
127 if (vertical) {
128 tick_position = new Num.Vector2(0, range.Y + ((i + 1) * tick_spacing));
129 }
130 else {
131 tick_position = new Num.Vector2(range.X + ((i + 1) * tick_spacing), 0);
132 }
133
134 tick_absolute_position = Num.Vector2.Add(starting_position, tick_position);
135 }
136 }
137
138 public static void DrawLine(ImDrawListPtr draw_list, Num.Vector2 c, Num.Vector2[] points, ImGuiColor col) {
139 var p = Num.Vector2.Zero;
140
141 for (int i = 0; i < points.Length; i++)
142 {
143 points[i] = Num.Vector2.Add(points[i], c);
144 }
145
146 draw_list.AddPolyline(ref points[0], points.Length, (uint)col, 0, 1.0f);
147 }
148
149 public static int Scale(Num.Vector2 domain, Num.Vector2 range, int num) {
150 //https://stats.stackexchange.com/a/281164
151
152 var domain_span = Math.Sign(domain.Y - domain.X) * Math.Max(1, Math.Abs(domain.Y - domain.X));
153 var range_span = range.Y - range.X;
154
155 var start = range.X - domain.X;
156
157 return (int) (((num - domain.X) / domain_span) * range_span + range.X);
158 }
159
160 public static float Scale(Num.Vector2 domain, Num.Vector2 range, float num) {
161 //https://stats.stackexchange.com/a/281164
162
163 if (!float.IsNaN(domain.Y - domain.X)) {
164 var domain_span = Math.Sign(domain.Y - domain.X) * Math.Max(1, Math.Abs(domain.Y - domain.X));
165 var range_span = range.Y - range.X;
166
167 var start = range.X - domain.X;
168
169 return (((num - domain.X) / domain_span) * range_span + range.X);
170 }
171 else {
172 return float.NaN;
173 }
174 }
175
176 public static float ScaleLogarithmic(Num.Vector2 domain, Num.Vector2 range, float num) {
177 var scaled_domain = new Num.Vector2((float)MathUtils.SymmetricLog10(domain.X), (float)MathUtils.SymmetricLog10(domain.Y));
178 float scaled_num = num == 0 ? 0.0f : (float)MathUtils.SymmetricLog10(num);
179
180 return Scale(scaled_domain, range, scaled_num);
181 }
182
183 public static Num.Vector2 adjust_domain(int domain_min, int domain_max)
184 {
185 if (domain_max == int.MinValue) {
186 return adjust_domain(0, 0);
187 }
188 else if (domain_min != domain_max) {
189 //Significant-digits based rounding (kinda):
190 // var orders_to_round = 4;
191 // var orders = (int)Math.Log10(domain_max);
192 // var domain_max_rounded = Math.Round(domain_max / Math.Pow(10, orders - orders_to_round)) * Math.Pow(10, orders - orders_to_round);
193 //Round so breaks are even (in theory):
194 var domain_max_rounded = Math.Ceiling(domain_max / 50.0) * 50;
195 var domain_min_rounded = Math.Floor(domain_min / 50.0) * 50;
196
197 // Logging.Info("Standard rounding.");
198
199 //Throw out rounding if result is too close together:
200 if (domain_min_rounded != domain_max_rounded) {
201 return new Num.Vector2((float)domain_min_rounded, (float)domain_max_rounded);
202 }
203 else {
204 return new Num.Vector2(domain_min, domain_max);
205 }
206
207
208 }
209 else {
210 var lower = MathUtils.Clamp(domain_min, 0, 100);
211 var upper = MathUtils.Clamp(domain_min, 10, 100);
212
213 // Logging.Info("Clamped rounding.");
214
215 return new Num.Vector2(domain_min-lower, domain_max+upper);
216 }
217 }
41 218
42 219 public static void Render(ImFontPtr font, Simulation sim, ImGuiWindowBridgeEngine engine)
43 220 {
44 221 bool newShow = true;
45 222
223 ImGui.PushFont(font);
46 224
47 ImGui.PushFont(font);
225 ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.None;
226 StyleSets.defaultSet.push();
48 227
49 ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.None;
50 StyleSets.defaultSet.push();
228 if(GraphWindow.hadFocus)
229 {
230 ImGui.PushStyleColor(ImGuiCol.Text, StyleSets.white);
231 }
232 ImGui.SetNextWindowSize(new Num.Vector2(400, 400));
51 233
52 if(GraphWindow.hadFocus)
53 {
54 ImGui.PushStyleColor(ImGuiCol.Text, StyleSets.white);
55 }
56 ImGui.SetNextWindowSize(new Num.Vector2(400, 400));
234 ImGui.Begin("Graph", ref newShow, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings);
235 if (GraphWindow.hadFocus)
236 {
237 ImGui.PopStyleColor();
238 }
239 GraphWindow.hadFocus = ImGui.IsWindowFocused();
240
241 data_sets["Total Funds"] = sim.allBudgets().Select(b => (double)b.money);
242 data_sets["Subsidies"] = sim.allBudgets().Select(b => (double)b.subsidy);
243 data_sets["Upkeep"] = sim.allBudgets().Select(b => (double)b.upkeep);
244 data_sets["Contracts"] = sim.allBudgets().Select(b => (double)b.contracts);
245 data_sets["Misc"] = sim.allBudgets().Select(b => (double)b.misc);
246 data_sets["Cashflow"] = sim.allBudgets().Select(b => (double)b.cashflow);
247
248 data_sets["Total trees"] = sim.allBudgets().Select(b => (double)b.trees);
249 data_sets["Dead trees"] = sim.allBudgets().Select(b => (double)b.dead_trees);
250 data_sets["Crowded trees"] = sim.allBudgets().Select(b => (double)b.crowded_trees);
251
252 var periods = 12.0d * GraphWindow.year;
253 var keys = data_sets_show.Keys.ToList();
57 254
58 ImGui.Begin("Graph", ref newShow, ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoSavedSettings);
59 if (GraphWindow.hadFocus)
60 {
61 ImGui.PopStyleColor();
255 var totals = data_sets["Total Funds"];
256
257 var max = 0.0d;
258 var min = 0.0d;
259
260 foreach (var key in keys) {
261 if (data_sets_show[key] && totals.Count() > 0) {
262 var series_max = data_sets[key].Max() * 1.10f;
263 max = Math.Max(series_max, max);
62 264 }
63 GraphWindow.hadFocus = ImGui.IsWindowFocused();
265 }
64 266
65 data_sets["Total Funds"] = sim.allBudgets().Select(b => (double)b.money);
66 data_sets["Subsidies"] = sim.allBudgets().Select(b => (double)b.subsidy);
67 data_sets["Upkeep"] = sim.allBudgets().Select(b => (double)b.upkeep);
68 data_sets["Contracts"] = sim.allBudgets().Select(b => (double)b.contracts);
69 data_sets["Misc"] = sim.allBudgets().Select(b => (double)b.misc);
70 data_sets["Cashflow"] = sim.allBudgets().Select(b => (double)b.cashflow);
267 foreach (var key in keys) {
268 if (data_sets_show[key] && totals.Count() > 0) {
269 var series_min = data_sets[key].Min();
270 series_min = series_min >= 0? series_min * 0.90f : series_min *1.10f;
271 min = Math.Min(series_min, min);
272 }
273 }
274
275 var draw_list = ImGui.GetWindowDrawList();
276 var padding = 30;
277
278 var domain_min = always_show_zero ? 0 : int.MaxValue;
279 var domain_max = int.MinValue;
280 var c = ImGui.GetCursorScreenPos();
281
282 //Y Axis
283 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, padding), c),
284 Num.Vector2.Add(new Num.Vector2(padding, 200 - padding), c),
285 (uint)ImGuiColor.LIGHTGREY, 0.0f);
71 286
72 data_sets["Total trees"] = sim.allBudgets().Select(b => (double)b.trees);
73 data_sets["Dead trees"] = sim.allBudgets().Select(b => (double)b.dead_trees);
74 data_sets["Crowded trees"] = sim.allBudgets().Select(b => (double)b.crowded_trees);
287 //X Axis
288 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, 200 - padding), c),
289 Num.Vector2.Add(new Num.Vector2(350, 200 - padding), c),
290 (uint)ImGuiColor.LIGHTGREY, 1.0f);
291
292
293 foreach (var key in keys)
294 {
295 if (data_sets_show[key] && data_sets[key].Count() > 0)
296 {
297 domain_min = Math.Min(domain_min, (int)data_sets[key].Min());
298 domain_max = Math.Max(domain_max, (int)data_sets[key].Max());
299 }
300 }
75 301
76 var periods = 12.0d * GraphWindow.year;
77 var keys = data_sets_show.Keys.ToList();
302 var domain = adjust_domain(domain_min, domain_max);
303 var range = new Num.Vector2(200 - padding, 0 + padding);
304
305 //Zero
306 var zero_point = logarithmic ? ScaleLogarithmic(domain, range, 0) : Scale(domain, range, 0);
307 // Logging.Spy(new {zero_point = zero_point});
308 draw_list.AddLine(Num.Vector2.Add(new Num.Vector2(padding, zero_point), c),
309 Num.Vector2.Add(new Num.Vector2(350, zero_point), c),
310 (uint)ImGuiColor.LIGHTGREY, 1.0f);
78 311
79 var totals = data_sets["Total Funds"];
312 var x_domain = new Num.Vector2((data_sets["Misc"].Count() - (int)periods),
313 data_sets["Misc"].Count());
314 var x_range = new Num.Vector2(0 + padding, 350 - padding);
80 315
81 var max = 0.0d;
82 var min = 0.0d;
316 foreach (var key in keys)
317 {
318 var show = data_sets_show[key];
319 var data = data_sets[key];
320 var color = data_sets_color[key];
83 321
84 foreach( var key in keys) {
85 if (data_sets_show[key] && totals.Count() > 0) {
86 var series_max = data_sets[key].Max() * 1.10f;
87 max = Math.Max(series_max, max);
88 }
322 if (data.Count() > 0 && show)
323 {
324 IEnumerable<float> data_array = data_sets[key].Select((p) => (logarithmic ? ScaleLogarithmic(domain, range, (float)p): Scale(domain, range, (float)p)));
325 var data_array2 = data_array.Select((p, i) => new Num.Vector2(Scale(x_domain, x_range, i), p)).ToArray();
326
327 DrawLine(draw_list, c, data_array2, color);
328 draw_list.AddText(font, 12, data_array2.Last(), (uint)color, key);
89 329 }
330 }
90 331
91 foreach( var key in keys) {
92 if (data_sets_show[key] && totals.Count() > 0) {
93 var series_min = data_sets[key].Min();
94 series_min = series_min >= 0? series_min * 0.90f : series_min *1.10f;
95 min = Math.Min(series_min, min);
96 }
332 DrawLinearAxis(draw_list, range /*new Num.Vector2(0, 200)*/, true, 11, Num.Vector2.Add(c, new Num.Vector2(padding, padding)));
333 if (logarithmic) {
334 DrawLogrithmicLabels(font, draw_list, domain, range, true, 11, c);
335 }
336 else {
337 DrawLinearLabels(font, draw_list, domain, range, true, 11, c);
338 }
339 DrawLinearAxis(draw_list, new Num.Vector2(0, 350), false, 12, Num.Vector2.Add(c, new Num.Vector2(padding, 200 - padding)));
340
341 ImGui.Dummy(new Num.Vector2(350, 200));
342
343 ImGui.RadioButton("1 year", ref GraphWindow.year, 1);
344 ImGui.SameLine();
345 ImGui.RadioButton("5 years", ref GraphWindow.year, 5);
346 ImGui.SameLine();
347 ImGui.RadioButton("25 years", ref GraphWindow.year, 25);
348 ImGui.SameLine();
349 ImGui.RadioButton("100 years", ref GraphWindow.year, 100);
350
351 ImGui.Text("Trees:");
352 for (int i = 0; i < tree_series.Length; i++)
353 {
354 var key = tree_series[i];
355 if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
356 {
357 data_sets_show[key] = !data_sets_show[key];
97 358 }
98 359
99 ImPlot.PushStyleVar(ImPlotStyleVar.LineWeight, 2.0f);
100 ImPlot.PushStyleVar(ImPlotStyleVar.MinorAlpha, 0.0f);
101 // ImPlot.PushStyleVar(ImPlotStyleVar.MajorGridSize, new Num.Vector2(0.0f, 0.0f));
102 // ImPlot.PushStyleVar(ImPlotStyleVar.MinorGridSize, new Num.Vector2(0.0f, 0.0f));
360 if (i != tree_series.Length-1)
361 {
362 ImGui.SameLine();
363 }
364 }
103 365
104 ImPlot.SetNextPlotLimits(totals.Count()-periods, totals.Count(), min, max , ImGuiCond.Always);
105 if( ImPlot.BeginPlot("My Plot", null, null, new Num.Vector2(-1,0), ImPlotFlags.NoLegend | ImPlotFlags.NoMousePos )) {
106 // Span<double> totals = new Span<double>(new double[]{0.0, 1.0, 2.0, 9.0});
107 foreach (var key in keys) {
108 var show = data_sets_show[key];
109 var data = data_sets[key];
110 var data_array = data_sets[key].ToArray();
111 if (data_array.Length > 0 && show)
112 {
113 ImPlot.PlotLine(key, ref data_array[0], data_array.Length);
114 ImPlot.AnnotateClamped(data_array.Length-1, data_array[data_array.Length-1],
115 new Num.Vector2(5, -10), StyleSets.grey, key);
116 }
117 }
118
119 ImPlot.EndPlot();
120 }
121
122 ImPlot.PopStyleVar(2);
123
124 ImGui.RadioButton("1 year", ref GraphWindow.year, 1);
125 ImGui.SameLine();
126 ImGui.RadioButton("5 years", ref GraphWindow.year, 5);
127 ImGui.SameLine();
128 ImGui.RadioButton("25 years", ref GraphWindow.year, 25);
129 ImGui.SameLine();
130 ImGui.RadioButton("100 years", ref GraphWindow.year, 100);
131
132 ImGui.Text("Trees:");
133 for (int i = 0; i < tree_series.Length; i++)
366 ImGui.Text("Money:");
367 for (int i = 0; i < money_series.Length; i++)
368 {
369 var key = money_series[i];
370 if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
134 371 {
135 var key = tree_series[i];
136 if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
137 {
138 data_sets_show[key] = !data_sets_show[key];
139 }
140
141 if (i != tree_series.Length-1)
142 {
143 ImGui.SameLine();
144 }
145
372 data_sets_show[key] = !data_sets_show[key];
146 373 }
374 if ((i % 4 != 3) && (i != money_series.Length-1)) {
375 ImGui.SameLine();
376 }
377 }
147 378
148 ImGui.Text("Money:");
149 for (int i = 0; i < money_series.Length; i++)
150 {
151 var key = money_series[i];
152 if (Menu.activeButton(key, data_sets_show[key], StyleSets.selected, StyleSets.white))
153 {
154 data_sets_show[key] = !data_sets_show[key];
155 }
156 if ((i % 4 != 3) && (i != money_series.Length-1)) {
157 ImGui.SameLine();
158 }
379 ImGui.Text("Always show zero:");
380 ImGui.SameLine();
381 ImGui.Checkbox("##AlwaysShowZero", ref always_show_zero);
382 #if DEBUG
383 ImGui.SameLine();
384 ImGui.Text("Logarithmic: ");
385 ImGui.SameLine();
386 ImGui.Checkbox("##Logarithmic", ref logarithmic);
387 #endif
159 388
160 }
161
162
163
164
165 ImGui.End();
166 ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.Left;
167 StyleSets.defaultSet.pop();
168 ImGui.PopFont();
169
389 ImGui.End();
390 ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.Left;
391 StyleSets.defaultSet.pop();
392 ImGui.PopFont();
170 393 }
171 394 }
172 395 }
@@ -6,6 +6,7
6 6
7 7 using isometricparkfna.Engines;
8 8 using isometricparkfna.Messages;
9 using isometricparkfna.Components;
9 10
10 11 namespace isometricparkfna.UI
11 12 {
@@ -98,12 +99,59
98 99 ImGui.Text(header);
99 100
100 101
101 var dimensions = ImGui.CalcTextSize("X Graph X Contracts $ Budget X Forest X News X | Pause 1 2 3 4 5") ;
102 var dimensions = ImGui.CalcTextSize("X Tower X Preserve X Dezone X Bulldozer | X Graph X Contracts $ Budget X Forest X News X | Pause 1 2 3 4 5") ;
102 103
103 104 // ImGui.SetCursorPosX(width - 520);
104 105 // Add 12 pixels for each button, plus separator
105 ImGui.SetCursorPosX(width - (dimensions.X + 11*12));
106 if (Menu.activeButton("\ue124 Graph", bridgeEngine.windowStatuses[Window.Graph], StyleSets.selected, StyleSets.white))
106 ImGui.SetCursorPosX(width - (dimensions.X + 11*15));
107
108 if (Menu.activeButton("\ue06e Tower", bridgeEngine.toolStatuses[Tool.Tower], StyleSets.selected, StyleSets.white))
109 {
110 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Tower});
111 }
112 if (Menu.activeButton("\ue099 Preserve", bridgeEngine.toolStatuses[Tool.Preserve], StyleSets.selected, StyleSets.white))
113 {
114 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Preserve});
115 }
116 if (!bridgeEngine.toolStatuses[Tool.Dezone]) {
117 if (Menu.activeButton("\ue122 Bulldozer", bridgeEngine.toolStatuses[Tool.Bulldozer], StyleSets.selected, StyleSets.white))
118 {
119 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Bulldozer});
120 }
121 }
122 else {
123 if (Menu.activeButton("\ue058 Dezone", bridgeEngine.toolStatuses[Tool.Dezone], StyleSets.selected, StyleSets.white))
124 {
125 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Dezone});
126 }
127 }
128
129
130 ImGui.SetCursorPosX(ImGui.GetCursorPosX() - 9);
131 if (ImGui.Button("\ue01d"))
132 {
133 ImGui.OpenPopup("BulldozerChildren");
134 }
135 if (ImGui.BeginPopup("BulldozerChildren"))
136 {
137 if (Menu.activeButton("\ue122 Bulldozer", bridgeEngine.toolStatuses[Tool.Bulldozer], StyleSets.selected, StyleSets.white))
138 {
139 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Bulldozer});
140 }
141 if (Menu.activeButton("\ue058 Dezone", bridgeEngine.toolStatuses[Tool.Dezone], StyleSets.selected, StyleSets.white))
142 {
143 bridgeEngine.toggleToolMessages.Add(new ToggleToolMessage {Tool = Tool.Dezone});
144 ImGui.CloseCurrentPopup();
145 }
146 if (ImGui.Button("Cancel"))
147 {
148 ImGui.CloseCurrentPopup();
149 }
150 ImGui.EndPopup();
151 }
152 ImGui.Text("|");
153
154 if (Menu.activeButton("\ue03e Graph", bridgeEngine.windowStatuses[Window.Graph], StyleSets.selected, StyleSets.white))
107 155 {
108 156 bridgeEngine.typeMessages.Add(new ToggleWindowTypeMessage {Window = Window.Graph});
109 157
@@ -46,8 +46,6
46 46 showModal = true;
47 47
48 48 NewGameWindow.Reset();
49
50
51 49 }
52 50
53 51 public static void Reset() {
@@ -193,10 +191,9
193 191
194 192 NewGameWindow.playerName2Pos = newPlayerName2Pos;
195 193
196 ImGui.RadioButton("Easy: Full Funding", ref choice, ((int)DifficultyLevel.Easy));
194 ImGui.RadioButton("Easy: Social Democracy", ref choice, ((int)DifficultyLevel.Easy));
197 195 ImGui.RadioButton("Medium: Austerity", ref choice, ((int)DifficultyLevel.Medium));
198 ImGui.RadioButton("Hard: Unfunded", ref choice, ((int)DifficultyLevel.Hard));
199
196 ImGui.RadioButton("Hard: Libertarianism", ref choice, ((int)DifficultyLevel.Hard));
200 197
201 198 if (ImGui.Button("Okay"))
202 199 {
@@ -220,13 +217,10
220 217 NewGameWindow.Reset();
221 218 }
222 219
223
224 220 ImGui.End();
225 221
226
227 222 StyleSets.defaultSet.pop();
228 223 ImGui.PopFont();
229
230 224 }
231 225 }
232 226 }
@@ -65,12 +65,31
65 65
66 66 public static class NewsWindow
67 67 {
68 public static bool wire_open = true;
69 public static bool true_open = false;
70 public static bool naturalist_open = false;
71 public static bool had_focus = false;
68 72
69 public static bool had_focus = false;
73 private static bool MenuItem(string label, bool active) {
74 if (active)
75 {
76 ImGui.PushStyleColor(ImGuiCol.Text, StyleSets.white);
77 }
78
79 var result = ImGui.BeginTabItem(label);
80
81 if (active)
82 {
83 ImGui.PopStyleColor(1);
84 }
85
86 return result;
87 }
70 88
71 89 public static void Render(ImFontPtr font, Simulation sim, ImGuiWindowBridgeEngine engine)
72 90 {
73 91 bool newShow = true;
92
74 93 if (newShow)
75 94 {
76 95 ImGui.PushFont(font);
@@ -98,10 +117,11
98 117
99 118 if (ImGui.BeginTabBar("Sources", 0))
100 119 {
101
102
103 if (ImGui.BeginTabItem("Wire"))
120 if (MenuItem("Wire", wire_open))
104 121 {
122 wire_open = true;
123 naturalist_open = false;
124 true_open = false;
105 125
106 126 foreach (NewsItem story in content.Where(s => (s.source == "Wire")).Take(3))
107 127 {
@@ -113,9 +133,12
113 133 }
114 134 ImGui.EndTabItem();
115 135 }
116 ImGui.EndTabItem();
117 if (ImGui.BeginTabItem("The Naturalist"))
136 if (MenuItem("The Naturalist", naturalist_open))
118 137 {
138 wire_open = false;
139 naturalist_open = true;
140 true_open = false;
141
119 142 foreach (NewsItem story in content.Where(s => (s.source == "Arborist")).Take(3))
120 143 {
121 144 if (ImGui.TreeNode(story.hed))
@@ -126,8 +149,12
126 149 }
127 150 ImGui.EndTabItem();
128 151 }
129 if (ImGui.BeginTabItem("All True News"))
152 if (MenuItem("All True News", true_open))
130 153 {
154 wire_open = false;
155 naturalist_open = false;
156 true_open = true;
157
131 158 foreach (NewsItem story in content.Where(s => (s.source == "True")).Take(3))
132 159 {
133 160 if (ImGui.TreeNode(story.hed))
@@ -138,10 +165,9
138 165 }
139 166 ImGui.EndTabItem();
140 167 }
168 ImGui.EndTabBar();
141 169 }
142 170
143 ImGui.EndTabBar();
144
145 171
146 172 if (ImGui.Button("Okay"))
147 173 {
@@ -5,6 +5,7
5 5
6 6 using Microsoft.Xna.Framework;
7 7
8 using isometricparkfna.Components;
8 9 using isometricparkfna.Engines;
9 10 using isometricparkfna.Messages;
10 11 using isometricparkfna.UI;
@@ -16,24 +17,42
16 17 {
17 18
18 19 public static bool hadFocus = false;
20
19 21 public static bool newFullscreen;
20 22 public static Vector2 newResolution;
23 public static float newSoundEffectVolume;
24 public static bool newSoundEffectsMute;
21 25
22 26 private static string fontName = "Iosevka";
23 27 private static int fontSize = 15;
24 28 private static ProfanityLevel profanityLevel = default;
25 29
26 public static void Initialize(Vector2 resolution, bool fullscreen, ProfanityLevel profanityLevel)
30
31 private static bool origFullscreen = OptionsWindow.newFullscreen;
32 private static Vector2 origResolution = OptionsWindow.newResolution;
33
34 private static string origFontName = OptionsWindow.fontName;
35 private static int origFontSize = OptionsWindow.fontSize;
36 private static ProfanityLevel origProfanityLevel = OptionsWindow.profanityLevel;
37 private static float origSoundEffectVolume;
38 private static bool origSoundEffectsMute;
39
40 private static float prevSoundEffectVolume; //Tracks the previously set. (As opposed to origSoundEffectVolume, which is the previously *applied* volume.
41
42 public static void Initialize(Vector2 resolution, bool fullscreen, ProfanityLevel profanityLevel, Options startingOptions)
27 43 {
28 44
29 45 OptionsWindow.newFullscreen = fullscreen;
30 46 OptionsWindow.newResolution = resolution;
31 47 OptionsWindow.profanityLevel = profanityLevel;
48
49 newSoundEffectVolume = startingOptions.SoundEffectVolume;
50 newSoundEffectsMute = startingOptions.SoundEffectMuted;
51 prevSoundEffectVolume = startingOptions.SoundEffectVolume;
32 52 }
33 53
34 public static void Render(ImFontPtr font, ImFontPtr italicFont, ImGuiWindowBridgeEngine bridgeEngine, int width, ProfanityLevel profanityLevel)
54 public static void Render(ImFontPtr font, ImFontPtr italicFont, ImGuiWindowBridgeEngine bridgeEngine, int width)
35 55 {
36
37 56 ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.None;
38 57 bool newShow = true;
39 58
@@ -63,7 +82,7
63 82 ImGui.SameLine();
64 83
65 84 if (ImGui.BeginCombo("##resolutions", string.Format("{0}x{1}",
66 newResolution.X, newResolution.Y)))
85 newResolution.X, newResolution.Y)))
67 86 {
68 87
69 88 foreach(var (width_option, height_option) in new[] {(1280, 640),
@@ -126,6 +145,26
126 145
127 146 ImGui.Checkbox("Fullscreen", ref newFullscreen);
128 147
148
149
150 ImGui.Separator();
151
152 ImGui.PushFont(italicFont);
153 ImGui.Text("Audio");
154 ImGui.PopFont();
155 ImGui.Text("Sound Effects:\t");
156
157 ImGui.SameLine();
158 ImGui.DragFloat("##Sfx", ref newSoundEffectVolume, 0.005f, 0.0f, 1.0f, "%.2f");
159
160 if ((newSoundEffectVolume != prevSoundEffectVolume) && ImGui.IsItemDeactivatedAfterEdit()) {
161 bridgeEngine.playSoundMessages.Add(new PlaySoundMessage { SoundName = "Bell", Volume = newSoundEffectVolume});
162 prevSoundEffectVolume = newSoundEffectVolume;
163 }
164
165 ImGui.SameLine();
166 ImGui.Checkbox("Mute", ref newSoundEffectsMute);
167
129 168 ImGui.Separator();
130 169
131 170 ImGui.PushFont(italicFont);
@@ -141,7 +180,10
141 180 {
142 181 if(ImGui.Selectable(level.ToString()))
143 182 {
144 bridgeEngine.setOptionMessages.Add(new SetOptionMessage { NewProfanitySetting = (ProfanityLevel)level});
183 bridgeEngine.setOptionMessages.Add(new SetOptionMessage { NewProfanitySetting = (ProfanityLevel)level,
184 NewSoundEffectVolume = origSoundEffectVolume,
185 NewSoundEffectMuted = origSoundEffectsMute
186 });
145 187 OptionsWindow.profanityLevel = (ProfanityLevel)level;
146 188 }
147 189 }
@@ -165,7 +207,21
165 207 fontName = OptionsWindow.fontName
166 208 });
167 209
168 }
210 origFullscreen = OptionsWindow.newFullscreen;
211 origResolution = OptionsWindow.newResolution;
212
213 origFontName = OptionsWindow.fontName;
214 origFontSize = OptionsWindow.fontSize;
215 origProfanityLevel = OptionsWindow.profanityLevel;
216 origSoundEffectVolume = OptionsWindow.newSoundEffectVolume;
217 origSoundEffectsMute = OptionsWindow.newSoundEffectsMute;
218
219
220 bridgeEngine.setOptionMessages.Add(new SetOptionMessage { NewProfanitySetting = (ProfanityLevel)profanityLevel,
221 NewSoundEffectVolume = newSoundEffectVolume,
222 NewSoundEffectMuted = newSoundEffectsMute});
223 }
224
169 225 ImGui.SameLine();
170 226 if (ImGui.Button("Apply"))
171 227 {
@@ -177,6 +233,41
177 233 fontSize = OptionsWindow.fontSize,
178 234 fontName = OptionsWindow.fontName
179 235 });
236
237 origFullscreen = OptionsWindow.newFullscreen;
238 origResolution = OptionsWindow.newResolution;
239
240 origFontName = OptionsWindow.fontName;
241 origFontSize = OptionsWindow.fontSize;
242 origProfanityLevel = OptionsWindow.profanityLevel;
243 origSoundEffectVolume = OptionsWindow.newSoundEffectVolume;
244 origSoundEffectsMute = OptionsWindow.newSoundEffectsMute;
245
246 bridgeEngine.setOptionMessages.Add(new SetOptionMessage { NewProfanitySetting = (ProfanityLevel)profanityLevel,
247 NewSoundEffectVolume = newSoundEffectVolume,
248 NewSoundEffectMuted = newSoundEffectsMute});
249 }
250
251 ImGui.SameLine();
252 if (ImGui.Button("Cancel")) {
253 bridgeEngine.typeMessages.Add(new ToggleWindowTypeMessage {Window = Window.Options});
254
255 OptionsWindow.newFullscreen = origFullscreen;
256 OptionsWindow.newResolution = origResolution;
257
258 OptionsWindow.fontName = origFontName;
259 OptionsWindow.fontSize = origFontSize;
260 OptionsWindow.profanityLevel = origProfanityLevel;
261 OptionsWindow.newSoundEffectVolume = origSoundEffectVolume;
262 OptionsWindow.newSoundEffectsMute = origSoundEffectsMute;
263
264
265 if ((origSoundEffectsMute != newSoundEffectsMute)
266 | (origSoundEffectVolume != newSoundEffectVolume)) {
267 bridgeEngine.setOptionMessages.Add(new SetOptionMessage { NewProfanitySetting = (ProfanityLevel)origProfanityLevel,
268 NewSoundEffectVolume = origSoundEffectVolume,
269 NewSoundEffectMuted = origSoundEffectsMute});
270 }
180 271 }
181 272
182 273
@@ -190,7 +281,7
190 281 {
191 282 bridgeEngine.typeMessages.Add(new ToggleWindowTypeMessage {Window = Window.Options});
192 283 }
193 }
284 }
194 285
195 286 public static void setFont(string fontName, int fontSize)
196 287 {
@@ -55,7 +55,7
55 55 {ImGuiCol.Border, black},
56 56 {ImGuiCol.BorderShadow, black},
57 57
58 {ImGuiCol.PopupBg, white},
58 {ImGuiCol.PopupBg, grey},
59 59
60 60 {ImGuiCol.Button, grey_transparent},
61 61 {ImGuiCol.Text, black}
@@ -2,14 +2,14
2 2 using JM.LinqFaster;
3 3 namespace isometricparkfna
4 4 {
5 public class EmptyArrayException : Exception {
6 public EmptyArrayException() {
7 }
5 public class EmptyArrayException : Exception {
6 public EmptyArrayException() {
7 }
8 8
9 public EmptyArrayException(string message) : base(message) {
10 }
9 public EmptyArrayException(string message) : base(message) {
10 }
11 11
12 }
12 }
13 13 public class MathUtils
14 14 {
15 15 public MathUtils()
@@ -68,6 +68,22
68 68 }
69 69 }
70 70
71 public static float Clamp(float val, float min, float max)
72 {
73 if (val > max)
74 {
75 return max;
76 }
77 else if (val < min)
78 {
79 return min;
80 }
81 else
82 {
83 return val;
84 }
85 }
86
71 87 protected float Decrement(float value, float delta)
72 88 {
73 89 float magnitude = Math.Abs(value);
@@ -136,38 +152,46
136 152 return integers[index];
137 153 }
138 154
139 public static float Percentile(float[] floats, float percentile) {
140 if (floats.Length > 0) {
141 Array.Sort(floats);
142 var raw_position = (floats.Length-1) * percentile;
155 public static float Percentile(float[] floats, float percentile) {
156 if (floats.Length > 0) {
157 // Array.Sort(floats);
158 var raw_position = (floats.Length-1) * percentile;
143 159
144 var lower_position = (int)raw_position;
145 var higher_position = Math.Min((int)(raw_position+1), floats.Length-1);
160 var lower_position = (int)raw_position;
161 var higher_position = Math.Min((int)(raw_position+1), floats.Length-1);
146 162
147 var remainder = (raw_position % 1);
163 var remainder = (raw_position % 1);
148 164
149 return (floats[lower_position] * (1-remainder)) + (floats[higher_position] * remainder);
150 }
151 else {
152 throw new EmptyArrayException("Array must not be empty");
153 }
154 }
165 return (floats[lower_position] * (1-remainder)) + (floats[higher_position] * remainder);
166 }
167 else {
168 throw new EmptyArrayException("Array must not be empty");
169 }
170 }
155 171
156 public static double Percentile(double[] doubles, double percentile) {
157 if (doubles.Length > 0) {
158 Array.Sort(doubles);
159 var raw_position = (doubles.Length-1) * percentile;
172 public static double Percentile(double[] doubles, double percentile) {
173 if (doubles.Length > 0) {
174 Array.Sort(doubles);
175 var raw_position = (doubles.Length-1) * percentile;
160 176
161 var lower_position = (int)raw_position;
162 var higher_position = Math.Min((int)raw_position + 1, doubles.Length -1);
177 var lower_position = (int)raw_position;
178 var higher_position = Math.Min((int)raw_position + 1, doubles.Length -1);
179
180 var remainder = (raw_position % 1);
163 181
164 var remainder = (raw_position % 1);
182 return (doubles[lower_position] * (1-remainder)) + (doubles[higher_position] * remainder);
183 }
184 else {
185 throw new EmptyArrayException("Array must not be empty");
186 }
187 }
165 188
166 return (doubles[lower_position] * (1-remainder)) + (doubles[higher_position] * remainder);
167 }
168 else {
169 throw new EmptyArrayException("Array must not be empty");
170 }
171 }
189 public static float SymmetricLog10(float num) {
190 return num > 0.0f ? (float)Math.Log10(num) : -(float)Math.Log10(-num);
191 }
192
193 public static double SymmetricLog10(double num) {
194 return num > 0.0f ? Math.Log10(num) : -Math.Log10(-num);
195 }
172 196 }
173 197 }
@@ -31,16 +31,12
31 31 <!-- <ProjectReference Include="..\encompass-cs\encompass-cs\encompass-cs.csproj" /> -->
32 32 <ProjectReference Include="..\SpriteFontPlus\src\SpriteFontPlus.FNA.Core.csproj" />
33 33 <ProjectReference Include="..\encompass-cs\encompass-cs\encompass-cs.csproj" />
34 <ProjectReference Include="..\ImPlot.NET\ImPlot.NET.csproj">
35 <!-- <Name>ImPlot.NET</Name> -->
36 </ProjectReference>
37 34 <ProjectReference Include="..\ImGui.NET\ImGui.NET.csproj">
38 35 <!-- <Name>ImGui.NET</Name> -->
39 36 </ProjectReference>
40 37 </ItemGroup>
41 38
42 39 <ItemGroup>
43 <Reference Include="System" />
44 40 <Reference Include="Newtonsoft.Json" Version="12.0.3">
45 41 <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
46 42 </Reference>
@@ -75,9 +75,6
75 75 <Name>ImGui.NET</Name>
76 76 <HintPath>..\packages\ImGui.NET.1.78.0\lib\netstandard2.0\ImGui.NET.dll</HintPath>
77 77 </ProjectReference>
78 <ProjectReference Include="..\ImPlot.NET\ImPlot.NET.csproj">
79 <Name>ImPlot.NET</Name>
80 </ProjectReference>
81 78 <!-- </ProjectReference>\
82 79 -->
83 80 <ProjectReference Include="..\encompass-cs\encompass-cs\encompass-cs.csproj">
@@ -89,8 +86,29
89 86 <None Include="Content\FNASound.wav">
90 87 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
91 88 </None>
89 <None Include="Content\Click.wav">
90 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
91 </None>
92 <None Include="Content\ClickPart1.wav">
93 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
94 </None>
95 <None Include="Content\ClickPart2.wav">
96 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
97 </None>
98 <None Include="Content\ConstructionShort.wav">
99 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
100 </None>
101 <None Include="Content\Construction.wav">
102 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
103 </None>
104 <None Include="Content\Bell.wav">
105 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
106 </None>
92 107 <None Include="packages.config" />
93 <None Include="Content\part4_tileset.png">
108 <!-- <None Include="Content\part4_tileset.png"> -->
109 <!-- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> -->
110 <!-- </None> -->
111 <None Include="Content\merged_tileset.png">
94 112 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
95 113 </None>
96 114 <None Include="Content\solid_tileset.png">
@@ -102,10 +120,12
102 120 <None Include="Content\iosevka-medium.ttf">
103 121 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
104 122 </None>
123 <None Include="Content\OCRA.ttf">
124 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
125 </None>
105 126 <Content Include="cimgui/win-x64/cimgui.dll" CopyToOutputDirectory="PreserveNewest" />
106 127 <Content Include="cimgui/osx-x64/cimgui.dylib" CopyToOutputDirectory="PreserveNewest" Link="libcimgui.dylib" />
107 128 <Content Include="cimgui/linux-x64/cimgui.so" CopyToOutputDirectory="PreserveNewest" Link="libcimgui.so" />
108 <Content Include="cimplot/linux-x64/cimplot.so" CopyToOutputDirectory="PreserveNewest" Link="libcimplot.so" />
109 129 <None Include="fnalibs\README.txt" />
110 130 <None Include="fnalibs\lib64\libFAudio.so.0" />
111 131 <None Include="fnalibs\lib64\libmojoshader.so" />
You need to be logged in to leave comments. Login now