|
1 |
| -// pub fn show_wonders(game: &Game, player: &ShownPlayer, ui: &mut Ui) { |
2 |
| -//todo move to cards ui |
3 |
| -// let player = game.get_player(player.index); |
4 |
| -// let y = 5.; |
5 |
| -// |
6 |
| -// for (i, card) in player.wonder_cards.iter().enumerate() { |
7 |
| -// let req = match card.required_advances[..] { |
8 |
| -// [] => String::from("no advances"), |
9 |
| -// _ => card.required_advances.join(", "), |
10 |
| -// }; |
11 |
| -// ui.label( |
12 |
| -// vec2(900. + i as f32 * 30.0, y), |
13 |
| -// &format!( |
14 |
| -// "Wonder Card {} cost {} requires {}", |
15 |
| -// &card.name, card.cost, req |
16 |
| -// ), |
17 |
| -// ); |
18 |
| -// } |
19 |
| -// } |
| 1 | +use crate::client_state::{ActiveDialog, StateUpdate}; |
| 2 | +use crate::custom_phase_ui::MultiSelection; |
| 3 | +use crate::dialog_ui::ok_button; |
| 4 | +use crate::layout_ui::{bottom_centered_text, left_mouse_button_pressed_in_rect}; |
| 5 | +use crate::render_context::RenderContext; |
| 6 | +use crate::select_ui::HighlightType; |
| 7 | +use crate::tooltip::show_tooltip_for_rect; |
| 8 | +use macroquad::color::BLACK; |
| 9 | +use macroquad::math::{vec2, Rect}; |
| 10 | +use macroquad::prelude::{draw_rectangle, draw_rectangle_lines, Color, GREEN, RED, YELLOW}; |
| 11 | +use server::action::Action; |
| 12 | +use server::card::{hand_cards, HandCard, HandCardType}; |
| 13 | +use server::content::action_cards::get_action_card; |
| 14 | +use server::content::custom_phase_actions::CurrentEventResponse; |
| 15 | +use server::content::wonders::get_wonder; |
| 16 | +use server::player::Player; |
| 17 | +use server::playing_actions::PlayingAction; |
| 18 | +use server::tactics_card::CombatRole; |
| 19 | +use server::wonder::Wonder; |
| 20 | + |
| 21 | +pub struct HandCardObject { |
| 22 | + id: HandCard, |
| 23 | + name: String, |
| 24 | + description: Vec<String>, |
| 25 | + color: Color, |
| 26 | +} |
| 27 | + |
| 28 | +impl HandCardObject { |
| 29 | + pub fn new(id: HandCard, color: Color, name: String, description: Vec<String>) -> Self { |
| 30 | + Self { |
| 31 | + id, |
| 32 | + name, |
| 33 | + description, |
| 34 | + color, |
| 35 | + } |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +#[must_use] |
| 40 | +pub fn wonder_cards(player: &Player) -> Vec<Wonder> { |
| 41 | + player.wonder_cards.iter().map(|n| get_wonder(n)).collect() |
| 42 | +} |
| 43 | + |
| 44 | +const ACTION_CARD_COLOR: Color = RED; |
| 45 | +const WONDER_CARD_COLOR: Color = YELLOW; |
| 46 | + |
| 47 | +pub(crate) fn show_cards(rc: &RenderContext) -> StateUpdate { |
| 48 | + let p = rc.shown_player; |
| 49 | + let cards = hand_cards(p, &HandCardType::get_all()); |
| 50 | + let size = vec2(180., 30.); |
| 51 | + |
| 52 | + let selection = if let ActiveDialog::HandCardsRequest(r) = &rc.state.active_dialog { |
| 53 | + Some(r) |
| 54 | + } else { |
| 55 | + None |
| 56 | + }; |
| 57 | + |
| 58 | + for pass in 0..2 { |
| 59 | + let mut y = (cards.len() as f32 * -size.y) / 2.; |
| 60 | + for card in &cards { |
| 61 | + let screen = rc.state.screen_size; |
| 62 | + let pos = vec2(screen.x, screen.y / 2.0) + vec2(-size.x, y); |
| 63 | + |
| 64 | + let c = get_card_object(card); |
| 65 | + |
| 66 | + if pass == 0 { |
| 67 | + draw_rectangle(pos.x, pos.y, size.x, size.y, c.color); |
| 68 | + let (thickness, border) = highlight(&c, selection); |
| 69 | + draw_rectangle_lines(pos.x, pos.y, size.x, size.y, thickness, border); |
| 70 | + |
| 71 | + rc.state.draw_text(&c.name, pos.x + 10., pos.y + 22.); |
| 72 | + } else { |
| 73 | + let rect = Rect::new(pos.x, pos.y, size.x, size.y); |
| 74 | + |
| 75 | + // tooltip should be shown on top of everything |
| 76 | + show_tooltip_for_rect(rc, &c.description, rect); |
| 77 | + |
| 78 | + if left_mouse_button_pressed_in_rect(rect, rc) { |
| 79 | + if let Some(s) = selection { |
| 80 | + return StateUpdate::OpenDialog(ActiveDialog::HandCardsRequest( |
| 81 | + s.clone().toggle(c.id), |
| 82 | + )); |
| 83 | + } |
| 84 | + if can_play_card(rc, card) { |
| 85 | + return play_card(card); |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + y += size.y; |
| 91 | + } |
| 92 | + } |
| 93 | + StateUpdate::None |
| 94 | +} |
| 95 | + |
| 96 | +fn can_play_card(rc: &RenderContext, card: &HandCard) -> bool { |
| 97 | + if rc.can_control_shown_player() && rc.is_playing() { |
| 98 | + if let HandCard::ActionCard(id) = card { |
| 99 | + return (get_action_card(*id).civil_card.can_play)(rc.game, rc.shown_player); |
| 100 | + } |
| 101 | + } |
| 102 | + false |
| 103 | +} |
| 104 | + |
| 105 | +fn play_card(card: &HandCard) -> StateUpdate { |
| 106 | + match card { |
| 107 | + HandCard::ActionCard(a) => StateUpdate::execute_with_warning( |
| 108 | + Action::Playing(PlayingAction::ActionCard(*a)), |
| 109 | + vec![], |
| 110 | + ), |
| 111 | + HandCard::Wonder(_) => panic!("wonders are played in the construct menu"), |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +fn highlight(c: &HandCardObject, selection: Option<&MultiSelection<HandCard>>) -> (f32, Color) { |
| 116 | + if let Some(s) = selection { |
| 117 | + if s.selected.contains(&c.id) { |
| 118 | + return (8.0, GREEN); |
| 119 | + } |
| 120 | + if s.request.choices.contains(&c.id) { |
| 121 | + return (8.0, HighlightType::Choices.color()); |
| 122 | + } |
| 123 | + } |
| 124 | + (2.0, BLACK) |
| 125 | +} |
| 126 | + |
| 127 | +fn get_card_object(card: &HandCard) -> HandCardObject { |
| 128 | + match card { |
| 129 | + HandCard::ActionCard(a) if *a == 0 => HandCardObject::new( |
| 130 | + card.clone(), |
| 131 | + ACTION_CARD_COLOR, |
| 132 | + "Action Card".to_string(), |
| 133 | + vec!["Hidden Action Card".to_string()], |
| 134 | + ), |
| 135 | + HandCard::ActionCard(id) => { |
| 136 | + let a = get_action_card(*id); |
| 137 | + HandCardObject::new( |
| 138 | + card.clone(), |
| 139 | + ACTION_CARD_COLOR, |
| 140 | + a.civil_card.name.clone(), |
| 141 | + vec![ |
| 142 | + a.civil_card.description.clone(), |
| 143 | + format!("Tactics: {}", a.tactics_card.name), |
| 144 | + format!("Unit Type: {:?}", a.tactics_card.fighter_requirement), |
| 145 | + format!( |
| 146 | + "Role: {:?}", |
| 147 | + match a.tactics_card.role_requirement { |
| 148 | + None => "None".to_string(), |
| 149 | + Some(r) => match r { |
| 150 | + CombatRole::Attacker => "Attacker".to_string(), |
| 151 | + CombatRole::Defender => "Defender".to_string(), |
| 152 | + }, |
| 153 | + } |
| 154 | + ), |
| 155 | + a.tactics_card.description.clone(), |
| 156 | + ], |
| 157 | + ) |
| 158 | + } |
| 159 | + HandCard::Wonder(n) if n.is_empty() => HandCardObject::new( |
| 160 | + card.clone(), |
| 161 | + WONDER_CARD_COLOR, |
| 162 | + "Wonder Card".to_string(), |
| 163 | + vec!["Hidden Wonder Card".to_string()], |
| 164 | + ), |
| 165 | + HandCard::Wonder(name) => { |
| 166 | + let w = get_wonder(name); |
| 167 | + HandCardObject::new( |
| 168 | + card.clone(), |
| 169 | + WONDER_CARD_COLOR, |
| 170 | + w.name.clone(), |
| 171 | + vec![ |
| 172 | + w.description.clone(), |
| 173 | + format!("Cost: {}", w.cost.to_string()), |
| 174 | + format!("Required advances: {}", w.required_advances.join(", ")), |
| 175 | + ], |
| 176 | + ) |
| 177 | + } |
| 178 | + } |
| 179 | +} |
| 180 | + |
| 181 | +pub fn select_cards_dialog(rc: &RenderContext, s: &MultiSelection<HandCard>) -> StateUpdate { |
| 182 | + bottom_centered_text( |
| 183 | + rc, |
| 184 | + format!( |
| 185 | + "{}: {} cards selected", |
| 186 | + s.request.description, |
| 187 | + s.selected.len() |
| 188 | + ) |
| 189 | + .as_str(), |
| 190 | + ); |
| 191 | + |
| 192 | + if ok_button( |
| 193 | + rc, |
| 194 | + crate::custom_phase_ui::multi_select_tooltip(s, s.request.is_valid(&s.selected), "cards"), |
| 195 | + ) { |
| 196 | + StateUpdate::response(CurrentEventResponse::SelectHandCards(s.selected.clone())) |
| 197 | + } else { |
| 198 | + StateUpdate::None |
| 199 | + } |
| 200 | +} |
0 commit comments