Description:
Add Mass Vandalism event.
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r420:ad760cacfa02 -

@@ -0,0 +1,8
1
2
3 using Encompass;
4
5 namespace isometricparkfna.Components
6 {
7 public struct EventComponent : IComponent { }
8 }
@@ -8,10 +8,10
8 8 - Movement @done(2021-01-27)
9 9 - Close button @done(2021-01-28)
10 10 - Better appearance
11 - Money graph @maybe
11 - Money graph @maybe
12 12 Procgen:
13 13 short phase, maybe?
14 - Add some procedurally generated dialog @maybe @milestone(2: Procgen)
14 - Add some procedurally generated dialog @maybe @milestone(2: Procgen)
15 15 - Add some procedurally generated newspaper @maybe @milestone(2: Procgen) @done(2021-03-15)
16 16 - Basic NEWS tab @milestone(2: Procgen)
17 17 - Different tabs for different sources @done(2021-02-21)
@@ -33,7 +33,6
33 33 - Add company images @milestone(3: Contracts) @maybe @done(2021-05-21)
34 34 - Contracts should end
35 35 Trees:
36
37 36 - Add basic maintenance cost @milestone(1: Basic Money) @done(2021-01-27)
38 37 - Add basic age simulation
39 38 - Add water @milestone(6: Trees and Tiles)
@@ -46,7 +45,7
46 45 Reduces cost of vandalism repair?
47 46 - Sell Firewood?
48 47 Staff:
49 - Ranger staffing? @maybe @milestone(1: Basic Money)
48 - Ranger staffing? @maybe @milestone(1: Basic Money)
50 49 - Staffing window
51 50 - Ranger allocation
52 51 - Set employee salaries, leave, etc. @maybe
@@ -56,7 +55,7
56 55 Leisure:
57 56 - Add way to mark off area for leisure @milestone(7: Leisure)
58 57 - Basic satisfaction @milestone(7: Leisure)
59 - Set
58 - Set
60 59 End games/outcomes:
61 60 - Financial mismanagement @milestone(5: Events)
62 61 - Figure out threshold
@@ -76,12 +75,11
76 75 - Land repatriation to indigenous @maybe
77 76 Like the acknowledgement, don't want it to be too white savior-y (although obv. player isn't necessarily white)
78 77 - Research center @maybe
79 -
80 78 Community:
81 79 Differing reputation with different groups. Could mix more and less political.
82 80 Don't want to go too Democracy 3/4: being able to affect the group size via policy is probably out. (Groups being intersectional might work, but is kind of tricky.)
83 Maybe a procedurally generated set of groups with some hard-coded elements? E.g.,
84
81 Maybe a procedurally generated set of groups with some hard-coded elements? E.g
82
85 83 Misc:
86 84 - Assistant commentary @milestone(5: Events)
87 85 Need to ensure it's not annoying
@@ -91,13 +89,13
91 89 - Federal grant
92 90 - Celebrity visit
93 91 - Disasters @maybe
94 - Fire
92 - Fire
95 93 would probably have to animate
96 94 - Disease
97 95 - Photos for dialog?
98 96 - Graphs window
99 97 Could use ImPlot for this
100
98
101 99 Structure:
102 100 - Add modes @milestone(5: Events)
103 101 - Refactor stuff out of FNAGame
@@ -154,11 +152,11
154 152 - Relocate fonts to central place @done(2021-06-26)
155 153 - Remove fonts from DebugWindow?
156 154 - Adjust window dimensions when font changes
157 - Option to Turn off bad outcomes or disasters @maybe
155 - Option to Turn off bad outcomes or disasters @maybe
158 156 - Dyslexic-friendly font @maybe @done(2021-06-26)
159 157 Cursory research indicates open sans-serif fonts are best,
160 158 although fonts only help so much. (Monospaced fonts are also cited as good options so Iosevka might already be good enough. Still, I added Roboto.)
161
159
162 160 - Screen reader support @maybe
163 161 Would probably be a big undertaking (sort of opposite to the web, where things tend to be accessible unless you start reimplenting things or going more advanced)
164 162 - Investigate .NET support for screen readers
@@ -172,7 +170,6
172 170 - Linux
173 171 - Look for prior art
174 172 - Add a "describe" button/key that speaks the current scene @maybe
175 -
176 173 - No fees when contracts break
177 174 - Contracts go dormant instead of ending.
178 175 Other QoL things:
@@ -1,17 +1,32
1
2 VAR playerSwears = 0
3 VAR playerRude = 0
1 4
2 5 VAR GovernorOpinion = 0
3 6
7
4 8 //This is needed to make both including and for jumpting to dialog sections work:
5 9 === placeholder ===
6 10
7 11 -> END
8 12
13
14 === function alter(ref x, k) ===
15 ~ x = x + k
16
17
18 === function inc(ref x) ===
19 ~ x = x + 1
20
21 === function dec(ref x) ===
22 ~ x = x - 1
23
9 24 === Once ===
10 25
11 26 Once upon a time...
12 27
13 * There were two choices.
14 * There were four lines of content.
28 + There were two choices.
29 + There were four lines of content.
15 30
16 31 - They lived happily ever after.
17 32 -> END
@@ -48,8 +63,6
48 63 * [Nice to meet you.]
49 64 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.
50 65
51 -> BadNewsReact ->
52
53 66 * * [Got it, thanks.]
54 67
55 68 \#assistantName\#: Bye
@@ -61,9 +74,46
61 74
62 75
63 76 === BadNewsReact ===
64 * [Damn.]
77
78
79
80 + [Damn.] {inc(playerSwears)}
81 ->->
82 + [Fuck.] {inc(playerSwears)}
83 ->->
84 + [Shoot.] {inc(playerSwears)}
85 ->->
86 + [*Sigh.* Fine.]
65 87 ->->
66 * [Fuck.]
88
89 === AssistantAcknowlege ===
90 + [Thanks.]
91 ->->
92 + [Mmmm hmm.]
93 ->->
94 + [Get to it.] {inc(playerRude)}
95 ->->
96 + [I really appreciate it, \#assistantName\#]
97 -> Appreciate
98
99 = Appreciate
100 \#assistantName\#: Oh, you're welcome.
67 101 ->->
68 * [Shoot.]
69 ->-> No newline at end of file
102
103 === MassVandalism ===
104 \#assistantName\#: Bad news, director.
105 + [Oh?]
106 \#assistantName\#: A number of trees have been seriously damaged overnight.
107 + + [How bad are they?]
108
109 \#assistantName\#: I'm no botanist, but they're not great. The gouges are pretty deep.
110
111 -> BadNewsReact ->
112
113 \#assistantName\#: Yeah, it's awful.
114
115 I'll see who's around and get to cleaning.
116
117 -> AssistantAcknowlege ->
118
119 -> END No newline at end of file
@@ -1,1 +1,1
1 {"inkVersion":20,"root":[[["done",{"#f":5,"#n":"g-0"}],null],"done",{"placeholder":["end",{"#f":1}],"Once":[["^Once upon a time...","\n",["ev",{"^->":"Once.0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"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":18},{"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"},{"#f":5}],"c-1":["ev",{"^->":"Once.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^They lived happily ever after.","\n","end",{"#f":5}]}],{"#f":1}],"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}]}],{"#f":1}],"IntroAssistant":[["^#assistantName#: Hello. I'm #assistantName#.","\n","ev","str","^Nice to meet you.","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^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",{"->t->":"BadNewsReact"},["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}]}],{"#f":1}],"BadNewsReact":[["ev","str","^Damn.","/str","/ev",{"*":".^.c-0","flg":20},"ev","str","^Fuck.","/str","/ev",{"*":".^.c-1","flg":20},"ev","str","^Shoot.","/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","ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"global decl":["ev",0,{"VAR=":"GovernorOpinion"},"/ev","end",null],"#f":1}],"listDefs":{}} No newline at end of file
1 {"inkVersion":20,"root":[[["done",{"#f":5,"#n":"g-0"}],null],"done",{"placeholder":["end",{"#f":1}],"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"},{"#f":5}],"c-1":["ev",{"^->":"Once.0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^They lived happily ever after.","\n","end",{"#f":5}]}],{"#f":1}],"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}]}],{"#f":1}],"IntroAssistant":[["^#assistantName#: Hello. I'm #assistantName#.","\n","ev","str","^Nice to meet you.","/str","/ev",{"*":".^.c-0","flg":20},{"c-0":["\n","^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}]}],{"#f":1}],"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},{"c-0":["\n","ev","void","/ev","->->",{"#f":5}],"c-1":["\n","ev","void","/ev","->->",{"#f":5}],"c-2":["\n","ev","void","/ev","->->",{"#f":5}],"c-3":["\n","ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"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","->->",{"#f":5}],"c-1":["\n","ev","void","/ev","->->",{"#f":5}],"c-2":["\n","ev","void","/ev","->->",{"#f":5}],"c-3":["\n","ev","void","/ev","->->",{"#f":5}]}],{"#f":1}],"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 awful.","\n","^I'll see who's around and get to cleaning.","\n",{"->t->":"AssistantAcknowlege"},"end",{"#f":5}]}],{"#f":5}]}],{"#f":1}],"global decl":["ev",0,{"VAR=":"GovernorOpinion"},"/ev","end",null],"#f":1}],"listDefs":{}} No newline at end of file
@@ -4,6 +4,6
4 4 INCLUDE dialog.ink
5 5
6 6
7 -> IntroAssistant
7 -> MassVandalism
8 8
9 9 -> END No newline at end of file
@@ -1,39 +1,75
1 1 using System;
2 2
3 using Microsoft.Xna.Framework;
4
3 5 using Encompass;
4 6
5 7 using isometricparkfna.Messages;
8 using isometricparkfna.Components;
9 using isometricparkfna.Utils;
6 10
7 11 namespace isometricparkfna.Engines
8 12 {
9 13
10 14 [Receives(typeof(TickMessage))]
11 15 [Sends(typeof(SpawnDialogMessage))]
16 [Reads(typeof(EventComponent),
17 typeof(TreeDeltaComponent))]
18 [Writes(typeof(TreeDeltaComponent))]
12 19 class EventEngine : Engine
13 20 {
14
15 21 Random Random;
16 22
17 23 public EventEngine()
18 24 {
19 25 this.Random = new Random();
26
20 27 }
21 28
22 29 public override void Update(double dt)
23 30 {
31
32 #region random_events
24 33 foreach (var tick in ReadMessages<TickMessage>())
25 34 {
26 35
27 if (this.Random.Next(0, 10) == 1)
36 #region remove_events
37 foreach(var entity in ReadEntities<EventComponent>())
38 {
39 Logging.Debug("Destroying Event entity.");
40 Destroy(entity);
41 }
42 #endregion
43 if (this.Random.Next(0, 100) == 1)
28 44 {
29 45 Logging.Debug("Spawning Once dialog.");
30 46 SendMessage(new SpawnDialogMessage { Path = "Once" });
31 47 }
32 48
33 }
34 }
49 if (this.Random.Next(0, 10) == 2)
50 {
51 Logging.Debug("Tree planting campaign!🎉");
52
53 var campaignEntity = CreateEntity();
54
55 AddComponent(campaignEntity, new TreeDeltaComponent{deltaTrees = new Fact<int>(4)});
35 56
36
57 // AddComponent(campaignEntity, new AreaComponent{squares=final_squares});
58 }
59 if (this.Random.Next(0, 10) == 3)
60 {
61 Logging.Debug("Mass vandalism 😿");
62
63 var campaignEntity = CreateEntity();
37 64
65 AddComponent(campaignEntity, new TreeDeltaComponent{deltaTrees = new Fact<int>(-100)});
66 AddComponent(campaignEntity, new EventComponent{});
67
68 SendMessage(new SpawnDialogMessage { Path = "MassVandalism" });
69 }
70 }
71 #endregion
72
73 }
38 74 }
39 75 }
@@ -1,5 +1,8
1 1 using System;
2 2 using System.Linq;
3 using System.Collections.Generic;
4
5 using Microsoft.Xna.Framework;
3 6
4 7 using Encompass;
5 8
@@ -23,10 +26,24
23 26 private int ticksToSend;
24 27 private Random random_generator;
25 28
29 Vector2[] all_squares;
30
26 31 public SimulationBridgeEngine(Simulation simulation)
27 32 {
28 33 this.simulation = simulation;
29 34 this.random_generator = new Random();
35
36 List<Vector2> squares = new List<Vector2>();
37
38 for(int i = 0; i < simulation.map.MapWidth; i++)
39 {
40 for(int j = 0; j < simulation.map.MapHeight; j++)
41 {
42 squares.Add(new Vector2(i,j));
43 }
44 }
45 this.all_squares = squares.ToArray();
46
30 47 }
31 48
32 49 public int addTick()
@@ -106,44 +123,52
106 123
107 124 foreach (ref readonly var entity in ReadEntities<TreeDeltaComponent>())
108 125 {
109 var status = GetComponent<ContractStatusComponent>(entity).status;
110 var area = GetComponent<AreaComponent>(entity);
111 var delta = GetComponent<TreeDeltaComponent>(entity);
126 if ((HasComponent<ContractStatusComponent>(entity) && GetComponent<ContractStatusComponent>(entity).status == ContractStatus.Accepted)
127 || !(HasComponent<ContractStatusComponent>(entity) ))
128 {
129 var delta = GetComponent<TreeDeltaComponent>(entity);
112 130
113 if (status == ContractStatus.Accepted)
114 {
115 var removed = 0;
116 var tree_squares = area.squares.Where((square) => simulation.map.cells[(int)square.X][(int)square.Y].hasTree);
117 var to_remove = -delta.deltaTrees.Value;
131 if (delta.deltaTrees.Value < 0)
132 {
133 var squares = HasComponent<AreaComponent>(entity) ? GetComponent<AreaComponent>(entity).squares : this.all_squares;
134 var removed = 0;
135 var tree_squares = squares.Where((square) => simulation.map.cells[(int)square.X][(int)square.Y].hasTree);
136 var to_remove = -delta.deltaTrees.Value;
118 137
119 //calculate the probability in order to get the expected number of removed trees
120 var expected = to_remove;
121 var trials = tree_squares.Count();
122 double probability = ((double)expected / (double)trials) / 12;
138 //calculate the probability in order to get the expected number of removed trees
139 var expected = to_remove;
140 var trials = tree_squares.Count();
141 double probability = ((double)expected / (double)trials) / 12;
123 142
124 foreach (var square in tree_squares)
125 {
126 var cell = simulation.map.cells[(int)square.X][(int)square.Y];
127 if (cell.hasTree
128 && random_generator.NextDouble() < probability)
129 {
130 cell.removeTree();
131 removed++;
132 }
133 if (removed >= to_remove)
134 {
135 // break;
136 }
137 }
138 }
139 }
140 }
141 this.ticksToSend = 0;
143 foreach (var square in tree_squares)
144 {
145 var cell = simulation.map.cells[(int)square.X][(int)square.Y];
146 if (cell.hasTree
147 && random_generator.NextDouble() < probability)
148 {
149 cell.removeTree();
150 removed++;
151 }
152 if (removed >= to_remove)
153 {
154 // break;
155 }
156 }
157 Logging.Info(String.Format("Destroyed {0} trees, expected {1}, P(destroy)= {2}", removed, (expected / 12), probability));
158 }
159 else
160 {
161 }
162 }
142 163
143 simulation.contracts = new_contract_amount;
144 simulation.enforcement = new_enforcement_amount;
164 }
165 }
166 this.ticksToSend = 0;
145 167
146 }
168 simulation.contracts = new_contract_amount;
169 simulation.enforcement = new_enforcement_amount;
170
171 }
147 172
148 173 }
149 174 }
You need to be logged in to leave comments. Login now