Fix edge cases + use up charges when using "use"

This commit is contained in:
Condorra 2023-02-26 00:56:22 +11:00
parent 385d2d1fd8
commit 8085689490
5 changed files with 71 additions and 7 deletions

View File

@ -659,6 +659,16 @@ impl DBTrans {
Ok(()) Ok(())
} }
pub async fn check_task_by_type_code<'a>(&'a self, task_type: &'a str, task_code: &'a str)
-> DResult<bool> {
let n : i64 = self.pg_trans()?.query_one(
"SELECT COUNT(*) FROM tasks WHERE \
details->>'task_type' = $1 AND \
details->>'task_code' = $2", &[&task_type, &task_code]
).await?.get(0);
Ok(n > 0)
}
pub async fn alloc_item_code(&self) -> DResult<i64> { pub async fn alloc_item_code(&self) -> DResult<i64> {
Ok(self.pg_trans()?.query_one("SELECT NEXTVAL('item_seq')", &[]).await?.get(0)) Ok(self.pg_trans()?.query_one("SELECT NEXTVAL('item_seq')", &[]).await?.get(0))
} }

View File

@ -98,7 +98,15 @@ pub async fn describe_normal_item(ctx: &VerbContext<'_>, item: &Item) -> UResult
&language::caps_first( &language::caps_first(
&item.pronouns.subject), &item.pronouns.subject),
&item.pronouns.possessive)); &item.pronouns.possessive));
} }
if ctx.trans.check_task_by_type_code("DelayedHealth",
&format!("{}/{}/bandage", &item.item_type, &item.item_code)
).await? {
contents_desc.push_str(&format!("{} is wrapped up in bandages.\n",
&language::caps_first(&item.pronouns.subject))
);
}
} else if item.item_type == "possession" { } else if item.item_type == "possession" {
if health_ratio == 1.0 { if health_ratio == 1.0 {
contents_desc.push_str(&format!("{}'s in perfect condition.\n", &language::caps_first(&item.pronouns.subject))); contents_desc.push_str(&format!("{}'s in perfect condition.\n", &language::caps_first(&item.pronouns.subject)));

View File

@ -26,6 +26,7 @@ use crate::{
skills::skill_check_and_grind, skills::skill_check_and_grind,
effect::run_effects, effect::run_effects,
}, },
language,
}; };
use async_trait::async_trait; use async_trait::async_trait;
use std::time; use std::time;
@ -156,17 +157,41 @@ impl QueueCommandHandler for QueueHandler {
1, false), 1, false),
target_name, target_name target_name, target_name
))? ))?
} }
let use_data = match item.possession_type.as_ref() let use_data = match item.possession_type.as_ref()
.and_then(|poss_type| possession_data().get(&poss_type)) .and_then(|poss_type| possession_data().get(&poss_type))
.and_then(|poss_data| poss_data.use_data.as_ref()) { .and_then(|poss_data| poss_data.use_data.as_ref()) {
None => user_error("You can't use that!".to_owned())?, None => user_error("You can't use that!".to_owned())?,
Some(d) => d Some(d) => d
}; };
if let Some(charge_data) = item.possession_type.as_ref()
.and_then(|poss_type| possession_data().get(&poss_type))
.and_then(|poss_data| poss_data.charge_data.as_ref()) {
if item.charges < 1 {
user_error(
format!("{} has no {} {} left",
item.display_for_sentence(!ctx.session_dat.less_explicit_mode,
1, true),
&language::pluralise(charge_data.charge_name_prefix),
charge_data.charge_name_suffix
))?;
}
}
if let Some(err) = (use_data.errorf)(&item, &target) { if let Some(err) = (use_data.errorf)(&item, &target) {
user_error(err)?; user_error(err)?;
} }
if ctx.trans.check_task_by_type_code(
"DelayedHealth",
&format!("{}/{}/{}", &target.item_type, &target.item_code,
use_data.task_ref)
).await? {
user_error(format!("You see no reason to use {} on {}",
item.display_for_sentence(!ctx.session_dat.less_explicit_mode,
1, false),
target.display_for_sentence(!ctx.session_dat.less_explicit_mode,
1, false)
))?;
}
let is_self_use = target_type == &"player" && target_code == &player_item.item_code; let is_self_use = target_type == &"player" && target_code == &player_item.item_code;
let mut player_mut = (*player_item).clone(); let mut player_mut = (*player_item).clone();
let skillcheck = skill_check_and_grind(&ctx.trans, &mut player_mut, let skillcheck = skill_check_and_grind(&ctx.trans, &mut player_mut,
@ -187,7 +212,14 @@ impl QueueCommandHandler for QueueHandler {
ctx.trans.save_item_model(&target_mut_save).await?; ctx.trans.save_item_model(&target_mut_save).await?;
} }
ctx.trans.save_item_model(&player_mut).await?; ctx.trans.save_item_model(&player_mut).await?;
if item.possession_type.as_ref()
.and_then(|poss_type| possession_data().get(&poss_type))
.and_then(|poss_data| poss_data.charge_data.as_ref()).is_some() {
let mut item_mut = (*item).clone();
item_mut.charges -= 1;
ctx.trans.save_item_model(&item_mut).await?;
}
Ok(()) Ok(())
} }
} }

View File

@ -1,5 +1,4 @@
use crate::{ use crate::{
db::DBTrans,
models::{ models::{
item::Item, item::Item,
task::{ task::{
@ -28,6 +27,8 @@ use serde::{Serialize, Deserialize};
use std::collections::{BTreeMap, VecDeque}; use std::collections::{BTreeMap, VecDeque};
use chrono::Utc; use chrono::Utc;
use log::info; use log::info;
use mockall_double::double;
#[double] use crate::db::DBTrans;
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct DelayedHealthEffect { pub struct DelayedHealthEffect {
@ -58,6 +59,9 @@ impl TaskHandler for DelayedHealthTaskHandler {
} }
Some(it) => it Some(it) => it
}; };
if item.is_dead {
return Ok(None);
}
match item_effect_series.1.pop_front() { match item_effect_series.1.pop_front() {
None => Ok(None), None => Ok(None),
Some(DelayedHealthEffect { magnitude, message, message_nonexp, .. }) => { Some(DelayedHealthEffect { magnitude, message, message_nonexp, .. }) => {

View File

@ -64,7 +64,7 @@ impl Default for ChargeData {
Self { Self {
max_charges: 1, max_charges: 1,
charge_name_prefix: "charge", charge_name_prefix: "charge",
charge_name_suffix: "" charge_name_suffix: "",
} }
} }
} }
@ -484,6 +484,16 @@ pub fn possession_data() -> &'static BTreeMap<PossessionType, PossessionData> {
) )
}, },
), ),
task_ref: "bandage",
errorf: Box::new(
|_item, target|
if target.is_dead {
Some(format!("It is too late, {}'s dead", target.pronouns.subject))
} else if target.item_type != "player" && target.item_type != "npc" {
Some("It only works on animals.".to_owned())
} else {
None
}),
..Default::default() ..Default::default()
}), }),
..Default::default() ..Default::default()