Fixe lil buddy, add new states

This commit is contained in:
Joey Hines 2025-08-03 13:56:25 -06:00
parent fcde491549
commit df1900a7f8
Signed by: joeyahines
GPG Key ID: 38BA6F25C94C9382
8 changed files with 84 additions and 25 deletions

2
Cargo.lock generated
View File

@ -1093,7 +1093,7 @@ dependencies = [
[[package]] [[package]]
name = "fren" name = "fren"
version = "2.0.0" version = "2.1.0"
dependencies = [ dependencies = [
"axum 0.8.1", "axum 0.8.1",
"base64 0.22.1", "base64 0.22.1",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "fren" name = "fren"
version = "2.0.0" version = "2.1.0"
edition = "2024" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -4,8 +4,9 @@ use crate::event_listener::Listener;
use crate::inventory::ItemType; use crate::inventory::ItemType;
use crate::models::api_key::Apikey; use crate::models::api_key::Apikey;
use crate::models::lil_fren::{ use crate::models::lil_fren::{
AliveState, LilFren, draw_dancing, draw_frankenstein, draw_gone, draw_magic, draw_mining, AliveState, LilFren, draw_dancing, draw_frankenstein, draw_gone, draw_lost_balloon, draw_magic,
draw_resonance_cascade, draw_sick, draw_sleep, draw_standing, draw_tax_fraud, draw_mining, draw_mugging, draw_resonance_cascade, draw_sick, draw_sleep, draw_standing,
draw_tax_fraud,
}; };
use crate::models::managed_roles::ManagedRole; use crate::models::managed_roles::ManagedRole;
use crate::models::movie::Movie; use crate::models::movie::Movie;
@ -156,6 +157,8 @@ pub async fn draw_buddy_states(
ctx.reply(draw_sleep(&emoji)).await?; ctx.reply(draw_sleep(&emoji)).await?;
ctx.reply(draw_mining(&emoji)).await?; ctx.reply(draw_mining(&emoji)).await?;
ctx.reply(draw_gone()).await?; ctx.reply(draw_gone()).await?;
ctx.reply(draw_mugging(&emoji)).await?;
ctx.reply(draw_lost_balloon(&emoji)).await?;
Ok(()) Ok(())
} }

View File

@ -62,6 +62,10 @@ pub async fn checkup(ctx: Context<'_>) -> Result<(), Error> {
LilFrenState::PhasedIntoYourReality => { LilFrenState::PhasedIntoYourReality => {
"Lil Buddy has phased into your reality, they will be back soon" "Lil Buddy has phased into your reality, they will be back soon"
} }
LilFrenState::Mugging => "Uh-oh. Looks like buddy is mugging someone again...",
LilFrenState::LostABalloon => {
"Buddy lost their balloon :(, I hope this doesn't cause an international incident"
}
}; };
ctx.reply(state_msg).await?; ctx.reply(state_msg).await?;
@ -77,7 +81,7 @@ pub async fn checkup(ctx: Context<'_>) -> Result<(), Error> {
ctx.reply(resp).await?; ctx.reply(resp).await?;
} }
} else { } else {
ctx.reply("Sorry you have no little buddy right now. Please adopt!") ctx.reply("Sorry you have no little buddy right now. Please adopt, don't shop!")
.await?; .await?;
} }

View File

@ -19,7 +19,6 @@ use crate::discord::fren_coin::give_coin;
use crate::discord::joke::random; use crate::discord::joke::random;
use crate::error::Error; use crate::error::Error;
use crate::event_listener::{Listener, TriggerEvent, TriggerType}; use crate::event_listener::{Listener, TriggerEvent, TriggerType};
use crate::models::lil_fren::lil_fren_task;
use crate::models::social_credit::SocialCreditPhrase; use crate::models::social_credit::SocialCreditPhrase;
use crate::models::task::Task; use crate::models::task::Task;
use crate::user::User; use crate::user::User;
@ -56,12 +55,6 @@ async fn event_handler(
} }
}); });
} }
{
info!("Starting lil buddy task...");
let data = data.clone();
tokio::spawn(async move { lil_fren_task(data).await });
}
} }
serenity::FullEvent::Message { new_message } => { serenity::FullEvent::Message { new_message } => {
if new_message.content.starts_with("!") { if new_message.content.starts_with("!") {

View File

@ -15,6 +15,7 @@ use log::{error, info};
use magick_rust::magick_wand_genesis; use magick_rust::magick_wand_genesis;
use std::sync::Once; use std::sync::Once;
use structopt::StructOpt; use structopt::StructOpt;
use tracing_core::LevelFilter;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
const BAD_APPLE: &str = include_str!("assets/bad_apple.txt"); const BAD_APPLE: &str = include_str!("assets/bad_apple.txt");
@ -25,8 +26,11 @@ static START: Once = Once::new();
async fn main() { async fn main() {
let args: Args = Args::from_args(); let args: Args = Args::from_args();
tracing_subscriber::fmt() tracing_subscriber::fmt()
.with_max_level(tracing_core::metadata::Level::INFO) .with_env_filter(
.with_env_filter(EnvFilter::from_default_env()) EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy(),
)
.init(); .init();
let cfg = match BotConfig::new(&args.cfg_path) { let cfg = match BotConfig::new(&args.cfg_path) {

View File

@ -11,7 +11,6 @@ use rand::distr::{Distribution, StandardUniform};
use rand::{Rng, rng}; use rand::{Rng, rng};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
pub fn draw_standing(emoji: &Emoji) -> String { pub fn draw_standing(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new(); let mut msg = MessageBuilder::new();
@ -178,6 +177,34 @@ pub fn draw_feed(emoji: &Emoji, food: &str) -> String {
msg.build() msg.build()
} }
pub fn draw_mugging(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push_line(":GunPoint: :man_standing:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
pub fn draw_lost_balloon(emoji: &Emoji) -> String {
let mut msg = MessageBuilder::new();
msg.push_line(":blue_square::balloon::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push_line(":blue_square::blue_square::blue_square::blue_square::blue_square:");
msg.push(":blue_square::blue_square:");
msg.emoji(emoji);
msg.push_line(":blue_square::blue_square:");
msg.push_line(":green_square::green_square::green_square::green_square::green_square:");
msg.build()
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialOrd, PartialEq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialOrd, PartialEq)]
pub enum LilFrenState { pub enum LilFrenState {
Standing, Standing,
@ -190,11 +217,13 @@ pub enum LilFrenState {
AttemptingToNotCauseAResonanceCascade, AttemptingToNotCauseAResonanceCascade,
Mining, Mining,
PhasedIntoYourReality, PhasedIntoYourReality,
Mugging,
LostABalloon,
} }
impl Distribution<LilFrenState> for StandardUniform { impl Distribution<LilFrenState> for StandardUniform {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> LilFrenState { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> LilFrenState {
match rng.random_range(0..10) { match rng.random_range(0..12) {
0 => LilFrenState::Standing, 0 => LilFrenState::Standing,
1 => LilFrenState::TaxFraud, 1 => LilFrenState::TaxFraud,
2 => LilFrenState::Sick, 2 => LilFrenState::Sick,
@ -204,7 +233,9 @@ impl Distribution<LilFrenState> for StandardUniform {
6 => LilFrenState::AttemptingToCircumventDeath, 6 => LilFrenState::AttemptingToCircumventDeath,
7 => LilFrenState::AttemptingToNotCauseAResonanceCascade, 7 => LilFrenState::AttemptingToNotCauseAResonanceCascade,
8 => LilFrenState::Mining, 8 => LilFrenState::Mining,
_ => LilFrenState::PhasedIntoYourReality, 9 => LilFrenState::PhasedIntoYourReality,
10 => LilFrenState::Mugging,
_ => LilFrenState::LostABalloon,
} }
} }
} }
@ -291,6 +322,8 @@ impl LilFren {
LilFrenState::AttemptingToNotCauseAResonanceCascade => (-0.004, -0.004, 0.004), LilFrenState::AttemptingToNotCauseAResonanceCascade => (-0.004, -0.004, 0.004),
LilFrenState::Mining => (-0.006, -0.006, 0.001), LilFrenState::Mining => (-0.006, -0.006, 0.001),
LilFrenState::PhasedIntoYourReality => (0.0, 0.0, 0.0), LilFrenState::PhasedIntoYourReality => (0.0, 0.0, 0.0),
LilFrenState::Mugging => (-0.006, -0.006, 0.01),
LilFrenState::LostABalloon => (-0.002, -0.002, -0.006),
}; };
lil_fren.hunger = (lil_fren.hunger + hunger_diff * self.metabolism).clamp(-1.0, 1.0); lil_fren.hunger = (lil_fren.hunger + hunger_diff * self.metabolism).clamp(-1.0, 1.0);
@ -299,8 +332,8 @@ impl LilFren {
(lil_fren.entertainment + entertainment_diff * self.smarts).clamp(-1.0, 1.0); (lil_fren.entertainment + entertainment_diff * self.smarts).clamp(-1.0, 1.0);
if rng().random_bool(0.75) { if rng().random_bool(0.75) {
info!("fren is now {:?}", self.state);
lil_fren.state = rng().random(); lil_fren.state = rng().random();
info!("fren is now {:?}", self.state);
} }
db.insert(lil_fren)?; db.insert(lil_fren)?;
@ -333,6 +366,8 @@ impl LilFren {
LilFrenState::AttemptingToNotCauseAResonanceCascade => draw_resonance_cascade(emoji), LilFrenState::AttemptingToNotCauseAResonanceCascade => draw_resonance_cascade(emoji),
LilFrenState::Mining => draw_mining(emoji), LilFrenState::Mining => draw_mining(emoji),
LilFrenState::PhasedIntoYourReality => draw_gone(), LilFrenState::PhasedIntoYourReality => draw_gone(),
LilFrenState::Mugging => draw_mugging(emoji),
LilFrenState::LostABalloon => draw_lost_balloon(emoji),
} }
} }
@ -348,12 +383,13 @@ impl LilFren {
} }
} }
pub async fn lil_fren_task(data: Arc<GlobalData>) { pub async fn lil_fren_task(data: &Arc<GlobalData>) -> Result<(), Error> {
tokio::time::sleep(Duration::from_secs(60)).await;
let fren = LilFren::get_lil_fren(&data.db).unwrap(); let fren = LilFren::get_lil_fren(&data.db).unwrap();
if let Some(mut fren) = fren { if let Some(mut fren) = fren {
debug!("Updating Lil Fren state..."); debug!("Updating Lil Fren state...");
fren.update_fren(&data.db).unwrap(); fren.update_fren(&data.db)?;
} }
Ok(())
} }

View File

@ -3,12 +3,14 @@ use crate::discord::shop::restock_shop;
use crate::error::Error; use crate::error::Error;
use crate::models::birthday::BirthdayEntry; use crate::models::birthday::BirthdayEntry;
use crate::models::insult_compliment::{RandomResponseTemplate, ResponseType}; use crate::models::insult_compliment::{RandomResponseTemplate, ResponseType};
use chrono::{Days, Duration, TimeZone, Timelike, Utc}; use crate::models::lil_fren::lil_fren_task;
use chrono::{Days, Duration, TimeDelta, TimeZone, Timelike, Utc};
use j_db::database::Database; use j_db::database::Database;
use j_db::model::JdbModel; use j_db::model::JdbModel;
use log::{error, info}; use log::{error, info};
use poise::serenity_prelude::all::Mentionable; use poise::serenity_prelude::all::Mentionable;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ops::Add;
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)] #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
@ -17,13 +19,17 @@ pub enum TaskType {
CheckBirthdays, CheckBirthdays,
HandleReload, HandleReload,
RestockShop, RestockShop,
UpdateLilBuddy,
} }
impl TaskType { impl TaskType {
pub fn exclusive(&self) -> bool { pub fn exclusive(&self) -> bool {
matches!( matches!(
self, self,
TaskType::CheckBirthdays | TaskType::HandleReload | TaskType::RestockShop TaskType::CheckBirthdays
| TaskType::HandleReload
| TaskType::RestockShop
| TaskType::UpdateLilBuddy
) )
} }
} }
@ -83,6 +89,7 @@ impl Task {
pub async fn create_reoccurring_tasks(data: &Arc<GlobalData>) -> Result<(), Error> { pub async fn create_reoccurring_tasks(data: &Arc<GlobalData>) -> Result<(), Error> {
Task::add_task(&data.db, TaskType::CheckBirthdays, Utc::now())?; Task::add_task(&data.db, TaskType::CheckBirthdays, Utc::now())?;
Task::add_task(&data.db, TaskType::RestockShop, Utc::now())?; Task::add_task(&data.db, TaskType::RestockShop, Utc::now())?;
Task::add_task(&data.db, TaskType::UpdateLilBuddy, Utc::now())?;
Task::add_task( Task::add_task(
&data.db, &data.db,
TaskType::HandleReload, TaskType::HandleReload,
@ -170,10 +177,22 @@ impl Task {
Err(err) => error!("Error restocking shop: {:?}", err), Err(err) => error!("Error restocking shop: {:?}", err),
} }
let next_check = Utc::now()
.with_minute(0)
.unwrap()
.with_second(0)
.unwrap()
.add(TimeDelta::hours(1));
Task::add_task(&data.db, TaskType::RestockShop, next_check)?;
}
TaskType::UpdateLilBuddy => {
lil_fren_task(data).await?;
Task::add_task( Task::add_task(
&data.db, &data.db,
TaskType::RestockShop, TaskType::UpdateLilBuddy,
Utc::now() + Duration::hours(1), Utc::now() + Duration::minutes(5),
)?; )?;
} }
} }