diff --git a/src/actor.rs b/src/actor.rs index 7daa8a9..d4d7779 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -41,10 +41,12 @@ pub struct SendMessageEvent { pub struct ChatScriptEvent { name: String, param: String, + param2: String, } #[derive(Component)] pub struct Actor { + pub id: String, pub hp: f32, pub m: f32, // mass pub v: Vec3, // velocity @@ -55,6 +57,7 @@ pub struct Actor { impl Default for Actor { fn default() -> Self { Self { + id: "".to_string(), hp: 100.0, m: 100.0, v: Vec3::ZERO, @@ -340,6 +343,7 @@ pub fn handle_send_messages( ew_chatscript.send(ChatScriptEvent { name: branch.script.clone(), param: branch.script_parameter.clone(), + param2: branch.script_parameter2.clone(), }); } } @@ -416,6 +420,7 @@ pub fn handle_conversations( ew_chatscript.send(ChatScriptEvent { name: branch.script.clone(), param: branch.script_parameter.clone(), + param2: branch.script_parameter2.clone(), }); } } @@ -423,13 +428,37 @@ pub fn handle_conversations( pub fn handle_chat_scripts( mut er_chatscript: EventReader, + mut q_actor: Query<(&mut Actor, &mut Suit), Without>, mut q_player: Query<(&mut Actor, &mut Suit), With>, ) { for script in er_chatscript.read() { match script.name.as_str() { - "refilloxygen" => if let Ok(amount) = script.param.parse::() { + "refilloxygen" => if let Ok(mut amount) = script.param.parse::() { for (mut _actor, mut suit) in q_player.iter_mut() { - suit.oxygen = (suit.oxygen + amount).clamp(0.0, suit.oxygen_max); + if script.param2.is_empty() { + suit.oxygen = (suit.oxygen + amount).clamp(0.0, suit.oxygen_max); + } + else { + let mut found_other = false; + info!("param2={}", script.param2); + for (other_actor, mut other_suit) in q_actor.iter_mut() { + if !other_actor.id.is_empty() { + info!("ID={}", other_actor.id); + } + if other_actor.id == script.param2 { + found_other = true; + amount = amount + .clamp(0.0, other_suit.oxygen) + .clamp(0.0, suit.oxygen_max - suit.oxygen); + other_suit.oxygen = other_suit.oxygen - amount; + suit.oxygen = (suit.oxygen + amount).clamp(0.0, suit.oxygen_max); + break; + } + } + if !found_other { + error!("Script error: could not find actor with ID `{}`", script.param2); + } + } } } else { error!("Invalid parameter for command `{}`: `{}`", script.name, script.param); diff --git a/src/defs.txt b/src/defs.txt index b7d68b1..de3f4e9 100644 --- a/src/defs.txt +++ b/src/defs.txt @@ -122,8 +122,10 @@ actor 10 0 70 suit lvl info actor -300 0 40 suit + id drifter name "Drifter" chatid drifter + oxygen 0.08 chat drifter name "Drifter" msg 5 INIT noresponse "Requesting permission to communicate..." @@ -134,7 +136,7 @@ actor -300 0 40 suit lvl info choice 0 outcold EXIT "Damn, it's gotta be moldy in that suit. How long has it been drifting?" choice 0 outcold EXIT "Harvest some oxygen" - script refilloxygen 0.08 + script refilloxygen 1 drifter msg 0 outcold EXIT "" chat error diff --git a/src/world.rs b/src/world.rs index f17a6d8..5ec6427 100644 --- a/src/world.rs +++ b/src/world.rs @@ -231,6 +231,7 @@ struct ParserState { chat: String, // Actor fields + id: String, pos: Vec3, model: String, model_scale: f32, @@ -245,6 +246,7 @@ struct ParserState { thrust_sideways: f32, thrust_back: f32, reaction_wheels: f32, + oxygen: f32, // Chat fields delay: f64, @@ -267,6 +269,7 @@ impl Default for ParserState { name: "NONAME".to_string(), chat: "".to_string(), + id: "".to_string(), pos: Vec3::new(0.0, 0.0, 0.0), model: "".to_string(), model_scale: 1.0, @@ -281,6 +284,7 @@ impl Default for ParserState { thrust_sideways: default_engine.thrust_forward, thrust_back: default_engine.thrust_back, reaction_wheels: default_engine.reaction_wheels, + oxygen: nature::OXY_D, delay: 0.0, text: "".to_string(), @@ -339,6 +343,7 @@ impl ParserState { fn spawn_actor(&mut self, commands: &mut Commands, asset_server: &Res) { let component_actor = actor::Actor { angular_momentum: self.angular_momentum, + id: self.id.clone(), ..default() }; let component_lifeform = actor::LifeForm::default(); @@ -353,7 +358,11 @@ impl ParserState { thrust_sideways: self.thrust_sideways, reaction_wheels: self.reaction_wheels, }; - let component_suit = actor::Suit::default(); + let component_suit = actor::Suit { + oxygen: self.oxygen, + oxygen_max: nature::OXY_D, + ..default() + }; let component_model = SceneBundle { transform: Transform { translation: self.pos, @@ -367,7 +376,7 @@ impl ParserState { // TODO: is there a more dynamic way to construct this...? info!("Spawning actor {} with model {} at {}/{}/{}", self.name, self.model, self.pos.x, self.pos.y, self.pos.z); - if self.is_alive { + if self.is_lifeform { if !self.chat.is_empty() { commands.spawn(( component_actor, @@ -484,6 +493,9 @@ pub fn load_defs( continue; } } + ["id", id] => { + state.id = id.to_string(); + } ["alive", "yes"] => { state.is_alive = true; state.is_lifeform = true; @@ -492,6 +504,17 @@ pub fn load_defs( ["vehicle", "yes"] => { state.is_vehicle = true; } + ["oxygen", amount] => { + if let Ok(amount) = amount.parse::() { + state.is_lifeform = true; + state.is_suited = true; + state.oxygen = amount; + } + else { + error!("Can't parse float: {line}"); + continue; + } + } ["pronoun", pronoun] => { state.pronoun = pronoun.to_string(); }