From 34e3cb5eb542a4163c6cd51755e0f1d92efcce67 Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Thu, 2 Jul 2020 17:53:01 -0400 Subject: [PATCH 1/4] Added spawning test dummy --- CHANGELOG.md | 1 + client/src/cmd.rs | 5 ++++ common/src/cmd.rs | 18 +++++++++++++ server/src/cmd.rs | 67 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 621684c177..3c7e0f489d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ability to wield 2 × 1h weapons and shields (Note: 1h weapons & shields are not currently avaliable, see [!1095](https://gitlab.com/veloren/veloren/-/merge_requests/1095) for more info) - Zoomable Map - M2 attack for hammer +- Spawnable training dummies ### Changed diff --git a/client/src/cmd.rs b/client/src/cmd.rs index 0e07f0365a..7c5502ba8b 100644 --- a/client/src/cmd.rs +++ b/client/src/cmd.rs @@ -32,6 +32,11 @@ impl TabComplete for ArgumentSpec { .filter(|string| string.starts_with(part)) .map(|c| c.to_string()) .collect(), + ArgumentSpec::Boolean(_, part, _) => vec!["true", "false"] + .iter() + .filter(|string| string.starts_with(part)) + .map(|c| c.to_string()) + .collect(), } } } diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 16fab4703b..812af83795 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -40,6 +40,7 @@ pub enum ChatCommand { Build, Debug, DebugColumn, + Dummy, Explosion, Faction, GiveExp, @@ -81,6 +82,7 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[ ChatCommand::Build, ChatCommand::Debug, ChatCommand::DebugColumn, + ChatCommand::Dummy, ChatCommand::Explosion, ChatCommand::Faction, ChatCommand::GiveExp, @@ -191,6 +193,7 @@ impl ChatCommand { "Prints some debug information about a column", NoAdmin, ), + ChatCommand::Dummy => cmd(vec![], "Spawns a training dummy", NoAdmin), ChatCommand::Explosion => cmd( vec![Float("radius", 5.0, Required)], "Explodes the ground around you", @@ -321,6 +324,7 @@ impl ChatCommand { Enum("alignment", ALIGNMENTS.clone(), Required), Enum("entity", ENTITIES.clone(), Required), Integer("amount", 1, Optional), + Boolean("ai", "true".to_string(), Optional), ], "Spawn a test entity", Admin, @@ -370,6 +374,7 @@ impl ChatCommand { ChatCommand::Build => "build", ChatCommand::Debug => "debug", ChatCommand::DebugColumn => "debug_column", + ChatCommand::Dummy => "dummy", ChatCommand::Explosion => "explosion", ChatCommand::Faction => "faction", ChatCommand::GiveExp => "give_exp", @@ -433,6 +438,7 @@ impl ChatCommand { ArgumentSpec::Message(_) => "{/.*/}", ArgumentSpec::SubCommand => "{} {/.*/}", ArgumentSpec::Enum(_, _, _) => "{}", + ArgumentSpec::Boolean(_, _, _) => "{}", }) .collect::>() .join(" ") @@ -514,6 +520,11 @@ pub enum ArgumentSpec { /// * Predefined string completions /// * whether it's optional Enum(&'static str, Vec, Requirement), + /// The argument is likely a boolean. The associated values are + /// * label + /// * suggested tab-completion + /// * whether it's optional + Boolean(&'static str, String, Requirement), } impl ArgumentSpec { @@ -569,6 +580,13 @@ impl ArgumentSpec { format! {"[{}]", label} } }, + ArgumentSpec::Boolean(label, _, req) => { + if &Requirement::Required == req { + format!("<{}>", label) + } else { + format!("[{}]", label) + } + }, } } } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 03259a291b..ebfac3b3b1 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -66,6 +66,7 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler { ChatCommand::Build => handle_build, ChatCommand::Debug => handle_debug, ChatCommand::DebugColumn => handle_debug_column, + ChatCommand::Dummy => handle_spawn_training_dummy, ChatCommand::Explosion => handle_explosion, ChatCommand::Faction => handle_faction, ChatCommand::GiveExp => handle_give_exp, @@ -497,8 +498,15 @@ fn handle_spawn( args: String, action: &ChatCommand, ) { - match scan_fmt_some!(&args, &action.arg_fmt(), String, npc::NpcBody, String) { - (Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount) => { + match scan_fmt_some!( + &args, + &action.arg_fmt(), + String, + npc::NpcBody, + String, + String + ) { + (Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount, opt_ai) => { if let Some(alignment) = parse_alignment(target, &opt_align) { let amount = opt_amount .and_then(|a| a.parse().ok()) @@ -506,6 +514,8 @@ fn handle_spawn( .unwrap_or(1) .min(10); + let ai = opt_ai.unwrap_or("true".to_string()); + match server.state.read_component_cloned::(target) { Some(pos) => { let agent = @@ -524,7 +534,7 @@ fn handle_spawn( let body = body(); - let new_entity = server + let mut entity_base = server .state .create_npc( pos, @@ -534,9 +544,13 @@ fn handle_spawn( ) .with(comp::Vel(vel)) .with(comp::MountState::Unmounted) - .with(agent.clone()) - .with(alignment) - .build(); + .with(alignment); + + if ai == "true".to_string() { + entity_base = entity_base.with(agent.clone()); + } + + let new_entity = entity_base.build(); if let Some(uid) = server.state.ecs().uid_from_entity(new_entity) { server.notify_client( @@ -568,6 +582,47 @@ fn handle_spawn( } } +fn handle_spawn_training_dummy( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + _args: String, + _action: &ChatCommand, +) { + match server.state.read_component_cloned::(target) { + Some(pos) => { + let vel = Vec3::new( + rand::thread_rng().gen_range(-2.0, 3.0), + rand::thread_rng().gen_range(-2.0, 3.0), + 10.0, + ); + + let body = comp::Body::Object(comp::object::Body::Scarecrow); + + server + .state + .create_npc( + pos, + comp::Stats::new("Training Dummy".to_string(), body), + comp::Loadout::default(), + body, + ) + .with(comp::Vel(vel)) + .with(comp::MountState::Unmounted) + .build(); + + server.notify_client( + client, + ChatType::CommandInfo.server_msg(format!("Spawned a training dummy")), + ); + }, + None => server.notify_client( + client, + ChatType::CommandError.server_msg("You have no position!"), + ), + } +} + fn handle_players( server: &mut Server, client: EcsEntity, From d2941fd54e57e3e49f3dcf652a0bbff90734eb14 Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Thu, 2 Jul 2020 18:13:21 -0400 Subject: [PATCH 2/4] Fixed clippy issues --- server/src/cmd.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index ebfac3b3b1..d9dcae1471 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -514,7 +514,7 @@ fn handle_spawn( .unwrap_or(1) .min(10); - let ai = opt_ai.unwrap_or("true".to_string()); + let ai = opt_ai.unwrap_or_else(|| "true".to_string()); match server.state.read_component_cloned::(target) { Some(pos) => { @@ -546,7 +546,7 @@ fn handle_spawn( .with(comp::MountState::Unmounted) .with(alignment); - if ai == "true".to_string() { + if ai == "true" { entity_base = entity_base.with(agent.clone()); } @@ -613,7 +613,7 @@ fn handle_spawn_training_dummy( server.notify_client( client, - ChatType::CommandInfo.server_msg(format!("Spawned a training dummy")), + ChatType::CommandInfo.server_msg("Spawned a training dummy"), ); }, None => server.notify_client( From 8e2006c27e2e6f82c2fbd89d63a89e0eed85dd14 Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Fri, 3 Jul 2020 12:16:55 -0400 Subject: [PATCH 3/4] Prevent xp gain from training dummy kill --- server/src/cmd.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/cmd.rs b/server/src/cmd.rs index d9dcae1471..626730547c 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -599,14 +599,14 @@ fn handle_spawn_training_dummy( let body = comp::Body::Object(comp::object::Body::Scarecrow); + let mut stats = comp::Stats::new("Training Dummy".to_string(), body); + + // Level 0 will prevent exp gain from kill + stats.level.set_level(0); + server .state - .create_npc( - pos, - comp::Stats::new("Training Dummy".to_string(), body), - comp::Loadout::default(), - body, - ) + .create_npc(pos, stats, comp::Loadout::default(), body) .with(comp::Vel(vel)) .with(comp::MountState::Unmounted) .build(); From 30d8f03e7b7eec5cd115e52b1c49c7a9a345460b Mon Sep 17 00:00:00 2001 From: Forest Anderson Date: Fri, 3 Jul 2020 13:33:37 -0400 Subject: [PATCH 4/4] Added proper training dummy model --- assets/voxygen/voxel/object/training_dummy.vox | Bin 0 -> 6504 bytes common/src/comp/body/object.rs | 5 ++++- server/src/cmd.rs | 2 +- server/src/events/entity_manipulation.rs | 4 ++++ voxygen/src/scene/figure/load.rs | 1 + 5 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 assets/voxygen/voxel/object/training_dummy.vox diff --git a/assets/voxygen/voxel/object/training_dummy.vox b/assets/voxygen/voxel/object/training_dummy.vox new file mode 100644 index 0000000000000000000000000000000000000000..47c096991cf9f5c0ac5d8e66e3046b01d002ce7b GIT binary patch literal 6504 zcmciGTdby6SqJd8-NiKPRYE+Y&DOCGL zXUSeSdp;t`KC6XFqr0{gIRdfBsaY*l8l9zjT>`OsT{6YKs!i>O*Vp-CUT60@UrJ$i zud{o#kF$H4-IIOPOSAXwT3BS3^C>QR%Y_uy^O+Ra3puJG*oO-#275I``)IF5H6)Ku z@+v80`)sd9H5BNSP4W@(4$c88{K+|N6)WOj!3f4YN1*;`e85WB|WtquCv!A zEYEo|lE@S)%le$FD}hKNQ>ZjLOOPWFNn{F@MrVm~1R{w{q0;CqNsd4ykttLfoh8c= zh$J$FN~05sK84D<9D6b>$F4>anL?%ME$cD&eawB!kjNA&jm{F}2t*Q@LZ#7Jq8x!p zB2%a|I!lrx5J_YTl}2aDas(oYOrg@~tVM=MB2%a|*5$Z!IPM&dJBQP z(m9-bvazfuox@4zaMC%PypqRO{Shm%*9AWI;Uf-J?l(&%ht=O`cL2}Dwq zr&w1SosI0Am)LT%DUYiA{i7p0X@~NFr0HG&-BZY;jISmPjH~s5JUvrfyvfL=u@orLj!g z&VKu1rdu!bw)5Y1{@YK+dE5DKJO6FxzwP|DpKN+vW?r_>T8SJb_3eQ>ZjL8`&xDn3p_(NFr0HG&)C^lRPVdNFr0HG&&pR?EPeU0+B?fP-%2F zvU8Cy@&qD@Org@~Y!0*4x!0Y8phgmzLZ#_-b(wa}YuC@V-Ggqu%)92b>-WR1-w(Uy zwQF9x=Cx~HyM90H`u(tLUb4%sdC3w7kttLfosH~V zvLu{6e>-xvrKyj>$G<J@b^C z_snz8Jon6V&ph|cbI&~Gm>1bacG)veSrVB-rO{>T8S zJb_3eQ>ZjL8`(L^M|lE~M5a(_bT+bcl27skB8g0)(&%ht=j?v7Jb_3eQ>ZjLo5O5z zHbs_5B2%a|`eCLzYa)qEq0(69{eyMhH;?^`(K?YSRM#5adRg|(LT=eNi+!`$H;a9< z*f)!Pvyfw1^$-%0)RMiAQ$Z{kyg-X-wEXBDLIUZk(HRuO@HIXS)*P6OU{iv@dGKK0|Q`e-Q^hsn2m8Q35?=O3QBr=6c(|gMse)+YN ze~uo0-G2M+eP7VnR~|J*O%`8o1f{}9jC|6yRRG9 zefZ{a_KBB|>CQN&2iurFe_~AEJUx!xGmWheOk@AiY5e?GrcoZ8#*s&+ankg&^(-s<%qE@OJ^=$O8CYJB{K$H&!QxMqC+ zm-fbZECFAn1zid4I{@0CXe*ZVd zzh8M^-2D90<5e$t?s(H{ZXEBu|7GLBH%{Y`-<-x1zdenwe`*@HUAsG8@x1-<&f8uz z9(w)D$Ne{*9uK^9Z+!9%FBng~>&4^Tuf29W`0h84%O8Bl_{4|bHy-}2bK}w9dvH8; z^<(4NZ+vd_-pBUINTIbGL7&2{WSjdAE)u~12>M(K62~$=9gYK{^MWn8xMWr*!bjMof=>L z-p=^Jc<%qp{oj4l4L|k%Z@u-_@kcLvV!Zg4&yQDr{G(&%k)83aznI4N-!Y9Z-gx6U zd-m*j|ML&VuiW*uF+K9|xaOg2#?znq$qYZd>wD+gYsc@r;IZ-QSAKfD=Mx_r+wa;M z-~H+HlcKqT8 zKR#al(I>{6{_N}HzOOtx?zrQQ@uO*ssWAR)tj|v4hky5z_xD5JU;kI%NASm=v!7NE Un?J30c>QPfe*DBg`|;EN0JnAEm;e9( literal 0 HcmV?d00001 diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index e3121eb9a5..f98f1bdb92 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -56,6 +56,7 @@ pub enum Body { ArrowSnake = 50, CampfireLit = 51, BoltFireBig = 52, + TrainingDummy = 53, } impl Body { @@ -65,7 +66,7 @@ impl Body { } } -pub const ALL_OBJECTS: [Body; 53] = [ +pub const ALL_OBJECTS: [Body; 54] = [ Body::Arrow, Body::Bomb, Body::Scarecrow, @@ -119,6 +120,7 @@ pub const ALL_OBJECTS: [Body; 53] = [ Body::BoltFire, Body::BoltFireBig, Body::ArrowSnake, + Body::TrainingDummy, ]; impl Body { @@ -177,6 +179,7 @@ impl Body { Body::BoltFire => "bolt_fire", Body::BoltFireBig => "bolt_fire_big", Body::ArrowSnake => "arrow_snake", + Body::TrainingDummy => "training_dummy", } } } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 626730547c..70886e603a 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -597,7 +597,7 @@ fn handle_spawn_training_dummy( 10.0, ); - let body = comp::Body::Object(comp::object::Body::Scarecrow); + let body = comp::Body::Object(comp::object::Body::TrainingDummy); let mut stats = comp::Stats::new("Training Dummy".to_string(), body); diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index d2edbf6b44..dadf62fe65 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -24,6 +24,10 @@ pub fn handle_damage(server: &Server, uid: Uid, change: HealthChange) { } } +/// Handle an entity dying. If it is a player, it will send a message to all +/// other players. If the entity that killed it had stats, then give it exp for +/// the kill. Experience given is equal to the level of the entity that was +/// killed times 10. pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSource) { let state = server.state_mut(); diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 51d0f66720..3a61c147a6 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -3020,6 +3020,7 @@ pub fn mesh_object( Body::ArrowSnake => ("weapon.projectile.snake-arrow", Vec3::new(-1.5, -6.5, 0.0)), Body::BoltFire => ("weapon.projectile.fire-bolt-0", Vec3::new(-3.0, -5.5, -3.0)), Body::BoltFireBig => ("weapon.projectile.fire-bolt-1", Vec3::new(-6.0, -6.0, -6.0)), + Body::TrainingDummy => ("object.training_dummy", Vec3::new(-7.0, -5.0, 0.0)), }; load_mesh(name, offset, generate_mesh) }