Skip to content

Commit

Permalink
Merge pull request #5 from SnowdenWintermute/feature
Browse files Browse the repository at this point in the history
0.3.0
  • Loading branch information
SnowdenWintermute authored Jan 26, 2024
2 parents 5f8a47a + d7ea856 commit a888a92
Show file tree
Hide file tree
Showing 28 changed files with 327 additions and 68 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Roguelike Racing

A multiplayer turn based game in the spirit of For the King, Diablo and Final Fantasy.
Live at [label](https://roguelikeracing.com)

UI written with the Yew frontend framework, backend uses websockets via Actix.

Expand Down
24 changes: 12 additions & 12 deletions client/cypress/e2e/test.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ describe("a test test", () => {
cy.findByRole("button", { name: "Create Character" }).focus();
cy.findByRole("button", { name: "Create Character" }).click();

cy.findByPlaceholderText("Character name...")
.click()
.clear()
.type("character 2", { delay: 0 });
cy.findByRole("button", { name: "Create Character" }).focus();
cy.findByRole("button", { name: "Create Character" }).click();
// cy.findByPlaceholderText("Character name...")
// .click()
// .clear()
// .type("Rebecca Chambers", { delay: 0 });
// cy.findByRole("button", { name: "Create Character" }).focus();
// cy.findByRole("button", { name: "Create Character" }).click();

cy.findByPlaceholderText("Character name...")
.click()
.clear()
.type("character 3", { delay: 0 });
cy.findByRole("button", { name: "Create Character" }).focus();
cy.findByRole("button", { name: "Create Character" }).click();
// cy.findByPlaceholderText("Character name...")
// .click()
// .clear()
// .type("character 3", { delay: 0 });
// cy.findByRole("button", { name: "Create Character" }).focus();
// cy.findByRole("button", { name: "Create Character" }).click();

cy.findByRole("button", { name: "Ready" }).click();
// cy.findByText("Open Inventory").click();
Expand Down
8 changes: 4 additions & 4 deletions client/dist/index.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>Roguelike Racing</title>
<link rel="stylesheet" href="/output-24b437c61eec847e.css">
<link rel="stylesheet" href="/output-c24bce4d664576cf.css">

<base href="/">

<link rel="preload" href="/roguelike-racing-client-471b113b9deca254_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/roguelike-racing-client-471b113b9deca254.js"></head>
<link rel="preload" href="/roguelike-racing-client-a1f8a7222ed7da46_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/roguelike-racing-client-a1f8a7222ed7da46.js"></head>
<body>

<script type="module">import init from '/roguelike-racing-client-471b113b9deca254.js';init('/roguelike-racing-client-471b113b9deca254_bg.wasm');</script><script>(function () {
<script type="module">import init from '/roguelike-racing-client-a1f8a7222ed7da46.js';init('/roguelike-racing-client-a1f8a7222ed7da46_bg.wasm');</script><script>(function () {
var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
var url = protocol + '//' + window.location.host + '/_trunk/ws';
var poll_interval = 5000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,6 @@ pub fn create_action_button_click_handler<'a>(
&websocket_state.websocket,
PlayerInputs::UseSelectedAbility(game_state.focused_character_id),
);

send_client_input(
&websocket_state.websocket,
PlayerInputs::SelectAbility(ClientSelectAbilityPacket {
character_id: focused_character_id,
ability_name_option: None,
}),
)
});
}),
GameActions::DropItem(item_id) => Box::new(move || {
Expand Down
16 changes: 14 additions & 2 deletions client/src/components/game/character_autofocus_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ pub fn character_autofocus_manager() -> Html {
});
// if battle ended, focus first owned character
let _ = (|| -> Result<(), AppError> {
let party = game_state.get_current_party()?;
let character_positions = party.character_positions.clone();
if current_battle_id.is_none()
&& prev_current_battle_id_state.is_some()
&& !game_state.viewing_inventory
{
let username = &lobby_state.username;
let party = game_state.get_current_party()?;
let character_positions = party.character_positions.clone();
let game = game_state.get_current_game()?;
let player = get_player(game, username.to_string())?;
for character_id in character_positions {
Expand All @@ -73,6 +73,18 @@ pub fn character_autofocus_manager() -> Html {
break;
}
}
} else {
game_dispatch.reduce_mut(|store| {
if let Some(active_combatant_id) = active_combatant_id_option {
if !store.viewing_inventory
&& character_positions.contains(&active_combatant_id)
{
if store.current_battle_id != *prev_current_battle_id_state {
store.focused_character_id = active_combatant_id
}
}
}
})
}
Ok(())
})();
Expand Down
27 changes: 27 additions & 0 deletions client/src/components/game/combat_log/combat_log_message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use yew::AttrValue;

#[derive(Clone, PartialEq)]
pub enum CombatLogMessageStyle {
Basic,
PartyProgress,
PartyWipe,
PartyEscape,
BattleVictory,
}

#[derive(Clone, PartialEq)]
pub struct CombatLogMessage {
pub message: AttrValue,
pub style: CombatLogMessageStyle,
pub timestamp: u64,
}

impl CombatLogMessage {
pub fn new(message: AttrValue, style: CombatLogMessageStyle, timestamp: u64) -> Self {
CombatLogMessage {
message,
style,
timestamp,
}
}
}
27 changes: 26 additions & 1 deletion client/src/components/game/combat_log/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod combat_log_message;
use self::combat_log_message::CombatLogMessage;
use crate::store::game_store::GameStore;
use yew::prelude::*;
use yewdux::use_store;
Expand All @@ -12,9 +14,32 @@ pub fn combat_log() -> Html {
<div class="list-none overflow-y-auto
flex flex-col-reverse flex-1" >
<ul class="" >
{game_state.combat_log.iter().map(|log_entry| html!(<li>{log_entry}</li>)).collect::<Html>()}
{game_state.combat_log.iter().map(|log_entry| html!(
<CombatLogMessageElement combat_log_message={log_entry.clone()} />))
.collect::<Html>()}
</ul>
</div>
</div>
)
}

#[derive(Properties, PartialEq)]
pub struct Props {
combat_log_message: CombatLogMessage,
}

#[function_component(CombatLogMessageElement)]
pub fn combat_log_message_element(props: &Props) -> Html {
let Props { combat_log_message } = props;
let color = match combat_log_message.style {
combat_log_message::CombatLogMessageStyle::Basic => "",
combat_log_message::CombatLogMessageStyle::PartyProgress => "text-yellow-400",
combat_log_message::CombatLogMessageStyle::PartyWipe => "text-red-400",
combat_log_message::CombatLogMessageStyle::PartyEscape => "text-green-600",
combat_log_message::CombatLogMessageStyle::BattleVictory => "text-green-600",
};

html!(
<li class={color}>{combat_log_message.message.clone()}</li>
)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::components::game::combat_log::combat_log_message::CombatLogMessage;
use crate::components::game::combat_log::combat_log_message::CombatLogMessageStyle;
use crate::components::mesh_manager::CombatantAnimation;
use crate::components::mesh_manager::FloatingNumber;
use crate::store::game_store::GameStore;
Expand All @@ -16,12 +18,20 @@ pub fn swing_to_hit_animation_finished_handler(
) -> Result<(), AppError> {
game_dispatch.reduce_mut(|store| -> Result<(), AppError> {
let game = store.get_current_game_mut()?;
let (_, combatant_properties) = game.get_mut_combatant_by_id(&target_id)?;
let (attacker_entity_properties, _) = game.get_mut_combatant_by_id(&combatant_id)?;
let attacker_name = attacker_entity_properties.name.clone();
let (entity_properties, combatant_properties) = game.get_mut_combatant_by_id(&target_id)?;
let target_name = entity_properties.name.clone();
let new_hp = if let Some(hp_change) = hp_change_option {
let new_hp = combatant_properties.change_hp(hp_change);
store.combat_log.push(AttrValue::from(format!(
"{combatant_id} hit {target_id} for {hp_change}"
)));
store.combat_log.push(CombatLogMessage::new(
AttrValue::from(format!(
"{} ({combatant_id}) hit {} ({target_id}) for {hp_change}",
attacker_name, target_name
)),
CombatLogMessageStyle::Basic,
0,
));
new_hp
} else {
combatant_properties.hit_points
Expand All @@ -37,9 +47,14 @@ pub fn swing_to_hit_animation_finished_handler(
})?;

if evaded {
store.combat_log.push(AttrValue::from(format!(
"{target_id} evaded an attack from {combatant_id}"
)));
store.combat_log.push(CombatLogMessage::new(
AttrValue::from(format!(
"{} ({target_id}) evaded an attack from {} ({combatant_id})",
target_name, attacker_name,
)),
CombatLogMessageStyle::Basic,
0,
));
if target_event_manager.action_result_queue.front().is_none() {
target_event_manager.animation_queue = VecDeque::from([CombatantAnimation::Evasion])
}
Expand All @@ -58,9 +73,11 @@ pub fn swing_to_hit_animation_finished_handler(
if new_hp == 0 {
target_event_manager.animation_queue =
VecDeque::from([CombatantAnimation::Death(Some(hp_change))]);
store
.combat_log
.push(AttrValue::from(format!("{target_id} died")));
store.combat_log.push(CombatLogMessage::new(
AttrValue::from(format!("{} ({target_id}) died", target_name)),
CombatLogMessageStyle::Basic,
0,
));
} else {
target_event_manager.animation_queue =
VecDeque::from([CombatantAnimation::HitRecovery(hp_change)])
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/game/dungeon_room/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub fn dungeon_room(props: &Props) -> Html {
/>
}
</div>
if !game_state.viewing_inventory {
// if !game_state.viewing_inventory {
<div class="w-1/2 border-l border-slate-400 p-2 flex flex-col" >
if let Some(time_of_death) = time_of_death_option {
<div class=" border border-slate-400 bg-slate-700 p-4
Expand All @@ -112,7 +112,7 @@ pub fn dungeon_room(props: &Props) -> Html {
<ItemsOnGround />
}
</div>
}
// }
</section>
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn players_included_in_list(props: &PlayersIncludedInListProps) -> Html {
let is_ready = props.list_to_check.contains(username);
let mut ready_class = "";
if is_ready {
ready_class = "text-green-400"
ready_class = "text-green-600"
}
html!(
<div class={ready_class}>
Expand Down
3 changes: 1 addition & 2 deletions client/src/components/game/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod action_menu;
mod character_autofocus_manager;
mod character_sheet;
mod combat_log;
pub mod combat_log;
pub mod combatant;
mod combatant_detail_tab;
pub mod debug;
Expand Down Expand Up @@ -71,7 +71,6 @@ pub fn game() -> Html {

let focused_character = party.characters.get(&game_state.focused_character_id);


html!(
<main class="h-screen w-screen p-4 bg-gray-600 text-zinc-300 flex flex-col relative">
// <GameDebug />
Expand Down
21 changes: 16 additions & 5 deletions client/src/components/lobby/welcome_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn welcome_info() -> Html {
<section class="flex-1 p-4 mb-4 mr-4 bg-slate-700 border border-slate-400 overflow-y-auto">
<h3 class="text-lg">{"Roguelike Racing"}</h3>
<button onclick={handle_show_patch_notes_click} class="mb-2">
{"alpha 0.2.1 ⓘ"}
{"alpha 0.3.0 ⓘ"}
</button>
if *show_patch_notes_state == false {
<WelcomeMessage />
Expand All @@ -27,16 +27,27 @@ pub fn welcome_info() -> Html {
fn welcome_message() -> Html {
html!(
<>
<p>{"0.2.1"}</p>
<p>{"0.3.0 1/26/2024"}</p>
<p>{"Fixed bugs:"}</p>
<ul class="list-disc list-inside mb-1">
<li>{"Opening the inventory while combat animations were playing would cause the client to desync"}</li>
<li>{"Focus now shifts to the active character at the beginning of combat if not in the inventory"}</li>
</ul>
<p>{"Added features:"}</p>
<ul class="list-disc list-inside mb-1">
<li>{"Color coded messages now display in the combat log when any party in a game descends to a new floor, escapes the dungeon or wipes"}</li>
<li>{"Version history now shows dates"}</li>
</ul>
<p>{"0.2.1 1/25/2024"}</p>
<ul class="list-disc list-inside mb-1">
<li>{"Added patch notes section to welcome info"}</li>
<li>{"Fixed a bug where the room exploration tracker wouldn't work on any floor except the first"}</li>
</ul>
<p>{"0.2.0"}</p>
<p>{"0.2.0 1/24/2024"}</p>
<p>{"Fixed bugs:"}</p>
<ul class="list-disc list-inside mb-1">
<li>{"players couldn't attack while wearing a shield"}</li>
<li>{"unequipping an item would not change focus to the unequipped item"}</li>
<li>{"Players couldn't attack while wearing a shield"}</li>
<li>{"Unequipping an item would not change focus to the unequipped item"}</li>
</ul>
<p>{"Added features:"}</p>
<ul class="list-disc list-inside mb-1">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::components::game::combat_log::combat_log_message::CombatLogMessage;
use crate::components::game::combat_log::combat_log_message::CombatLogMessageStyle;
use crate::store::game_store::GameStore;
use common::app_consts::error_messages;
use common::combat::CombatTurnResult;
Expand Down Expand Up @@ -46,17 +48,21 @@ pub fn send_next_turn_result_to_combatant_event_manager(
BattleConclusion::Victory => {
party.current_room.monsters = None;
party.battle_id = None;
store
.combat_log
.push(AttrValue::from("battle ended in victory"));
store.combat_log.push(CombatLogMessage::new(
AttrValue::from("battle ended in victory"),
CombatLogMessageStyle::BattleVictory,
0,
));

store.current_battle_id = None;
}
BattleConclusion::Defeat => {
party.time_of_wipe = Some(js_sys::Date::now() as u64);
store
.combat_log
.push(AttrValue::from("battle ended in defeat (game over)"));
store.combat_log.push(CombatLogMessage::new(
AttrValue::from("battle ended in defeat"),
CombatLogMessageStyle::PartyWipe,
0,
));
}
}

Expand Down
4 changes: 4 additions & 0 deletions client/src/components/websocket_manager/handle_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use super::lobby_update_handlers::handle_game_started;
use super::lobby_update_handlers::handle_player_toggled_ready;
use super::lobby_update_handlers::handle_user_joined_game;
use super::lobby_update_handlers::handle_user_left_game;
use super::new_game_message_handler::new_game_message_handler;
use super::websocket_channel_packet_handlers::handle_user_joined_websocket_channel;
use super::websocket_channel_packet_handlers::handle_user_left_websocket_channel;
use super::websocket_channel_packet_handlers::handle_websocket_channels_full_update;
Expand Down Expand Up @@ -157,6 +158,9 @@ pub fn handle_packet(
GameServerUpdatePackets::DungeonRoomTypesOnCurrentFloor(packet) => {
new_dungeon_room_types_on_current_floor(game_dispatch, packet)
}
GameServerUpdatePackets::GameMessage(packet) => {
new_game_message_handler(game_dispatch, packet)
}
_ => {
log!(format!("unhandled packet: {:#?}", data));
Err(AppError {
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/websocket_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod adventuring_party_update_handlers;
mod dungeon_floor_number_changed_handler;
mod game_full_update_handler;
mod handle_battle_victory_report;
mod handle_character_dropped_equipped_item;
Expand All @@ -9,9 +10,9 @@ mod handle_packet;
mod in_game_party_update_handlers;
mod inventory_management_update_handlers;
mod lobby_update_handlers;
mod new_game_message_handler;
pub mod send_client_input;
mod websocket_channel_packet_handlers;
mod dungeon_floor_number_changed_handler;
use crate::components::alerts::set_alert;
use crate::store::alert_store::AlertStore;
use crate::store::game_store::GameStore;
Expand Down
Loading

0 comments on commit a888a92

Please sign in to comment.