Split possessions out into separate files per type.

This commit is contained in:
Condorra 2023-03-13 17:53:41 +11:00
parent e0187bd2c8
commit b000f9830b
5 changed files with 369 additions and 325 deletions

View File

@ -1,12 +1,17 @@
use serde::{Serialize, Deserialize};
use crate::{
models::item::{SkillType, Item, ItemSpecialData, Pronouns}
models::item::{SkillType, Item, Pronouns},
models::consent::ConsentType,
};
use once_cell::sync::OnceCell;
use std::collections::BTreeMap;
use rand::seq::SliceRandom;
use super::species::BodyPart;
use ansi::ansi;
mod fangs;
mod antenna_whip;
mod trauma_kit;
mod corp_licence;
pub type AttackMessageChoice = Vec<Box<dyn Fn(&Item, &Item, bool) -> String + 'static + Sync + Send>>;
pub type AttackMessageChoicePart = Vec<Box<dyn Fn(&Item, &Item, &BodyPart, bool) -> String + 'static + Sync + Send>>;
@ -85,7 +90,8 @@ pub struct UseData {
pub fail_effects: Vec<UseEffect>,
pub success_effects: Vec<UseEffect>,
pub errorf: Box<dyn Fn(&Item, &Item) -> Option<String> + Sync + Send>,
pub task_ref: &'static str,
pub task_ref: &'static str,
pub needs_consent_check: Option<ConsentType>,
}
impl Default for UseData {
@ -98,6 +104,7 @@ impl Default for UseData {
success_effects: vec!(),
errorf: Box::new(|_it, _target| None),
task_ref: "set me",
needs_consent_check: None,
}
}
}
@ -228,328 +235,12 @@ pub fn possession_data() -> &'static BTreeMap<PossessionType, PossessionData> {
use PossessionType::*;
&POSSESSION_DATA.get_or_init(|| {
vec!(
(Fangs, PossessionData {
weapon_data: Some(WeaponData {
uses_skill: SkillType::Fists,
raw_min_to_learn: 0.0,
raw_max_to_learn: 2.0,
normal_attack_start_messages: vec!(
Box::new(|attacker, victim, exp|
format!("{} bares {} teeth and lunges at {}",
&attacker.display_for_sentence(exp, 1, true),
&attacker.pronouns.possessive,
&victim.display_for_sentence(exp, 1, false),
)
)
),
normal_attack_success_messages: vec!(
Box::new(|attacker, victim, part, exp|
format!("{}'s teeth connect and tear at the flesh of {}'s {}",
&attacker.display_for_sentence(exp, 1, true),
&victim.display_for_sentence(exp, 1, false),
&part.display(victim.sex.clone())
)
)
),
..Default::default()
}),
..Default::default()
}),
(AntennaWhip, PossessionData {
display: "antenna whip",
details: "A crudely fashioned whip made from a broken metal antenna. It looks a bit flimsy, but it \
might do you until you get a better weapon!",
aliases: vec!("whip"),
weapon_data: Some(WeaponData {
uses_skill: SkillType::Whips,
raw_min_to_learn: 0.0,
raw_max_to_learn: 2.0,
normal_attack_start_messages: vec!(
Box::new(|attacker, victim, exp|
format!("{} lines up {} antenna whip for a strike on {}",
&attacker.display_for_sentence(exp, 1, true),
&attacker.pronouns.possessive,
&victim.display_for_sentence(exp, 1, false),
)
)
),
normal_attack_success_messages: vec!(
Box::new(|attacker, victim, part, exp|
format!("{}'s antenna whip scores a painful red line across {}'s {}",
&attacker.display_for_sentence(exp, 1, true),
&victim.display_for_sentence(exp, 1, false),
&part.display(victim.sex.clone())
)
)
),
normal_attack_mean_damage: 3.0,
normal_attack_stdev_damage: 3.0,
..Default::default()
}),
..Default::default()
}),
(MediumTraumaKit, PossessionData {
display: "medium trauma kit",
details: "A collection of bandages and and small gadgets that look like they could, in the right hands, make an unhealthy person healthy again. It looks like when brand new, it could be used 5 times.",
aliases: vec!("trauma"),
charge_data: Some(ChargeData {
max_charges: 5,
charge_name_prefix: "treatment",
charge_name_suffix: "worth of supplies",
..Default::default()
}),
use_data: Some(UseData {
uses_skill: SkillType::Medic,
diff_level: 10.0,
crit_fail_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} attempts to heal {} with a trauma kit, but fucks it up badly\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} attempts to heal {} with a trauma kit, but messes it up badly\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
UseEffect::ChangeTargetHealth {
delay_secs: 0, base_effect: -2, skill_multiplier: -3.0,
max_effect: -5,
message: Box::new(
|target|
(format!(
"Fuck! The trauma kit makes {}'s condition worse",
target.display_for_sentence(true, 1, false)),
format!(
"The trauma kit makes {}'s condition worse",
target.display_for_sentence(false, 1, false)
)
))
}
),
fail_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} attempts unsuccessfully to heal {} with a trauma kit\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} attempts unsuccessfully to heal {} with a trauma kit\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
),
success_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} expertly heals {} with a trauma kit\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} expertly heals {} with a trauma kit\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
UseEffect::ChangeTargetHealth {
delay_secs: 0, base_effect: 2, skill_multiplier: 8.0,
max_effect: 10,
message: Box::new(
|target|
(format!(
"FUUUCK! It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
),
format!(
"It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 10, base_effect: 2, skill_multiplier: 7.0,
max_effect: 9,
message: Box::new(
|target|
(format!(
"FUUUCK! It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
),
format!(
"It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 20, base_effect: 1, skill_multiplier: 6.0,
max_effect: 7,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 30, base_effect: 1, skill_multiplier: 5.0,
max_effect: 6,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 40, base_effect: 0, skill_multiplier: 4.0,
max_effect: 4,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 50, base_effect: 0, skill_multiplier: 3.0,
max_effect: 3,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 60, base_effect: 0, skill_multiplier: 2.0,
max_effect: 2,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
),
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()
}),
becomes_on_spent: Some(EmptyMedicalBox),
..Default::default()
}),
(EmptyMedicalBox, PossessionData {
display: "empty medical box",
details: "An empty box that looks like it once had something medical in it.",
aliases: vec!("box"),
..Default::default()
}),
(NewCorpLicence, PossessionData {
display: "new corp licence",
details: ansi!("A blank form that you can <bold>use<reset> to establish a new corp. It rests on a clipboard with a pencil attached by a chain. There is a space to <bold>write<reset> on it [try <bold>write Blah on licence<reset> followed by <bold>use licence<reset> to create a corp named Blah]"),
aliases: vec!("form", "license", "licence", "new"),
use_data: Some(UseData {
uses_skill: SkillType::Persuade,
diff_level: 4.0,
crit_fail_effects: vec!(),
fail_effects: vec!(),
success_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, _target| (
format!(
"{} signs a contract establishing Blah as a corp\n",
&player.display_for_sentence(true, 1, true),
),
format!("{} signs a contract establishing Blah as a corp\n",
&player.display_for_sentence(false, 1, true),
)))
},
),
errorf: Box::new(
|item, _target|
match item.special_data {
Some(ItemSpecialData::ItemWriting { .. }) => None,
_ => Some("You have to your corp's name on it first!".to_owned())
}),
..Default::default()
}),
weight: 10,
becomes_on_spent: Some(CertificateOfIncorporation),
..Default::default()
}),
(CertificateOfIncorporation, PossessionData {
display: "certificate of incorporation",
details: "A certificate recording the formation of a corp.",
weight: 10,
..Default::default()
}),
(Fangs, fangs::data()),
(AntennaWhip, antenna_whip::data()),
(MediumTraumaKit, trauma_kit::medium_data()),
(EmptyMedicalBox, trauma_kit::empty_data()),
(NewCorpLicence, corp_licence::data()),
(CertificateOfIncorporation, corp_licence::cert_data()),
).into_iter().collect()
})
}

View File

@ -0,0 +1,38 @@
use super::{PossessionData, WeaponData};
use crate::models::item::SkillType;
pub fn data() -> PossessionData {
PossessionData {
display: "antenna whip",
details: "A crudely fashioned whip made from a broken metal antenna. It looks a bit flimsy, but it \
might do you until you get a better weapon!",
aliases: vec!("whip"),
weapon_data: Some(WeaponData {
uses_skill: SkillType::Whips,
raw_min_to_learn: 0.0,
raw_max_to_learn: 2.0,
normal_attack_start_messages: vec!(
Box::new(|attacker, victim, exp|
format!("{} lines up {} antenna whip for a strike on {}",
&attacker.display_for_sentence(exp, 1, true),
&attacker.pronouns.possessive,
&victim.display_for_sentence(exp, 1, false),
)
)
),
normal_attack_success_messages: vec!(
Box::new(|attacker, victim, part, exp|
format!("{}'s antenna whip scores a painful red line across {}'s {}",
&attacker.display_for_sentence(exp, 1, true),
&victim.display_for_sentence(exp, 1, false),
&part.display(victim.sex.clone())
)
)
),
normal_attack_mean_damage: 3.0,
normal_attack_stdev_damage: 3.0,
..Default::default()
}),
..Default::default()
}
}

View File

@ -0,0 +1,50 @@
use super::{PossessionData, UseData, UseEffect};
use crate::models::item::{SkillType, ItemSpecialData};
use ansi::ansi;
use super::PossessionType::*;
pub fn data() -> PossessionData {
PossessionData {
display: "new corp licence",
details: ansi!("A blank form that you can <bold>use<reset> to establish a new corp. It rests on a clipboard with a pencil attached by a chain. There is a space to <bold>write<reset> on it [try <bold>write Blah on licence<reset> followed by <bold>use licence<reset> to create a corp named Blah]"),
aliases: vec!("form", "license", "licence", "new"),
use_data: Some(UseData {
uses_skill: SkillType::Persuade,
diff_level: 4.0,
crit_fail_effects: vec!(),
fail_effects: vec!(),
success_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, _target| (
format!(
"{} signs a contract establishing Blah as a corp\n",
&player.display_for_sentence(true, 1, true),
),
format!("{} signs a contract establishing Blah as a corp\n",
&player.display_for_sentence(false, 1, true),
)))
},
),
errorf: Box::new(
|item, _target|
match item.special_data {
Some(ItemSpecialData::ItemWriting { .. }) => None,
_ => Some("You have to your corp's name on it first!".to_owned())
}),
..Default::default()
}),
weight: 10,
becomes_on_spent: Some(CertificateOfIncorporation),
..Default::default()
}
}
pub fn cert_data() -> PossessionData {
PossessionData {
display: "certificate of incorporation",
details: "A certificate recording the formation of a corp.",
weight: 10,
..Default::default()
}
}

View File

@ -0,0 +1,32 @@
use super::{PossessionData, WeaponData};
use crate::models::item::SkillType;
pub fn data() -> PossessionData {
PossessionData {
weapon_data: Some(WeaponData {
uses_skill: SkillType::Fists,
raw_min_to_learn: 0.0,
raw_max_to_learn: 2.0,
normal_attack_start_messages: vec!(
Box::new(|attacker, victim, exp|
format!("{} bares {} teeth and lunges at {}",
&attacker.display_for_sentence(exp, 1, true),
&attacker.pronouns.possessive,
&victim.display_for_sentence(exp, 1, false),
)
)
),
normal_attack_success_messages: vec!(
Box::new(|attacker, victim, part, exp|
format!("{}'s teeth connect and tear at the flesh of {}'s {}",
&attacker.display_for_sentence(exp, 1, true),
&victim.display_for_sentence(exp, 1, false),
&part.display(victim.sex.clone())
)
)
),
..Default::default()
}),
..Default::default()
}
}

View File

@ -0,0 +1,233 @@
use super::{PossessionData, UseData, UseEffect, ChargeData};
use crate::models::item::SkillType;
use super::PossessionType::*;
pub fn medium_data() -> PossessionData {
PossessionData {
display: "medium trauma kit",
details: "A collection of bandages and and small gadgets that look like they could, in the right hands, make an unhealthy person healthy again. It looks like when brand new, it could be used 5 times.",
aliases: vec!("trauma"),
charge_data: Some(ChargeData {
max_charges: 5,
charge_name_prefix: "treatment",
charge_name_suffix: "worth of supplies",
..Default::default()
}),
use_data: Some(UseData {
uses_skill: SkillType::Medic,
diff_level: 10.0,
crit_fail_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} attempts to heal {} with a trauma kit, but fucks it up badly\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} attempts to heal {} with a trauma kit, but messes it up badly\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
UseEffect::ChangeTargetHealth {
delay_secs: 0, base_effect: -2, skill_multiplier: -3.0,
max_effect: -5,
message: Box::new(
|target|
(format!(
"Fuck! The trauma kit makes {}'s condition worse",
target.display_for_sentence(true, 1, false)),
format!(
"The trauma kit makes {}'s condition worse",
target.display_for_sentence(false, 1, false)
)
))
}
),
fail_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} attempts unsuccessfully to heal {} with a trauma kit\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} attempts unsuccessfully to heal {} with a trauma kit\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
),
success_effects: vec!(
UseEffect::BroadcastMessage {
messagef: Box::new(|player, _item, target| (
format!(
"{} expertly heals {} with a trauma kit\n",
&player.display_for_sentence(true, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(true, 1, false)
}
),
format!("{} expertly heals {} with a trauma kit\n",
&player.display_for_sentence(false, 1, true),
&if target.item_type == player.item_type && target.item_code == player.item_code {
player.pronouns.intensive.clone()
} else {
target.display_for_sentence(false, 1, false)
}
)))
},
UseEffect::ChangeTargetHealth {
delay_secs: 0, base_effect: 2, skill_multiplier: 8.0,
max_effect: 10,
message: Box::new(
|target|
(format!(
"FUUUCK! It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
),
format!(
"It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 10, base_effect: 2, skill_multiplier: 7.0,
max_effect: 9,
message: Box::new(
|target|
(format!(
"FUUUCK! It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
),
format!(
"It hurts {}, but also starts to soothe {}",
target.display_for_sentence(true, 1, false),
&target.pronouns.object
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 20, base_effect: 1, skill_multiplier: 6.0,
max_effect: 7,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 30, base_effect: 1, skill_multiplier: 5.0,
max_effect: 6,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 40, base_effect: 0, skill_multiplier: 4.0,
max_effect: 4,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 50, base_effect: 0, skill_multiplier: 3.0,
max_effect: 3,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
UseEffect::ChangeTargetHealth {
delay_secs: 60, base_effect: 0, skill_multiplier: 2.0,
max_effect: 2,
message: Box::new(
|target|
(format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(true, 1, false),
),
format!(
"The bandages soothe {}'s wounds",
target.display_for_sentence(false, 1, false),
))
)
},
),
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()
}),
becomes_on_spent: Some(EmptyMedicalBox),
..Default::default()
}
}
pub fn empty_data() -> PossessionData {
PossessionData {
display: "empty medical box",
details: "An empty box that looks like it once had something medical in it.",
aliases: vec!("box"),
..Default::default()
}
}