Support wielding weapons.
This commit is contained in:
parent
dc38d87beb
commit
2850b66bee
@ -12,7 +12,10 @@ use crate::message_handler::user_commands::parsing::parse_offset;
|
||||
use crate::models::{
|
||||
session::Session,
|
||||
user::User,
|
||||
item::Item,
|
||||
item::{
|
||||
Item,
|
||||
LocationActionType,
|
||||
},
|
||||
task::{Task, TaskParse}
|
||||
};
|
||||
use tokio_postgres::types::ToSql;
|
||||
@ -630,10 +633,45 @@ impl DBTrans {
|
||||
|
||||
pub async fn get_location_stats(&self, location: &str) -> DResult<LocationStats> {
|
||||
Ok(serde_json::from_value(self.pg_trans()?.query_one(
|
||||
"SELECT COUNT(*) AS total_count, SUM(details->>'weight') AS total_weight \
|
||||
FROM items WHERE location = $1", &[&location]
|
||||
"SELECT JSON_BUILD_OBJECT('total_count', COUNT(*), 'total_weight', COALESCE(SUM(CAST(details->>'weight' AS NUMERIC)), 0)) \
|
||||
FROM items WHERE details->>'location' = $1", &[&location]
|
||||
).await?.get(0))?)
|
||||
}
|
||||
|
||||
pub async fn set_exclusive_action_type_to(&self, item: &Item,
|
||||
new_action_type: &LocationActionType,
|
||||
other_item_action_type: &LocationActionType) -> DResult<()> {
|
||||
self.pg_trans()?.execute("UPDATE items SET details=\
|
||||
JSONB_SET(details, '{action_type}', $1) \
|
||||
WHERE details->>'location' = $2 AND \
|
||||
details->>'action_type' = $3",
|
||||
&[&serde_json::to_value(other_item_action_type)?,
|
||||
&item.location,
|
||||
&serde_json::to_value(new_action_type)?
|
||||
.as_str().unwrap()
|
||||
]).await?;
|
||||
self.pg_trans()?.execute("UPDATE items SET details=\
|
||||
JSONB_SET(details, '{action_type}', $1) \
|
||||
WHERE details->>'item_type' = $2 AND \
|
||||
details->>'item_code' = $3",
|
||||
&[&serde_json::to_value(new_action_type)?,
|
||||
&item.item_type,
|
||||
&item.item_code
|
||||
]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_action_and_location(&self, location: &str, action_type: &LocationActionType) -> DResult<Option<Arc<Item>>> {
|
||||
if let Some(item) = self.pg_trans()?.query_opt(
|
||||
"SELECT details FROM items WHERE \
|
||||
details->>'location' = $1 AND \
|
||||
details->>'action_type' = $2",
|
||||
&[&location,
|
||||
&serde_json::to_value(action_type)?.as_str().unwrap()]).await? {
|
||||
return Ok(Some(Arc::new(serde_json::from_value::<Item>(item.get("details"))?)));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||
|
@ -28,6 +28,7 @@ mod register;
|
||||
pub mod say;
|
||||
mod whisper;
|
||||
mod who;
|
||||
pub mod wield;
|
||||
|
||||
pub struct VerbContext<'l> {
|
||||
pub session: &'l ListenerSession,
|
||||
@ -125,6 +126,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
||||
"whisper" => whisper::VERB,
|
||||
"tell" => whisper::VERB,
|
||||
|
||||
"wield" => wield::VERB,
|
||||
"who" => who::VERB,
|
||||
};
|
||||
|
||||
|
140
blastmud_game/src/message_handler/user_commands/wield.rs
Normal file
140
blastmud_game/src/message_handler/user_commands/wield.rs
Normal file
@ -0,0 +1,140 @@
|
||||
use super::{
|
||||
VerbContext,
|
||||
UserVerb,
|
||||
UserVerbRef,
|
||||
UResult,
|
||||
ItemSearchParams,
|
||||
user_error,
|
||||
get_player_item_or_fail,
|
||||
search_item_for_user,
|
||||
};
|
||||
use crate::{
|
||||
static_content::possession_type::possession_data,
|
||||
regular_tasks::queued_command::{
|
||||
QueueCommandHandler,
|
||||
QueueCommand,
|
||||
queue_command
|
||||
},
|
||||
models::item::{
|
||||
LocationActionType,
|
||||
SkillType,
|
||||
},
|
||||
services::{
|
||||
broadcast_to_room,
|
||||
skills::skill_check_and_grind,
|
||||
},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use std::time;
|
||||
|
||||
pub struct QueueHandler;
|
||||
#[async_trait]
|
||||
impl QueueCommandHandler for QueueHandler {
|
||||
async fn start_command(&self, ctx: &mut VerbContext<'_>, command: &QueueCommand)
|
||||
-> UResult<time::Duration> {
|
||||
let player_item = get_player_item_or_fail(ctx).await?;
|
||||
if player_item.is_dead {
|
||||
user_error("You try to wield it, but your ghostly hands slip through it uselessly".to_owned())?;
|
||||
}
|
||||
let item_id = match command {
|
||||
QueueCommand::Wield { possession_id } => possession_id,
|
||||
_ => user_error("Unexpected command".to_owned())?
|
||||
};
|
||||
let item = match ctx.trans.find_item_by_type_code("possession", &item_id).await? {
|
||||
None => user_error("Item not found".to_owned())?,
|
||||
Some(it) => it
|
||||
};
|
||||
if item.location != format!("player/{}", player_item.item_code) {
|
||||
user_error("You try to wield it but realise you no longer have it".to_owned())?
|
||||
}
|
||||
let msg_exp = format!("{} fumbles around with {} {}\n",
|
||||
&player_item.display_for_sentence(true, 1, true),
|
||||
&player_item.pronouns.possessive,
|
||||
&item.display_for_sentence(true, 1, false));
|
||||
let msg_nonexp = format!("{} fumbles around with {} {}\n",
|
||||
&player_item.display_for_sentence(false, 1, true),
|
||||
&player_item.pronouns.possessive,
|
||||
&item.display_for_sentence(false, 1, false));
|
||||
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
|
||||
let mut draw_level: f64 = *player_item.total_skills.get(&SkillType::Quickdraw).to_owned().unwrap_or(&8.0);
|
||||
let mut player_item_mut = (*player_item).clone();
|
||||
|
||||
let skill_result =
|
||||
skill_check_and_grind(ctx.trans, &mut player_item_mut, &SkillType::Quickdraw, draw_level).await?;
|
||||
if skill_result < -0.5 {
|
||||
draw_level -= 2.0;
|
||||
} else if skill_result < -0.25 {
|
||||
draw_level -= 1.0;
|
||||
} else if skill_result > 0.5 {
|
||||
draw_level += 2.0;
|
||||
} else if skill_result > 0.25 {
|
||||
draw_level += 1.0;
|
||||
}
|
||||
ctx.trans.save_item_model(&player_item_mut).await?;
|
||||
|
||||
let wait_ticks = (12.0 - (draw_level / 2.0)).min(8.0).max(1.0);
|
||||
Ok(time::Duration::from_millis((wait_ticks * 500.0).round() as u64))
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
async fn finish_command(&self, ctx: &mut VerbContext<'_>, command: &QueueCommand)
|
||||
-> UResult<()> {
|
||||
let player_item = get_player_item_or_fail(ctx).await?;
|
||||
if player_item.is_dead {
|
||||
user_error("You try to wield it, but your ghostly hands slip through it uselessly".to_owned())?;
|
||||
}
|
||||
let item_id = match command {
|
||||
QueueCommand::Wield { possession_id } => possession_id,
|
||||
_ => user_error("Unexpected command".to_owned())?
|
||||
};
|
||||
let item = match ctx.trans.find_item_by_type_code("possession", &item_id).await? {
|
||||
None => user_error("Item not found".to_owned())?,
|
||||
Some(it) => it
|
||||
};
|
||||
if item.location != format!("player/{}", player_item.item_code) {
|
||||
user_error("You try to wield it but realise you no longer have it".to_owned())?
|
||||
}
|
||||
let msg_exp = format!("{} wields {} {}\n",
|
||||
&player_item.display_for_sentence(true, 1, true),
|
||||
&player_item.pronouns.possessive,
|
||||
&item.display_for_sentence(true, 1, false));
|
||||
let msg_nonexp = format!("{} wields {} {}\n",
|
||||
&player_item.display_for_sentence(false, 1, true),
|
||||
&player_item.pronouns.possessive,
|
||||
&item.display_for_sentence(false, 1, false));
|
||||
broadcast_to_room(ctx.trans, &player_item.location, None, &msg_exp, Some(&msg_nonexp)).await?;
|
||||
ctx.trans.set_exclusive_action_type_to(&item,
|
||||
&LocationActionType::Wielded,
|
||||
&LocationActionType::Normal).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Verb;
|
||||
#[async_trait]
|
||||
impl UserVerb for Verb {
|
||||
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||
let player_item = get_player_item_or_fail(ctx).await?;
|
||||
let weapon = search_item_for_user(ctx, &ItemSearchParams {
|
||||
include_contents: true,
|
||||
..ItemSearchParams::base(&player_item, &remaining)
|
||||
}).await?;
|
||||
if player_item.is_dead {
|
||||
user_error("You try to wield it, but your ghostly hands slip through it uselessly".to_owned())?;
|
||||
}
|
||||
if weapon.action_type == LocationActionType::Wielded {
|
||||
user_error("You're actually already wielding it.".to_owned())?;
|
||||
}
|
||||
if weapon.item_type != "possession" ||
|
||||
weapon.possession_type.as_ref()
|
||||
.and_then(|poss_type| possession_data().get(&poss_type))
|
||||
.and_then(|poss_data| poss_data.weapon_data.as_ref())
|
||||
.is_none() {
|
||||
user_error("You can't wield that!".to_owned())?;
|
||||
}
|
||||
queue_command(ctx, &QueueCommand::Wield { possession_id: weapon.item_code.clone() }).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
static VERB_INT: Verb = Verb;
|
||||
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -15,6 +15,7 @@ use crate::message_handler::user_commands::{
|
||||
CommandHandlingError,
|
||||
UResult,
|
||||
movement,
|
||||
wield,
|
||||
user_error,
|
||||
get_user_or_fail
|
||||
};
|
||||
@ -24,12 +25,14 @@ use once_cell::sync::OnceCell;
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum QueueCommand {
|
||||
Movement { direction: Direction },
|
||||
Wield { possession_id: String }
|
||||
}
|
||||
impl QueueCommand {
|
||||
pub fn name(&self) -> &'static str {
|
||||
use QueueCommand::*;
|
||||
match self {
|
||||
Movement {..} => "Movement"
|
||||
Movement {..} => "Movement",
|
||||
Wield {..} => "Wield",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -44,7 +47,8 @@ fn queue_command_registry() -> &'static BTreeMap<&'static str, &'static (dyn Que
|
||||
static REGISTRY: OnceCell<BTreeMap<&'static str, &'static (dyn QueueCommandHandler + Sync + Send)>> =
|
||||
OnceCell::new();
|
||||
REGISTRY.get_or_init(|| vec!(
|
||||
("Movement", &movement::QueueHandler as &(dyn QueueCommandHandler + Sync + Send))
|
||||
("Movement", &movement::QueueHandler as &(dyn QueueCommandHandler + Sync + Send)),
|
||||
("Wield", &wield::QueueHandler as &(dyn QueueCommandHandler + Sync + Send))
|
||||
).into_iter().collect())
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,16 @@ pub async fn stop_attacking(trans: &DBTrans, by_whom: &Item, to_whom: &Item) ->
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn what_wielded(_trans: &DBTrans, who: &Item) -> DResult<&'static WeaponData> {
|
||||
async fn what_wielded(trans: &DBTrans, who: &Item) -> DResult<&'static WeaponData> {
|
||||
if let Some(item) = trans.find_by_action_and_location(
|
||||
&format!("{}/{}", &who.item_type, &who.item_code), &LocationActionType::Wielded).await? {
|
||||
if let Some(dat) = item.possession_type.as_ref()
|
||||
.and_then(|pt| possession_data().get(&pt))
|
||||
.and_then(|pd| pd.weapon_data.as_ref()) {
|
||||
return Ok(dat);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Search inventory for wielded item first.
|
||||
if who.item_type == "npc" {
|
||||
if let Some(intrinsic) = npc_by_code().get(who.item_code.as_str())
|
||||
|
@ -46,105 +46,105 @@ pub fn calculate_total_stats_skills_for_user(target_item: &mut Item, user: &User
|
||||
target_item.total_skills.entry(SkillType::Appraise)
|
||||
.and_modify(|sk| *sk += brn * 0.5).or_insert(brn * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Appraise)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Blades)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Blades)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Bombs)
|
||||
.and_modify(|sk| *sk += brn * 0.5).or_insert(brn * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Bombs)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Chemistry)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Climb)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Climb)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Clubs)
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brw * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Clubs)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Craft)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Dodge)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Dodge)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fish)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fish)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fists)
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brw * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fists)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Focus)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Focus)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fuck)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Fuck)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Hack)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Locksmith)
|
||||
.and_modify(|sk| *sk += brn * 0.5).or_insert(brn * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Locksmith)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Medic)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Persuade)
|
||||
.and_modify(|sk| *sk += brn * 0.5).or_insert(brn * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Persuade)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Pilot)
|
||||
.and_modify(|sk| *sk += brn * 0.5).or_insert(brn * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Pilot)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Pistols)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Pistols)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Quickdraw)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Quickdraw)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Repair)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Rifles)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Rifles)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Scavenge)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Scavenge)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Science)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Sneak)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Sneak)
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += col * 0.5).or_insert(col * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Spears)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Spears)
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += end * 0.5).or_insert(end * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Swim)
|
||||
.and_modify(|sk| *sk += end).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Teach)
|
||||
.and_modify(|sk| *sk += brn).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Throw)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Throw)
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += brw * 0.5).or_insert(brw * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Track)
|
||||
.and_modify(|sk| *sk += sen).or_insert(brn);
|
||||
target_item.total_skills.entry(SkillType::Whips)
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += sen * 0.5).or_insert(sen * 0.5);
|
||||
target_item.total_skills.entry(SkillType::Whips)
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(brn * 0.5);
|
||||
.and_modify(|sk| *sk += refl * 0.5).or_insert(refl * 0.5);
|
||||
// 5: Apply skill (de)buffs...
|
||||
for buff in &target_item.temporary_buffs {
|
||||
for impact in &buff.impacts {
|
||||
|
Loading…
Reference in New Issue
Block a user