Skip to content

Commit b03a007

Browse files
authored
Maya (#142)
1 parent 51c619c commit b03a007

23 files changed

+1187
-118
lines changed

client/src/assets.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,17 @@ impl Assets {
8989
}
9090

9191
fn wonders() -> HashMap<String, Texture2D> {
92-
[(
93-
"Pyramids".to_string(),
94-
load_png(include_bytes!("../assets/pyramid-svgrepo-com.png")),
95-
)]
92+
[
93+
(
94+
"Pyramids".to_string(),
95+
load_png(include_bytes!("../assets/pyramid-svgrepo-com.png")),
96+
),
97+
(
98+
"Great Gardens".to_string(),
99+
// todo find a better icon
100+
load_png(include_bytes!("../assets/pyramid-svgrepo-com.png")),
101+
),
102+
]
96103
.iter()
97104
.cloned()
98105
.collect()

client/src/collect_ui.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use crate::dialog_ui::{
77
};
88
use crate::hex_ui;
99
use crate::hex_ui::Point;
10-
use crate::layout_ui::{
11-
draw_icon, draw_scaled_icon, is_in_circle, left_mouse_button_pressed, ICON_SIZE,
12-
};
10+
use crate::layout_ui::{draw_scaled_icon, is_in_circle, left_mouse_button_pressed};
1311
use crate::render_context::RenderContext;
1412
use crate::resource_ui::{new_resource_map, resource_name, show_resource_pile};
1513
use macroquad::color::BLACK;
@@ -150,19 +148,23 @@ pub fn draw_resource_collect_tile(rc: &RenderContext, pos: Position) -> StateUpd
150148

151149
let c = hex_ui::center(pos);
152150
for (i, pile) in possible.iter().enumerate() {
153-
let center = if possible.len() == 1 {
154-
c
155-
} else {
156-
hex_ui::rotate_around(c, 30.0, 90 * i)
151+
let deg = (360. / possible.len() as f32) as usize * i;
152+
let (center, radius) = match possible.len() {
153+
1 => (c, 20.),
154+
2 => (hex_ui::rotate_around(c, 30.0, deg), 20.),
155+
n if n <= 4 => (hex_ui::rotate_around(c, 30.0, deg), 20.),
156+
_ => (hex_ui::rotate_around(c, 30.0, deg), 10.),
157157
};
158+
let size = radius * 1.3;
159+
158160
let color = if col.is_some_and(|r| r == pile) {
159161
BLACK
160162
} else {
161163
WHITE
162164
};
163-
draw_circle(center.x, center.y, 20., color);
165+
draw_circle(center.x, center.y, radius, color);
164166
if let Some(p) = left_mouse_button_pressed(rc) {
165-
if is_in_circle(p, center, 20.) {
167+
if is_in_circle(p, center, radius) {
166168
return click_collect_option(rc, collect, pos, pile);
167169
}
168170
}
@@ -175,32 +177,37 @@ pub fn draw_resource_collect_tile(rc: &RenderContext, pos: Position) -> StateUpd
175177
a.is_some_and(|a| *a > 0).then(|| (*r, a.unwrap()))
176178
})
177179
.collect();
178-
draw_collect_item(rc, center, &m);
180+
draw_collect_item(rc, center, &m, size);
179181
}
180182
}
181183
};
182184
StateUpdate::None
183185
}
184186

185-
fn draw_collect_item(rc: &RenderContext, center: Point, resources: &[(ResourceType, &u32)]) {
187+
fn draw_collect_item(
188+
rc: &RenderContext,
189+
center: Point,
190+
resources: &[(ResourceType, &u32)],
191+
size: f32,
192+
) {
186193
if resources.iter().len() == 1 {
187194
let (r, _) = resources.first().unwrap();
188-
draw_icon(
195+
draw_scaled_icon(
189196
rc,
190197
&rc.assets().resources[r],
191198
resource_name(*r),
192-
center.to_vec2() - vec2(ICON_SIZE / 2., ICON_SIZE / 2.),
199+
center.to_vec2() - vec2(size / 2., size / 2.),
200+
size,
193201
);
194202
} else {
195203
resources.iter().enumerate().for_each(|(j, (r, _))| {
196-
let size = ICON_SIZE / 2.;
197204
let c = hex_ui::rotate_around(center, 10.0, 180 * j);
198205
draw_scaled_icon(
199206
rc,
200207
&rc.assets().resources[r],
201208
resource_name(*r),
202209
c.to_vec2() - vec2(size / 2., size / 2.),
203-
size,
210+
size / 2.,
204211
);
205212
});
206213
}

client/src/local_client/bin/main.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,13 @@ pub fn setup_local_game() -> Game {
155155
// .unwrap()
156156
// .pieces
157157
// .wonders = vec![game.wonders_left.pop().unwrap()];
158-
game.players[player_index1]
159-
.wonder_cards
160-
.push(game.wonders_left.pop().unwrap());
158+
let gardens = game.wonders_left.remove(
159+
game.wonders_left
160+
.iter()
161+
.position(|w| w.name == "Great Gardens")
162+
.unwrap(),
163+
);
164+
game.players[player_index1].wonder_cards.push(gardens);
161165
game.players[player_index1]
162166
.get_city_mut(Position::from_offset("C2"))
163167
.unwrap()
@@ -242,6 +246,9 @@ pub fn setup_local_game() -> Game {
242246

243247
game.advance("Voting", player_index1);
244248
game.advance("Free Economy", player_index1);
249+
game.advance("Storage", player_index1);
250+
game.players[player_index1].gain_resources(ResourcePile::food(5));
251+
245252
game
246253
}
247254

server/src/combat.rs

+55-52
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::action::{CombatAction, PlayActionCard};
22
use crate::combat::CombatModifier::{
33
CancelFortressExtraDie, SteelWeaponsAttacker, SteelWeaponsDefender,
44
};
5-
use crate::content::advances::STEEL_WEAPONS;
65
use crate::content::custom_phase_actions::{start_siegecraft_phase, start_steel_weapons_phase};
76
use crate::game::GameState::Playing;
87
use crate::game::{Game, GameState};
@@ -13,6 +12,30 @@ use itertools::Itertools;
1312
use serde::{Deserialize, Serialize};
1413
use std::mem;
1514

15+
#[derive(Clone, PartialEq)]
16+
pub struct CombatStrength {
17+
pub attacker: bool,
18+
pub player_index: usize,
19+
pub extra_dies: u8,
20+
pub extra_combat_value: u8,
21+
pub hit_cancels: u8,
22+
pub roll_log: Vec<String>,
23+
}
24+
25+
impl CombatStrength {
26+
#[must_use]
27+
pub fn new(player_index: usize, attacker: bool) -> Self {
28+
Self {
29+
player_index,
30+
attacker,
31+
extra_dies: 0,
32+
extra_combat_value: 0,
33+
hit_cancels: 0,
34+
roll_log: vec![],
35+
}
36+
}
37+
}
38+
1639
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1740
pub enum CombatPhase {
1841
PlayActionCard(usize),
@@ -259,90 +282,70 @@ fn remove_casualties(game: &mut Game, c: &mut Combat, units: Vec<u32>) -> Combat
259282
resolve_combat(game, c)
260283
}
261284

285+
///
286+
/// # Panics
287+
/// Panics if events are not set
262288
pub fn combat_loop(game: &mut Game, mut c: Combat) {
263289
loop {
264290
game.add_info_log_item(format!("\nCombat round {}", c.round));
265291
//todo: go into tactics phase if either player has tactics card (also if they can not play it unless otherwise specified via setting)
266292

267-
let steel_weapon_value = if game.get_player(c.attacker).has_advance(STEEL_WEAPONS)
268-
&& game.get_player(c.defender).has_advance(STEEL_WEAPONS)
269-
{
270-
1
271-
} else {
272-
2
273-
};
274-
let mut steel_weapon_log = vec![];
275293
let attacker_name = game.players[c.attacker].get_name();
276294
let active_attackers = c.active_attackers(game);
277-
let attacker_extra = if c.modifiers.contains(&SteelWeaponsAttacker) {
278-
steel_weapon_log.push(format!(
279-
"Attacker used steel weapons to add {steel_weapon_value} to their combat value"
280-
));
281-
steel_weapon_value
282-
} else {
283-
0
284-
};
295+
let mut attacker_strength = CombatStrength::new(c.attacker, true);
296+
game.players[c.attacker]
297+
.events
298+
.as_ref()
299+
.expect("events should be set")
300+
.on_combat_round
301+
.trigger(&mut attacker_strength, &c, game);
285302
let mut attacker_log = vec![];
286303
let attacker_rolls = roll(
287304
game,
288305
c.attacker,
289306
&active_attackers,
290-
0,
291-
attacker_extra,
307+
attacker_strength.extra_dies,
308+
attacker_strength.extra_combat_value,
292309
&mut attacker_log,
293310
);
294311
let attacker_log_str = roll_log_str(&attacker_log);
295312

296313
let active_defenders = active_defenders(game, c.defender, c.defender_position);
297314
let defender_name = game.players[c.defender].get_name();
298315
let mut defender_log = vec![];
299-
let mut fortress_log = vec![];
300-
let extra_defender_dies =
301-
if c.defender_fortress(game) && !c.modifiers.contains(&CancelFortressExtraDie) {
302-
fortress_log.push("added one extra die");
303-
1
304-
} else {
305-
0
306-
};
307-
let defender_extra = if c.modifiers.contains(&SteelWeaponsDefender) {
308-
steel_weapon_log.push(format!(
309-
"Defender used steel weapons to add {steel_weapon_value} to their combat value"
310-
));
311-
steel_weapon_value
312-
} else {
313-
0
314-
};
316+
let mut defender_strength = CombatStrength::new(c.defender, false);
317+
game.players[c.defender]
318+
.events
319+
.as_ref()
320+
.expect("events should be set")
321+
.on_combat_round
322+
.trigger(&mut defender_strength, &c, game);
315323
let defender_rolls = roll(
316324
game,
317325
c.defender,
318326
&active_defenders,
319-
extra_defender_dies,
320-
defender_extra,
327+
defender_strength.extra_dies,
328+
defender_strength.extra_combat_value,
321329
&mut defender_log,
322330
);
323331
let defender_log_str = roll_log_str(&defender_log);
324332
let attacker_combat_value = attacker_rolls.combat_value;
325-
let attacker_hit_cancels = attacker_rolls.hit_cancels;
333+
let attacker_hit_cancels = attacker_rolls.hit_cancels + attacker_strength.hit_cancels;
326334
let defender_combat_value = defender_rolls.combat_value;
327-
let mut defender_hit_cancels = defender_rolls.hit_cancels;
328-
if c.defender_fortress(game)
329-
&& !c
330-
.modifiers
331-
.contains(&CombatModifier::CancelFortressIgnoreHit)
332-
{
333-
defender_hit_cancels += 1;
334-
fortress_log.push("cancelled one hit");
335-
}
335+
let defender_hit_cancels = defender_rolls.hit_cancels + defender_strength.hit_cancels;
336336
let attacker_hits = (attacker_combat_value / 5).saturating_sub(defender_hit_cancels);
337337
let defender_hits = (defender_combat_value / 5).saturating_sub(attacker_hit_cancels);
338338
game.add_info_log_item(format!("\t{attacker_name} rolled {attacker_log_str} for combined combat value of {attacker_combat_value} and gets {attacker_hits} hits against defending units. {defender_name} rolled {defender_log_str} for combined combat value of {defender_combat_value} and gets {defender_hits} hits against attacking units."));
339-
if !steel_weapon_log.is_empty() {
340-
game.add_info_log_item(steel_weapon_log.join(", "));
339+
if !attacker_strength.roll_log.is_empty() {
340+
game.add_info_log_item(format!(
341+
". {attacker_name} used the following combat modifiers: {}",
342+
attacker_strength.roll_log.join(", ")
343+
));
341344
}
342-
if !fortress_log.is_empty() {
345+
if !defender_strength.roll_log.is_empty() {
343346
game.add_info_log_item(format!(
344-
" {defender_name} has a fortress, which {}",
345-
fortress_log.join(", ")
347+
". {defender_name} used the following combat modifiers: {}",
348+
defender_strength.roll_log.join(", ")
346349
));
347350
}
348351
if attacker_hits < active_defenders.len() as u8 && attacker_hits > 0 {

0 commit comments

Comments
 (0)