From 22fcc6417c3d0af8b292b52ff31ea91a17c05f67 Mon Sep 17 00:00:00 2001 From: Avi Weinstock Date: Sat, 6 Mar 2021 14:03:21 -0500 Subject: [PATCH] Make fireworks recursively shoot more fireworks (95% average replication). --- CHANGELOG.md | 1 + common/src/comp/body/object.rs | 12 ++++++- common/src/event.rs | 1 + common/src/states/basic_ranged.rs | 1 + common/src/states/charged_ranged.rs | 1 + common/src/states/repeater_ranged.rs | 1 + server/src/events/entity_creation.rs | 6 +++- server/src/events/inventory_manip.rs | 8 +---- server/src/events/mod.rs | 5 ++- server/src/sys/object.rs | 54 ++++++++++++++++++++++++++++ 10 files changed, 80 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9b690300..35e221fe66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - "Quest" given to new players converted to being a short tutorial - Items can be requested from the counterparty's inventory during trade. - Savanna grasses restricted to savanna, cacti to desert. +- Fireworks recursively shoot more fireworks. ### Removed diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 8a84786bd2..af4dc75a1d 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -1,4 +1,4 @@ -use crate::make_case_elim; +use crate::{comp::item::Reagent, make_case_elim}; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; @@ -227,4 +227,14 @@ impl Body { Body::Coins => "coins", } } + + pub fn for_firework(reagent: Reagent) -> Body { + match reagent { + Reagent::Blue => Body::FireworkBlue, + Reagent::Green => Body::FireworkGreen, + Reagent::Purple => Body::FireworkPurple, + Reagent::Red => Body::FireworkRed, + Reagent::Yellow => Body::FireworkYellow, + } + } } diff --git a/common/src/event.rs b/common/src/event.rs index f4b97f95e1..350649530e 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -65,6 +65,7 @@ pub enum ServerEvent { projectile: comp::Projectile, gravity: Option, speed: f32, + object: Option, }, Shockwave { properties: comp::shockwave::Properties, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index a0b5541578..c3d2726c2f 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -95,6 +95,7 @@ impl CharacterBehavior for Data { light: self.static_data.projectile_light, gravity: self.static_data.projectile_gravity, speed: self.static_data.projectile_speed, + object: None, }); update.character = CharacterState::BasicRanged(Data { diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 91c79a87f8..7981e3f998 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -149,6 +149,7 @@ impl CharacterBehavior for Data { gravity: self.static_data.projectile_gravity, speed: self.static_data.initial_projectile_speed + charge_frac * self.static_data.scaled_projectile_speed, + object: None, }); update.character = CharacterState::ChargedRanged(Data { diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index 9418336ca5..89fa6aca8a 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -163,6 +163,7 @@ impl CharacterBehavior for Data { light: self.static_data.projectile_light, gravity: self.static_data.projectile_gravity, speed: self.static_data.projectile_speed, + object: None, }); // Shoot projectiles diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 0f02d79cb4..2fb80f0bd9 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -10,7 +10,7 @@ use common::{ group, inventory::loadout::Loadout, shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop, - LightEmitter, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea, + LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea, }, outcome::Outcome, rtsim::RtSimEntity, @@ -120,6 +120,7 @@ pub fn handle_shoot( projectile: Projectile, gravity: Option, speed: f32, + object: Option, ) { let state = server.state_mut(); @@ -152,6 +153,9 @@ pub fn handle_shoot( if let Some(gravity) = gravity { builder = builder.with(gravity) } + if let Some(object) = object { + builder = builder.with(object) + } builder.build(); } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index f1adfee1f9..c1c9f8f450 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -644,13 +644,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv let mut new_entity = state .create_object(Default::default(), match kind { item::Throwable::Bomb => comp::object::Body::Bomb, - item::Throwable::Firework(reagent) => match reagent { - item::Reagent::Blue => comp::object::Body::FireworkBlue, - item::Reagent::Green => comp::object::Body::FireworkGreen, - item::Reagent::Purple => comp::object::Body::FireworkPurple, - item::Reagent::Red => comp::object::Body::FireworkRed, - item::Reagent::Yellow => comp::object::Body::FireworkYellow, - }, + item::Throwable::Firework(reagent) => comp::object::Body::for_firework(reagent), item::Throwable::TrainingDummy => comp::object::Body::TrainingDummy, }) .with(comp::Pos(pos.0 + Vec3::unit_z() * 0.25)) diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index d1e04c3616..afedfbb3a5 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -74,7 +74,10 @@ impl Server { projectile, gravity, speed, - } => handle_shoot(self, entity, dir, body, light, projectile, gravity, speed), + object, + } => handle_shoot( + self, entity, dir, body, light, projectile, gravity, speed, object, + ), ServerEvent::Shockwave { properties, pos, diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index d2577c0bbc..13a143f9c7 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -68,6 +68,60 @@ impl<'a> System<'a> for Sys { }, Object::Firework { owner, reagent } => { if vel.0.z < 0.0 { + const ENABLE_RECURSIVE_FIREWORKS: bool = true; + if ENABLE_RECURSIVE_FIREWORKS { + use common::{ + comp::{object, Body, Gravity, LightEmitter, Projectile}, + util::Dir, + }; + use rand::Rng; + use std::{f32::consts::PI, time::Duration}; + use vek::{Rgb, Vec3}; + let mut rng = rand::thread_rng(); + // Note that if the expected fireworks per firework is > 1, this will + // eventually cause enough server lag that more players can't log in. + // 0.25 * 2 + (0.70 - 0.25) * 1 = 0.5 + 0.45 = 0.95 + let num_fireworks = match rng.gen_range(0.0..1.0) { + x if x < 0.25 => 2, + x if x < 0.70 => 1, + _ => 0, + }; + for _ in 0..num_fireworks { + let speed: f32 = rng.gen_range(40.0..80.0); + let theta: f32 = rng.gen_range(0.0..2.0 * PI); + let phi: f32 = rng.gen_range(0.25 * PI..0.5 * PI); + let dir = Dir::from_unnormalized(Vec3::new( + theta.cos(), + theta.sin(), + phi.sin(), + )) + .expect("nonzero vector should normalize"); + server_emitter.emit(ServerEvent::Shoot { + entity, + dir, + body: Body::Object(object::Body::for_firework(*reagent)), + light: Some(LightEmitter { + animated: true, + flicker: 2.0, + strength: 2.0, + col: Rgb::new(1.0, 1.0, 0.0), + }), + projectile: Projectile { + hit_solid: Vec::new(), + hit_entity: Vec::new(), + time_left: Duration::from_secs(60), + owner: *owner, + ignore_group: true, + }, + gravity: Some(Gravity(1.0)), + speed, + object: Some(Object::Firework { + owner: *owner, + reagent: *reagent, + }), + }); + } + } server_emitter.emit(ServerEvent::Destroy { entity, cause: HealthSource::Suicide,