diff --git a/blastmud_game/src/models/item.rs b/blastmud_game/src/models/item.rs index da91697..5521757 100644 --- a/blastmud_game/src/models/item.rs +++ b/blastmud_game/src/models/item.rs @@ -736,6 +736,7 @@ pub struct Item { pub total_xp: u64, pub urges: Option, pub weight: u64, + pub raddamage: u64, } impl Item { @@ -834,6 +835,7 @@ impl Default for Item { presence_target: None, pronouns: Pronouns::default_inanimate(), queue: VecDeque::new(), + raddamage: 0, sex: None, special_data: None, static_special_data: None, diff --git a/blastmud_game/src/models/task.rs b/blastmud_game/src/models/task.rs index 58d3fcc..5308a46 100644 --- a/blastmud_game/src/models/task.rs +++ b/blastmud_game/src/models/task.rs @@ -80,10 +80,16 @@ pub enum TaskDetails { ChargeItem { item: String, }, + // Environment impacting the player hidden variables ApplyEnvironmentalEffects { on_player_type: String, on_player_code: String, }, + // Player hidden variables from environment impacting health + themselves + ApplyEnvironmentalConsequences { + on_player_type: String, + on_player_code: String, + }, } impl TaskDetails { pub fn name(self: &Self) -> &'static str { @@ -114,6 +120,7 @@ impl TaskDetails { DischargeLight { .. } => "DischargeLight", ChargeItem { .. } => "ChargeItem", ApplyEnvironmentalEffects { .. } => "ApplyEnvironmentalEffects", + ApplyEnvironmentalConsequences { .. } => "ApplyEnvironmentalConsequences", // Don't forget to add to TASK_HANDLER_REGISTRY in regular_tasks.rs too. } } diff --git a/blastmud_game/src/regular_tasks.rs b/blastmud_game/src/regular_tasks.rs index 0d2d0c1..b783e65 100644 --- a/blastmud_game/src/regular_tasks.rs +++ b/blastmud_game/src/regular_tasks.rs @@ -72,7 +72,14 @@ fn task_handler_registry( ("ExpireBuff", tempbuff::EXPIRE_BUFF_TASK), ("DischargeLight", lights::DISCHARGE_TASK), ("ChargeItem", charging::TASK_HANDLER), - ("ApplyEnvironmentalEffects", environment::TASK_HANDLER), + ( + "ApplyEnvironmentalEffects", + environment::EFFECT_TASK_HANDLER, + ), + ( + "ApplyEnvironmentalConsequences", + environment::CONSEQUENCE_TASK_HANDLER, + ), ] .into_iter() .collect() diff --git a/blastmud_game/src/services/combat.rs b/blastmud_game/src/services/combat.rs index 02837b2..8bb210a 100644 --- a/blastmud_game/src/services/combat.rs +++ b/blastmud_game/src/services/combat.rs @@ -761,6 +761,7 @@ pub async fn handle_resurrect(trans: &DBTrans, player: &mut Item) -> DResult, @@ -42,10 +43,12 @@ pub async fn ensure_appropriate_environment_handler_after_movement( None => return Ok(()), Some(r) => r, }; - match room.material_type { + let water_effects = match room.material_type { MaterialType::WaterSurface | MaterialType::Underwater => true, _ => false, - } + }; + let env_effects = room.environment.radiation > 0; + water_effects || env_effects }; let existing_task = ctx @@ -79,7 +82,7 @@ pub async fn ensure_appropriate_environment_handler_after_movement( } #[async_trait] -impl TaskHandler for EnvironmentHandler { +impl TaskHandler for EffectEnvironmentHandler { async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult> { let (player_type, player_code) = match &ctx.task.details { TaskDetails::ApplyEnvironmentalEffects { @@ -118,7 +121,8 @@ impl TaskHandler for EnvironmentHandler { Some(r) => r, }; - let need_save = water_environment_effects(ctx, &room, &mut player).await?; + let need_save = water_environment_effects(ctx, &room, &mut player).await? + || rad_environment_effects(ctx, &room, &mut player).await?; if need_save { ctx.trans.save_item_model(&player).await?; @@ -128,6 +132,56 @@ impl TaskHandler for EnvironmentHandler { } } +#[async_trait] +impl TaskHandler for ConsequenceEnvironmentHandler { + async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult> { + let (player_type, player_code) = match &ctx.task.details { + TaskDetails::ApplyEnvironmentalConsequences { + on_player_type, + on_player_code, + } => (on_player_type, on_player_code), + x => { + warn!( + "ConsequenceEnvironmentHandler called with bad TaskDetail type: {:#?}", + x + ); + return Ok(None); + } + }; + + let player = match ctx + .trans + .find_item_by_type_code(&player_type, &player_code) + .await? + { + None => return Ok(None), + Some(p) => p, + }; + let mut player = (*player).clone(); + + let mut anything_left = false; + if player.raddamage > 0 { + if player.raddamage <= 100 { + player.raddamage = 0; + } else { + anything_left = true; + if player.raddamage > 2000 { + let damage = (player.raddamage - 1000) / 1000; + let msg = format!("{} feels unwell", &player.display_for_sentence(1, true)); + change_health(ctx.trans, -(damage as i64), &mut player, &msg).await?; + } + player.raddamage -= 100; + } + } + ctx.trans.save_item_model(&player).await?; + Ok(if anything_left { + Some(time::Duration::from_secs(60)) + } else { + None + }) + } +} + pub async fn water_environment_effects( ctx: &mut TaskRunContext<'_>, room: &Room, @@ -194,4 +248,40 @@ pub async fn water_environment_effects( Ok(true) } -pub static TASK_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &EnvironmentHandler; +pub async fn rad_environment_effects( + ctx: &mut TaskRunContext<'_>, + room: &Room, + player_item: &mut Item, +) -> DResult { + if room.environment.radiation == 0 { + return Ok(false); + } + + player_item.raddamage += room.environment.radiation; + let existing_task = ctx + .trans + .fetch_specific_task("ApplyEnvironmentalConsequences", &player_item.refstr()) + .await?; + if existing_task.is_none() { + ctx.trans + .upsert_task(&Task { + meta: TaskMeta { + task_code: player_item.refstr(), + next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(60).unwrap(), + ..Default::default() + }, + details: TaskDetails::ApplyEnvironmentalConsequences { + on_player_type: player_item.item_type.clone(), + on_player_code: player_item.item_code.clone(), + }, + }) + .await?; + } + + Ok(true) +} + +pub static EFFECT_TASK_HANDLER: &'static (dyn TaskHandler + Sync + Send) = + &EffectEnvironmentHandler; +pub static CONSEQUENCE_TASK_HANDLER: &'static (dyn TaskHandler + Sync + Send) = + &ConsequenceEnvironmentHandler; diff --git a/blastmud_game/src/static_content/dumper.rs b/blastmud_game/src/static_content/dumper.rs index 8da5a95..1c57ee1 100644 --- a/blastmud_game/src/static_content/dumper.rs +++ b/blastmud_game/src/static_content/dumper.rs @@ -51,6 +51,7 @@ fn room_to_simpleroom(room: &Room) -> Option> { scavtable: room.scavtable.clone(), scan_code: room.scan_code.clone(), effects: None, + environment: room.environment.clone(), extra: (), }) } diff --git a/blastmud_game/src/static_content/room.rs b/blastmud_game/src/static_content/room.rs index 2803590..a191025 100644 --- a/blastmud_game/src/static_content/room.rs +++ b/blastmud_game/src/static_content/room.rs @@ -542,6 +542,7 @@ pub struct Room { pub exit_trigger: Option>, pub sell_trigger: Option>, pub scavtable: ScavtableType, + pub environment: RoomEnvironment, } impl Default for Room { @@ -570,10 +571,23 @@ impl Default for Room { exit_trigger: None, sell_trigger: None, scavtable: ScavtableType::Nothing, + environment: Default::default(), } } } +#[derive(Serialize, Deserialize, Clone)] +#[serde(default)] +pub struct RoomEnvironment { + pub radiation: u64, // mSv/10s tick +} + +impl Default for RoomEnvironment { + fn default() -> Self { + Self { radiation: 0 } + } +} + #[derive(Serialize, Deserialize)] #[serde(default)] pub struct SimpleRoom { @@ -601,6 +615,7 @@ pub struct SimpleRoom { pub journal: Option, pub scavtable: ScavtableType, pub effects: Option>, + pub environment: RoomEnvironment, pub extra: T, } @@ -645,6 +660,7 @@ impl Into for SimpleRoom { }), sell_trigger: None, scavtable: self.scavtable, + environment: self.environment, } } } @@ -674,6 +690,7 @@ impl<'a, T: Default> Default for SimpleRoom { scavtable: ScavtableType::Nothing, effects: None, extra: Default::default(), + environment: Default::default(), } } } diff --git a/blastmud_game/src/static_content/room/melbs.yaml b/blastmud_game/src/static_content/room/melbs.yaml index 1fdf094..3ad0269 100644 --- a/blastmud_game/src/static_content/room/melbs.yaml +++ b/blastmud_game/src/static_content/room/melbs.yaml @@ -1682,6 +1682,21 @@ stock_list: - possession_type: !RadSafetyTest list_price: 1000 +- zone: oorans + code: oorans_gift + name: OORANS Gift Shop + description: |- + A brightly coloured room, each wall a different primary colour. Rows of merchandise hang neatly on racks, while a shop keeper stands near the front, his hands clasped in anticipation of a sale + short: G$ + grid_coords: + x: 1 + y: 1 + z: 0 + exits: + - direction: north + stock_list: + - possession_type: !RadSafetyTest + list_price: 1000 - zone: melbs code: melbs_williamsst_collinsst name: Williams St & Collins St diff --git a/blastmud_game/src/static_content/room/northern_radfields.yaml b/blastmud_game/src/static_content/room/northern_radfields.yaml index a4e5ae9..7841952 100644 --- a/blastmud_game/src/static_content/room/northern_radfields.yaml +++ b/blastmud_game/src/static_content/room/northern_radfields.yaml @@ -34,6 +34,8 @@ exits: - direction: north - direction: south + environment: + radiation: 50 - zone: northern_radfields code: northrad_r6 name: Outside the abandoned windfarm @@ -46,6 +48,8 @@ exits: - direction: north - direction: south + environment: + radiation: 150 - zone: northern_radfields code: northrad_q6 name: Crystal clear pond @@ -58,6 +62,8 @@ exits: - direction: northwest - direction: south + environment: + radiation: 300 - zone: northern_radfields code: northrad_p5 name: The Bend Community Hall @@ -70,6 +76,8 @@ exits: - direction: north - direction: southeast + environment: + radiation: 205 - zone: northern_radfields code: northrad_o5 name: Gorge Southbank @@ -85,6 +93,8 @@ height: -10 difficulty: 10 - direction: south + environment: + radiation: 150 - zone: northern_radfields code: northrad_n5 name: Gorge River @@ -113,4 +123,3 @@ material_type: !Underwater exits: - direction: up -