1
+ use crate :: client_state:: { ActiveDialog , ShownPlayer , StateUpdate } ;
2
+ use crate :: dialog_ui:: dialog;
3
+ use crate :: payment_ui:: { payment_dialog, HasPayment , Payment , ResourcePayment } ;
4
+ use crate :: resource_ui:: { new_resource_map, ResourceType } ;
5
+ use crate :: select_ui:: HasCountSelectableObject ;
1
6
use itertools:: Itertools ;
2
7
use macroquad:: hash;
3
- use macroquad:: math:: { bool, vec2} ;
4
- use std:: cmp:: min;
5
- use std:: collections:: HashMap ;
6
-
8
+ use macroquad:: math:: { bool, vec2, Vec2 } ;
9
+ use macroquad:: ui:: widgets:: Checkbox ;
7
10
use server:: action:: Action ;
8
11
use server:: advance:: { Advance , Bonus } ;
9
12
use server:: content:: advances;
@@ -13,12 +16,8 @@ use server::player::Player;
13
16
use server:: playing_actions:: PlayingAction ;
14
17
use server:: resource_pile:: AdvancePaymentOptions ;
15
18
use server:: status_phase:: { StatusPhaseAction , StatusPhaseState } ;
16
-
17
- use crate :: client_state:: { ActiveDialog , ShownPlayer , StateUpdate } ;
18
- use crate :: dialog_ui:: dialog;
19
- use crate :: payment_ui:: { payment_dialog, HasPayment , Payment , ResourcePayment } ;
20
- use crate :: resource_ui:: { new_resource_map, ResourceType } ;
21
- use crate :: select_ui:: HasCountSelectableObject ;
19
+ use std:: cmp:: min;
20
+ use std:: collections:: HashMap ;
22
21
23
22
#[ derive( Clone ) ]
24
23
pub struct AdvancePayment {
@@ -80,83 +79,120 @@ impl HasPayment for AdvancePayment {
80
79
}
81
80
82
81
pub fn show_advance_menu ( game : & Game , player : & ShownPlayer ) -> StateUpdate {
83
- show_generic_advance_menu ( "Advances" , game, player, |name | {
82
+ show_generic_advance_menu ( "Advances" , game, player, |a | {
84
83
StateUpdate :: SetDialog ( ActiveDialog :: AdvancePayment ( AdvancePayment :: new (
85
84
game,
86
85
player. index ,
87
- name,
86
+ a . name . as_str ( ) ,
88
87
) ) )
89
88
} )
90
89
}
91
90
92
91
pub fn show_free_advance_menu ( game : & Game , player : & ShownPlayer ) -> StateUpdate {
93
- show_generic_advance_menu ( "Select a free advance" , game, player, |name| {
94
- StateUpdate :: status_phase ( StatusPhaseAction :: FreeAdvance ( name. to_string ( ) ) )
92
+ show_generic_advance_menu ( "Select a free advance" , game, player, |a| {
93
+ if can_advance ( game, player, a) {
94
+ return StateUpdate :: execute_with_confirm (
95
+ description ( game. get_player ( player. index ) , a) ,
96
+ Action :: StatusPhase ( StatusPhaseAction :: FreeAdvance ( a. name . clone ( ) ) ) ,
97
+ ) ;
98
+ }
99
+ advance_info ( game, player, a)
95
100
} )
96
101
}
97
102
103
+ fn advance_info ( game : & Game , player : & ShownPlayer , a : & Advance ) -> StateUpdate {
104
+ StateUpdate :: execute_with_cancel ( description ( game. get_player ( player. index ) , a) )
105
+ }
106
+
98
107
pub fn show_generic_advance_menu (
99
108
title : & str ,
100
109
game : & Game ,
101
110
player : & ShownPlayer ,
102
- new_update : impl Fn ( & str ) -> StateUpdate ,
111
+ new_update : impl Fn ( & Advance ) -> StateUpdate ,
103
112
) -> StateUpdate {
104
113
dialog ( player, title, |ui| {
105
114
let p = player. get ( game) ;
106
- let mut update = StateUpdate :: None ;
107
- let mut current_group = None ;
108
- for ( _a, list) in & advances:: get_all ( ) . iter ( ) . chunk_by ( |a| {
109
- if a. required . is_none ( ) {
110
- current_group = Some ( & a. name ) ;
111
- & a. name
112
- } else {
113
- current_group. unwrap ( )
114
- }
115
- } ) {
116
- let advances = list. collect :: < Vec < _ > > ( ) ;
117
- ui. group ( hash ! ( & advances[ 0 ] . name) , vec2 ( 1500. , 90. ) , |ui| {
118
- for a in advances {
119
- let name = & a. name ;
120
- let can_advance = if player. can_play_action {
121
- p. can_advance ( name)
122
- } else if player. can_control
123
- && matches ! (
124
- game. state,
125
- GameState :: StatusPhase ( StatusPhaseState :: FreeAdvance )
126
- )
127
- {
128
- p. can_advance_free ( name)
129
- } else {
130
- false
131
- } ;
132
-
133
- let desc = description ( p, a) ;
134
- if p. has_advance ( name) {
135
- ui. label ( None , & desc) ;
136
- } else if can_advance {
137
- if ui. button ( None , desc) {
138
- update = new_update ( name) ;
139
- }
140
- } else {
141
- ui. label ( None , & desc) ;
142
- } ;
115
+
116
+ for advances in groups ( ) {
117
+ let pos = group_pos ( & advances[ 0 ] ) ;
118
+ for ( i, a) in advances. into_iter ( ) . enumerate ( ) {
119
+ let pos = pos * vec2 ( 140. , 210. ) + vec2 ( 0. , i as f32 * 35. ) ;
120
+ let name = & a. name ;
121
+ let can_advance = can_advance ( game, player, & a) ;
122
+
123
+ if can_advance || p. has_advance ( name) {
124
+ let mut data = p. has_advance ( name) ;
125
+ Checkbox :: new ( hash ! ( name) )
126
+ // .label(name)
127
+ . pos ( pos + vec2 ( 60. , 50. ) )
128
+ . size ( vec2 ( 0. , 0. ) )
129
+ . ui ( ui, & mut data) ;
130
+ if data != p. has_advance ( name) {
131
+ return new_update ( & a) ;
132
+ }
143
133
}
144
- } ) ;
134
+ // Button::new(name.clone()).position(pos + vec2(0., 0.)).ui(ui);
135
+ ui. label ( pos + vec2 ( 0. , 0. ) , name) ;
136
+ }
145
137
}
146
- update
138
+ StateUpdate :: None
147
139
} )
148
140
}
149
141
150
- fn description ( p : & Player , a : & Advance ) -> String {
142
+ fn can_advance ( game : & Game , player : & ShownPlayer , a : & Advance ) -> bool {
143
+ let name = & a. name ;
144
+ let p = player. get ( game) ;
145
+ if player. can_play_action {
146
+ p. can_advance ( name)
147
+ } else if player. can_control
148
+ && matches ! (
149
+ game. state,
150
+ GameState :: StatusPhase ( StatusPhaseState :: FreeAdvance )
151
+ )
152
+ {
153
+ p. can_advance_free ( name)
154
+ } else {
155
+ false
156
+ }
157
+ }
158
+
159
+ fn groups ( ) -> Vec < Vec < Advance > > {
160
+ let mut current_group = None ;
161
+ advances:: get_all ( )
162
+ . into_iter ( )
163
+ . chunk_by ( |a| {
164
+ if a. required . is_none ( ) {
165
+ current_group = Some ( a. name . clone ( ) ) ;
166
+ a. name . clone ( )
167
+ } else {
168
+ current_group. as_ref ( ) . unwrap ( ) . clone ( )
169
+ }
170
+ } )
171
+ . into_iter ( )
172
+ . map ( |( _k, a) | a. collect :: < Vec < _ > > ( ) )
173
+ . collect :: < Vec < _ > > ( )
174
+ }
175
+
176
+ fn group_pos ( advance : & Advance ) -> Vec2 {
177
+ match advance. name . as_str ( ) {
178
+ "Farming" => vec2 ( 0. , 0. ) ,
179
+ "Mining" => vec2 ( 1. , 0. ) ,
180
+ "Fishing" => vec2 ( 2. , 0. ) ,
181
+ "Philosophy" => vec2 ( 3. , 0. ) ,
182
+ "Tactics" => vec2 ( 4. , 0. ) ,
183
+ "Math" => vec2 ( 2. , 1. ) ,
184
+ "Voting" => vec2 ( 3. , 1. ) ,
185
+ "Dogma" => vec2 ( 5. , 1. ) ,
186
+ _ => panic ! ( "Unknown advance: {}" , advance. name) ,
187
+ }
188
+ }
189
+
190
+ fn description ( p : & Player , a : & Advance ) -> Vec < String > {
151
191
let name = & a. name ;
152
192
let desc = & a. description ;
153
193
154
- let mut parts = vec ! [ ] ;
155
- parts. push ( if p. has_advance ( name) {
156
- format ! ( "+ {name}" )
157
- } else {
158
- format ! ( " {name}" )
159
- } ) ;
194
+ let mut parts: Vec < String > = vec ! [ ] ;
195
+ parts. push ( name. clone ( ) ) ;
160
196
parts. push ( desc. clone ( ) ) ;
161
197
parts. push ( format ! ( "Cost: {}" , p. advance_cost( name) ) ) ;
162
198
if let Some ( r) = & a. required {
@@ -181,25 +217,32 @@ fn description(p: &Player, a: &Advance) -> String {
181
217
parts. push ( format ! ( "Unlocks: {u}" ) ) ;
182
218
}
183
219
184
- parts. join ( ", " )
220
+ parts
185
221
}
186
222
187
- pub fn pay_advance_dialog ( ap : & AdvancePayment , player : & ShownPlayer ) -> StateUpdate {
188
- payment_dialog (
189
- player,
190
- & format ! ( "Pay for advance {}" , ap. name) ,
191
- ap,
192
- AdvancePayment :: valid,
193
- |ap| {
194
- StateUpdate :: Execute ( Action :: Playing ( PlayingAction :: Advance {
195
- advance : ap. name . to_string ( ) ,
196
- payment : ap. payment . to_resource_pile ( ) ,
197
- } ) )
198
- } ,
199
- |ap, r| ap. payment . get ( r) . selectable . max > 0 ,
200
- |ap, r| add ( ap, r, 1 ) ,
201
- |ap, r| add ( ap, r, -1 ) ,
202
- )
223
+ pub fn pay_advance_dialog ( ap : & AdvancePayment , player : & ShownPlayer , game : & Game ) -> StateUpdate {
224
+ let a = advances:: get_advance_by_name ( ap. name . as_str ( ) ) . unwrap ( ) ;
225
+
226
+ if can_advance ( game, player, & a) {
227
+ payment_dialog (
228
+ player,
229
+ & format ! ( "Pay for advance {}" , ap. name) ,
230
+ description ( game. get_player ( player. index ) , & a) ,
231
+ ap,
232
+ AdvancePayment :: valid,
233
+ |ap| {
234
+ StateUpdate :: Execute ( Action :: Playing ( PlayingAction :: Advance {
235
+ advance : ap. name . to_string ( ) ,
236
+ payment : ap. payment . to_resource_pile ( ) ,
237
+ } ) )
238
+ } ,
239
+ |ap, r| ap. payment . get ( r) . selectable . max > 0 ,
240
+ |ap, r| add ( ap, r, 1 ) ,
241
+ |ap, r| add ( ap, r, -1 ) ,
242
+ )
243
+ } else {
244
+ advance_info ( game, player, & a)
245
+ }
203
246
}
204
247
205
248
fn add ( ap : & AdvancePayment , r : ResourceType , i : i32 ) -> StateUpdate {
0 commit comments