use godot::{classes::RichTextLabel, prelude::*}; use crate::{ announcer::Announcement, game_manager::{Game, Player}, player::DamageSource, }; #[derive(GodotClass)] #[class(base=Node, init)] pub struct Chat { messages: Vec, base: Base, } #[godot_api] impl Chat { #[signal] pub fn on_new_message(idx: Gd); pub fn singleton() -> Option> { Game::singleton().and_then(|g| g.get_child(0).map(|c| c.cast())) } pub fn get_messages(&self) -> Vec> { self.messages.iter().map(|m| m.as_label()).collect() } pub fn new_message(&mut self, message: ChatMessage) { self.messages.len() as i64; self.messages.push(message.clone()); self.run_deferred(move |s| s.signals().on_new_message().emit(&message.as_label())); } } #[derive(Debug, Clone)] pub enum ChatMessage { Death(DamageSource, u16), Announcement(u16, Announcement), ChatMessage(String, Color, String), } impl ChatMessage { pub fn as_label(&self) -> Gd { let mut label = RichTextLabel::new_alloc(); label.set_fit_content(true); match self { ChatMessage::Death(source, player_id) => { if let Some(game) = Game::singleton() && let Some(player) = game.bind().find_player(*player_id) { match source { DamageSource::Player(source_id) => { if let Some(source) = game.bind().find_player(*source_id) { add_player(&mut label, source); label.append_text(" fragged "); add_player(&mut label, &player); } } DamageSource::Killbox(kind) => { add_player(&mut label, &player); label.append_text(&kind.as_kill_text()); } } } } ChatMessage::Announcement(player_id, announcement) => { if let Some(game) = Game::singleton() && let Some(player) = game.bind().find_player(*player_id) { add_player(&mut label, &player); label.append_text(" got "); let what = match announcement { Announcement::FirstBlood => "First Blood", Announcement::DoubleKill => "a Double Kill", Announcement::TripleKill => "a Triple Kill", Announcement::MegaKill => "a Mega Kill", }; label.append_text(&format!("[color=red]{}[/color]", what)); } } ChatMessage::ChatMessage(name, color, message) => { label.push_color(*color); label.add_text(&format!("{}: ", name)); label.pop(); label.add_text(message); } } label } } fn add_player(label: &mut Gd, player: &Player) { if let Some(game) = Game::singleton() && let Some(team) = game.bind().get_team(player.data.team) { label.push_color(team.bind().color); label.add_text(&player.data.name); label.pop(); } }