From ddf426c74b07ee274c07798b4133dea59323cc72 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 8 Nov 2020 15:11:00 -0600 Subject: [PATCH 01/10] Created ron files for abilities of the base 6 weapons. --- assets/common/abilities/axe/leap.ron | 13 ++++ assets/common/abilities/axe/spin.ron | 14 +++++ assets/common/abilities/axe/tempbasic.ron | 10 +++ assets/common/abilities/bow/basic.ron | 36 +++++++++++ assets/common/abilities/bow/charged.ron | 16 +++++ assets/common/abilities/bow/repeater.ron | 39 ++++++++++++ assets/common/abilities/hammer/charged.ron | 13 ++++ assets/common/abilities/hammer/leap.ron | 13 ++++ assets/common/abilities/hammer/tempbasic.ron | 10 +++ .../common/abilities/sceptre/healingbeam.ron | 14 +++++ .../common/abilities/sceptre/healingbomb.ron | 63 +++++++++++++++++++ assets/common/abilities/staff/firebomb.ron | 45 +++++++++++++ .../common/abilities/staff/fireshockwave.ron | 14 +++++ .../common/abilities/staff/flamethrower.ron | 14 +++++ assets/common/abilities/sword/dash.ron | 17 +++++ assets/common/abilities/sword/spin.ron | 14 +++++ .../common/abilities/sword/triplestrike.ron | 49 +++++++++++++++ 17 files changed, 394 insertions(+) create mode 100644 assets/common/abilities/axe/leap.ron create mode 100644 assets/common/abilities/axe/spin.ron create mode 100644 assets/common/abilities/axe/tempbasic.ron create mode 100644 assets/common/abilities/bow/basic.ron create mode 100644 assets/common/abilities/bow/charged.ron create mode 100644 assets/common/abilities/bow/repeater.ron create mode 100644 assets/common/abilities/hammer/charged.ron create mode 100644 assets/common/abilities/hammer/leap.ron create mode 100644 assets/common/abilities/hammer/tempbasic.ron create mode 100644 assets/common/abilities/sceptre/healingbeam.ron create mode 100644 assets/common/abilities/sceptre/healingbomb.ron create mode 100644 assets/common/abilities/staff/firebomb.ron create mode 100644 assets/common/abilities/staff/fireshockwave.ron create mode 100644 assets/common/abilities/staff/flamethrower.ron create mode 100644 assets/common/abilities/sword/dash.ron create mode 100644 assets/common/abilities/sword/spin.ron create mode 100644 assets/common/abilities/sword/triplestrike.ron diff --git a/assets/common/abilities/axe/leap.ron b/assets/common/abilities/axe/leap.ron new file mode 100644 index 0000000000..dc0c2fb266 --- /dev/null +++ b/assets/common/abilities/axe/leap.ron @@ -0,0 +1,13 @@ +LeapMelee( + energy_cost: 450, + buildup_duration: 200, + movement_duration: 200, + swing_duration: 200, + recover_duration: 200, + base_damage: 240, + knockback: 12.0, + range: 4.5, + max_angle: 30.0, + forward_leap_strength: 28.0, + vertical_leap_strength: 8.0, +), \ No newline at end of file diff --git a/assets/common/abilities/axe/spin.ron b/assets/common/abilities/axe/spin.ron new file mode 100644 index 0000000000..1ec1f743fb --- /dev/null +++ b/assets/common/abilities/axe/spin.ron @@ -0,0 +1,14 @@ +SpinMelee( + buildup_duration: 100, + swing_duration: 250, + recover_duration: 100, + base_damage: 60, + knockback: 0.0, + range: 3.5, + energy_cost: 100, + is_infinite: true, + is_helicopter: true, + is_interruptible: false, + forward_speed: 0.0, + num_spins: 1, +), \ No newline at end of file diff --git a/assets/common/abilities/axe/tempbasic.ron b/assets/common/abilities/axe/tempbasic.ron new file mode 100644 index 0000000000..001e96f0f6 --- /dev/null +++ b/assets/common/abilities/axe/tempbasic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 600, + swing_duration: 100, + recover_duration: 300, + base_damage: 120, + knockback: 0.0, + range: 3.5, + max_angle: 20.0, +), \ No newline at end of file diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/basic.ron new file mode 100644 index 0000000000..8155011f63 --- /dev/null +++ b/assets/common/abilities/bow/basic.ron @@ -0,0 +1,36 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 100, + recover_duration: 400, + projectile: ( + hit_solid: [Stick], + hit_entity: [ + Damage(Some(OutOfGroup), ( + source: Projectile, + value: 40.0, + )), + Knockback(Away(10.0)), + RewardEnergy(50), + Vanish, + /*projectile::Effect::Buff { + buff: Buff::new( + BuffKind::Bleeding, + BuffData { + strength: 20.0 * self.base_power(), + duration: Some(Duration::from_secs(5)), + }, + vec![BuffCategory::Physical], + BuffSource::Unknown, + ), + chance: Some(0.10), + },*/ + ], + time_left: 15, // seconds + owner: None, + ignore_group: true, + ), + projectile_body: Object(Arrow), + projectile_light: None, + projectile_gravity: Some(Gravity(0.2)), + projectile_speed: 100.0, +), \ No newline at end of file diff --git a/assets/common/abilities/bow/charged.ron b/assets/common/abilities/bow/charged.ron new file mode 100644 index 0000000000..1f3ebd47c1 --- /dev/null +++ b/assets/common/abilities/bow/charged.ron @@ -0,0 +1,16 @@ +ChargedRanged( + energy_cost: 0, + energy_drain: 300, + initial_damage: 40, + max_damage: 200, + initial_knockback: 10.0, + max_knockback: 20.0, + buildup_duration: 100, + charge_duration: 1500, + recover_duration: 500, + projectile_body: Object(MultiArrow), + projectile_light: None, + projectile_gravity: Some(Gravity(0.2)), + initial_projectile_speed: 100.0, + max_projectile_speed: 500.0, +), \ No newline at end of file diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron new file mode 100644 index 0000000000..e27dfb7dc7 --- /dev/null +++ b/assets/common/abilities/bow/repeater.ron @@ -0,0 +1,39 @@ +RepeaterRanged( + energy_cost: 450, + movement_duration: 300, + buildup_duration: 200, + shoot_duration: 200, + recover_duration: 800, + leap: Some(5.0), + projectile: ( + hit_solid: [Stick], + hit_entity: [ + Damage(Some(OutOfGroup), ( + source: Projectile, + value: 40.0, + )), + Knockback(Away(10.0)), + Vanish, + /*projectile::Effect::Buff { + buff: Buff::new( + BuffKind::Bleeding, + BuffData { + strength: 20.0 * self.base_power(), + duration: Some(Duration::from_secs(5)), + }, + vec![BuffCategory::Physical], + BuffSource::Unknown, + ), + chance: Some(0.10), + },*/ + ], + time_left: 15, // seconds + owner: None, + ignore_group: true, + ), + projectile_body: Object(Arrow), + projectile_light: None, + projectile_gravity: Some(Gravity(0.2)), + projectile_speed: 100.0, + reps_remaining: 5, +), \ No newline at end of file diff --git a/assets/common/abilities/hammer/charged.ron b/assets/common/abilities/hammer/charged.ron new file mode 100644 index 0000000000..4998616bd1 --- /dev/null +++ b/assets/common/abilities/hammer/charged.ron @@ -0,0 +1,13 @@ +ChargedMelee( + energy_cost: 1, + energy_drain: 300, + initial_damage: 10, + max_damage: 170, + initial_knockback: 10.0, + max_knockback: 60.0, + range: 3.5, + max_angle: 30.0, + charge_duration: 1200, + swing_duration: 200, + recover_duration: 300, +), \ No newline at end of file diff --git a/assets/common/abilities/hammer/leap.ron b/assets/common/abilities/hammer/leap.ron new file mode 100644 index 0000000000..f83731582f --- /dev/null +++ b/assets/common/abilities/hammer/leap.ron @@ -0,0 +1,13 @@ +LeapMelee( + energy_cost: 700, + buildup_duration: 100, + movement_duration: 800, + swing_duration: 150, + recover_duration: 200, + base_damage: 240, + knockback: 25.0, + range: 4.5, + max_angle: 360.0, + forward_leap_strength: 28.0, + vertical_leap_strength: 8.0, +), \ No newline at end of file diff --git a/assets/common/abilities/hammer/tempbasic.ron b/assets/common/abilities/hammer/tempbasic.ron new file mode 100644 index 0000000000..001e96f0f6 --- /dev/null +++ b/assets/common/abilities/hammer/tempbasic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 600, + swing_duration: 100, + recover_duration: 300, + base_damage: 120, + knockback: 0.0, + range: 3.5, + max_angle: 20.0, +), \ No newline at end of file diff --git a/assets/common/abilities/sceptre/healingbeam.ron b/assets/common/abilities/sceptre/healingbeam.ron new file mode 100644 index 0000000000..91b7c19d1a --- /dev/null +++ b/assets/common/abilities/sceptre/healingbeam.ron @@ -0,0 +1,14 @@ +BasicBeam( + buildup_duration: 250, + recover_duration: 250, + beam_duration: 1000, + base_hps: 60, + base_dps: 60, + tick_rate: 2.0, + range: 25.0, + max_angle: 1.0, + lifesteal_eff: 0.20, + energy_regen: 50, + energy_cost: 100, + energy_drain: 0, +), \ No newline at end of file diff --git a/assets/common/abilities/sceptre/healingbomb.ron b/assets/common/abilities/sceptre/healingbomb.ron new file mode 100644 index 0000000000..950b911679 --- /dev/null +++ b/assets/common/abilities/sceptre/healingbomb.ron @@ -0,0 +1,63 @@ +BasicRanged( + energy_cost: 800, + buildup_duration: 800, + recover_duration: 50, + projectile: ( + hit_solid: [ + Explode(( + effects: [ + Entity( + Some(OutOfGroup), + Damage(( + source: Explosion, + value: 50.0, + )), + ), + Entity( + Some(InGroup), + Damage(( + source: Healing, + value: 140.0, + )), + ), + ], + radius: 6.0, + energy_regen: 0, + )), + Vanish, + ], + hit_entity: [ + Explode(( + effects: [ + Entity( + Some(OutOfGroup), + Damage(( + source: Explosion, + value: 50.0, + )), + ), + Entity( + Some(InGroup), + Damage(( + source: Healing, + value: 140.0, + )), + ), + ], + radius: 6.0, + energy_regen: 0, + )), + Vanish, + ], + time_left: 20, // seconds + owner: None, + ignore_group: true, + ), + projectile_body: Object(BoltNature), + /*projectile_light: Some(LightEmitter { + col: (0.0, 1.0, 0.0).into(), + ..Default::default() + }),*/ + projectile_gravity: Some(Gravity(0.5)), + projectile_speed: 40.0, +), \ No newline at end of file diff --git a/assets/common/abilities/staff/firebomb.ron b/assets/common/abilities/staff/firebomb.ron new file mode 100644 index 0000000000..5cb53cf5fa --- /dev/null +++ b/assets/common/abilities/staff/firebomb.ron @@ -0,0 +1,45 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 500, + recover_duration: 350, + projectile: ( + hit_solid: [ + Explode(( + effects: [Entity( + Some(OutOfGroup), + Damage(( + source: Explosion, + value: 100.0, + )), + )], + radius: 5.0, + energy_regen: 50, + )), + Vanish, + ], + hit_entity: vec![ + Explode(( + effects: [Entity( + Some(OutOfGroup), + Damage(( + source: Explosion, + value: 100.0, + )), + )], + radius: 5.0, + energy_regen: 50, + )), + Vanish, + ], + time_left: 20, // seconds + owner: None, + ignore_group: true, + ), + projectile_body: Object(BoltFire), + /*projectile_light: Some(LightEmitter { + col: (1.0, 0.75, 0.11).into(), + ..Default::default() + }),*/ + projectile_gravity: Some(Gravity(0.3)), + projectile_speed: 60.0, +), \ No newline at end of file diff --git a/assets/common/abilities/staff/fireshockwave.ron b/assets/common/abilities/staff/fireshockwave.ron new file mode 100644 index 0000000000..f5eed9d021 --- /dev/null +++ b/assets/common/abilities/staff/fireshockwave.ron @@ -0,0 +1,14 @@ +Shockwave( + energy_cost: 600, + buildup_duration: 700, + swing_duration: 100, + recover_duration: 300, + damage: 200, + knockback: Away(25.0), + shockwave_angle: 360.0, + shockwave_vertical_angle: 90.0, + shockwave_speed: 20.0, + shockwave_duration: 500, + requires_ground: false, + move_efficiency: 0.1, +), \ No newline at end of file diff --git a/assets/common/abilities/staff/flamethrower.ron b/assets/common/abilities/staff/flamethrower.ron new file mode 100644 index 0000000000..acc4a510f9 --- /dev/null +++ b/assets/common/abilities/staff/flamethrower.ron @@ -0,0 +1,14 @@ +BasicBeam( + buildup_duration: 250, + recover_duration: 250, + beam_duration: 500, + base_hps: 0, + base_dps: 150, + tick_rate: 3.0, + range: 15.0, + max_angle: 22.5, + lifesteal_eff: 0.0, + energy_regen: 0, + energy_cost: 0, + energy_drain: 350, +), \ No newline at end of file diff --git a/assets/common/abilities/sword/dash.ron b/assets/common/abilities/sword/dash.ron new file mode 100644 index 0000000000..2935ff810b --- /dev/null +++ b/assets/common/abilities/sword/dash.ron @@ -0,0 +1,17 @@ +DashMelee( + energy_cost: 200, + base_damage: 120, + max_damage: 240, + base_knockback: 8.0, + max_knockback: 15.0, + range: 5.0, + angle: 45.0, + energy_drain: 500, + forward_speed: 4.0, + buildup_duration: 250, + charge_duration: 600, + swing_duration: 100, + recover_duration: 500, + infinite_charge: true, + is_interruptible: true, +), \ No newline at end of file diff --git a/assets/common/abilities/sword/spin.ron b/assets/common/abilities/sword/spin.ron new file mode 100644 index 0000000000..1ae86a7853 --- /dev/null +++ b/assets/common/abilities/sword/spin.ron @@ -0,0 +1,14 @@ +SpinMelee( + buildup_duration: 750, + swing_duration: 500, + recover_duration: 500, + base_damage: 140, + knockback: 10.0, + range: 3.5, + energy_cost: 200, + is_infinite: false, + is_helicopter: false, + is_interruptible: true, + forward_speed: 1.0, + num_spins: 3, +), \ No newline at end of file diff --git a/assets/common/abilities/sword/triplestrike.ron b/assets/common/abilities/sword/triplestrike.ron new file mode 100644 index 0000000000..b699b78544 --- /dev/null +++ b/assets/common/abilities/sword/triplestrike.ron @@ -0,0 +1,49 @@ +ComboMelee ( + stage_data: [ + ( + stage: 1, + base_damage: 100, + max_damage: 120, + damage_increase: 10, + knockback: 10.0, + range: 4.0, + angle: 30.0, + base_buildup_duration: 350, + base_swing_duration: 100, + base_recover_duration: 400, + forward_movement: 0.5, + ), + ( + stage: 2, + base_damage: 80, + max_damage: 110, + damage_increase: 15, + knockback: 12.0, + range: 3.5, + angle: 180.0, + base_buildup_duration: 400, + base_swing_duration: 600, + base_recover_duration: 400 + forward_movement: 0.0, + ), + ( + stage: 3, + base_damage: 130, + max_damage: 170, + damage_increase: 20, + knockback: 14.0, + range: 6.0, + angle: 10.0, + base_buildup_duration: 500, + base_swing_duration: 200, + base_recover_duration: 300, + forward_movement: 1.2, + ), + ], + initial_energy_gain: 0, + max_energy_gain: 100, + energy_increase: 20, + speed_increase: 0.05, + max_speed_increase: 1.8, + is_interruptible: true, +), \ No newline at end of file From 84627cfe883e306b3743cdf93936b979e50e2259 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 8 Nov 2020 17:53:37 -0600 Subject: [PATCH 02/10] Added ron files for unique and WIP tools. --- assets/common/abilities/dagger/tempbasic.ron | 10 ++++++++++ .../common/abilities/debug/forwardboost.ron | 4 ++++ assets/common/abilities/debug/possess.ron | 19 +++++++++++++++++++ assets/common/abilities/debug/upboost.ron | 4 ++++ assets/common/abilities/farming/basic.ron | 10 ++++++++++ assets/common/abilities/shield/tempbasic.ron | 10 ++++++++++ .../abilities/unique/beastclaws/basic.ron | 10 ++++++++++ .../abilities/unique/stonegolemfist/basic.ron | 10 ++++++++++ .../unique/stonegolemfist/shockwave.ron | 14 ++++++++++++++ common/src/comp/inventory/item/tool.rs | 1 - 10 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 assets/common/abilities/dagger/tempbasic.ron create mode 100644 assets/common/abilities/debug/forwardboost.ron create mode 100644 assets/common/abilities/debug/possess.ron create mode 100644 assets/common/abilities/debug/upboost.ron create mode 100644 assets/common/abilities/farming/basic.ron create mode 100644 assets/common/abilities/shield/tempbasic.ron create mode 100644 assets/common/abilities/unique/beastclaws/basic.ron create mode 100644 assets/common/abilities/unique/stonegolemfist/basic.ron create mode 100644 assets/common/abilities/unique/stonegolemfist/shockwave.ron diff --git a/assets/common/abilities/dagger/tempbasic.ron b/assets/common/abilities/dagger/tempbasic.ron new file mode 100644 index 0000000000..0d31c0b0f4 --- /dev/null +++ b/assets/common/abilities/dagger/tempbasic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 100, + swing_duration: 100, + recover_duration: 300, + base_damage: 50, + knockback: 0.0, + range: 3.5, + max_angle: 20.0, +) \ No newline at end of file diff --git a/assets/common/abilities/debug/forwardboost.ron b/assets/common/abilities/debug/forwardboost.ron new file mode 100644 index 0000000000..eebed9703c --- /dev/null +++ b/assets/common/abilities/debug/forwardboost.ron @@ -0,0 +1,4 @@ +CharacterAbility::Boost( + movement_duration: 50, + only_up: false, +), \ No newline at end of file diff --git a/assets/common/abilities/debug/possess.ron b/assets/common/abilities/debug/possess.ron new file mode 100644 index 0000000000..7a620b87e8 --- /dev/null +++ b/assets/common/abilities/debug/possess.ron @@ -0,0 +1,19 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 0, + recover_duration: 10, + projectile: ( + hit_solid: [Stick], + hit_entity: [Stick, Possess], + time_left: 10, // secs + owner: None, + ignore_group: false, + ), + projectile_body: Object(ArrowSnake), + /*projectile_light: Some(LightEmitter { + col: (0.0, 1.0, 0.33).into(), + ..Default::default() + }),*/ + projectile_gravity: None, + projectile_speed: 100.0, +), \ No newline at end of file diff --git a/assets/common/abilities/debug/upboost.ron b/assets/common/abilities/debug/upboost.ron new file mode 100644 index 0000000000..6b293a83b8 --- /dev/null +++ b/assets/common/abilities/debug/upboost.ron @@ -0,0 +1,4 @@ +CharacterAbility::Boost( + movement_duration: 50, + only_up: true, +), \ No newline at end of file diff --git a/assets/common/abilities/farming/basic.ron b/assets/common/abilities/farming/basic.ron new file mode 100644 index 0000000000..3b7aa36fca --- /dev/null +++ b/assets/common/abilities/farming/basic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 1, + buildup_duration: 600, + swing_duration: 100, + recover_duration: 150, + base_damage: 50, + knockback: 0.0, + range: 3.5, + max_angle: 20.0, +) \ No newline at end of file diff --git a/assets/common/abilities/shield/tempbasic.ron b/assets/common/abilities/shield/tempbasic.ron new file mode 100644 index 0000000000..d0023f388c --- /dev/null +++ b/assets/common/abilities/shield/tempbasic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 100, + swing_duration: 100, + recover_duration: 300, + base_damage: 40, + knockback: 0.0, + range: 3.0, + max_angle: 120.0, +), \ No newline at end of file diff --git a/assets/common/abilities/unique/beastclaws/basic.ron b/assets/common/abilities/unique/beastclaws/basic.ron new file mode 100644 index 0000000000..77e860349c --- /dev/null +++ b/assets/common/abilities/unique/beastclaws/basic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 250, + swing_duration: 250, + recover_duration: 250, + knockback: 25.0, + base_damage: 200, + range: 5.0, + max_angle: 120.0, +) \ No newline at end of file diff --git a/assets/common/abilities/unique/stonegolemfist/basic.ron b/assets/common/abilities/unique/stonegolemfist/basic.ron new file mode 100644 index 0000000000..53f8993be6 --- /dev/null +++ b/assets/common/abilities/unique/stonegolemfist/basic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 400, + swing_duration: 100, + recover_duration: 250, + knockback: 25.0, + base_damage: 200, + range: 5.0, + max_angle: 120.0, +), \ No newline at end of file diff --git a/assets/common/abilities/unique/stonegolemfist/shockwave.ron b/assets/common/abilities/unique/stonegolemfist/shockwave.ron new file mode 100644 index 0000000000..ecac0f22c1 --- /dev/null +++ b/assets/common/abilities/unique/stonegolemfist/shockwave.ron @@ -0,0 +1,14 @@ +Shockwave( + energy_cost: 0, + buildup_duration: 500, + swing_duration: 200, + recover_duration: 800, + damage: 500, + knockback: TowardsUp(40.0), + shockwave_angle: 90.0, + shockwave_vertical_angle: 15.0, + shockwave_speed: 20.0, + shockwave_duration: 2000, + requires_ground: true, + move_efficiency: 0.05, +), \ No newline at end of file diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index a5f7b9cd91..c8797bf4d3 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -580,7 +580,6 @@ impl Tool { range: 3.0, max_angle: 120.0, }, - BasicBlock, ], Unique(StoneGolemFist) => vec![ BasicMelee { From b4135ab3e24bdd49e9ae74b155142748801db2a9 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 8 Nov 2020 21:09:33 -0600 Subject: [PATCH 03/10] Changed how buffs were constructed on projectiles. --- assets/common/abilities/bow/basic.ron | 19 ++++++++--------- assets/common/abilities/bow/repeater.ron | 19 ++++++++--------- common/src/comp/inventory/item/tool.rs | 26 +++++++++++------------- common/src/comp/projectile.rs | 7 +++++-- common/src/states/charged_ranged.rs | 14 ++++++------- common/src/sys/projectile.rs | 13 +++++++----- 6 files changed, 50 insertions(+), 48 deletions(-) diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/basic.ron index 8155011f63..fe15b34c37 100644 --- a/assets/common/abilities/bow/basic.ron +++ b/assets/common/abilities/bow/basic.ron @@ -12,18 +12,17 @@ BasicRanged( Knockback(Away(10.0)), RewardEnergy(50), Vanish, - /*projectile::Effect::Buff { - buff: Buff::new( - BuffKind::Bleeding, - BuffData { - strength: 20.0 * self.base_power(), - duration: Some(Duration::from_secs(5)), - }, - vec![BuffCategory::Physical], - BuffSource::Unknown, + Buff( + buff: ( + kind: Bleeding, + data: ( + strength: 20.0, + duration: Some(5), // secs + ), + cat_ids: [Physical], ), chance: Some(0.10), - },*/ + ), ], time_left: 15, // seconds owner: None, diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index e27dfb7dc7..143e610fac 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -14,18 +14,17 @@ RepeaterRanged( )), Knockback(Away(10.0)), Vanish, - /*projectile::Effect::Buff { - buff: Buff::new( - BuffKind::Bleeding, - BuffData { - strength: 20.0 * self.base_power(), - duration: Some(Duration::from_secs(5)), - }, - vec![BuffCategory::Physical], - BuffSource::Unknown, + Buff( + buff: ( + kind: Bleeding, + data: ( + strength: 20.0, + duration: Some(5), // secs + ), + cat_ids: [Physical], ), chance: Some(0.10), - },*/ + ), ], time_left: 15, // seconds owner: None, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index c8797bf4d3..37a6751292 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -4,10 +4,10 @@ use crate::{ comp::{ body::object, - buff::{Buff, BuffCategory, BuffData, BuffKind, BuffSource}, + buff::{BuffCategory, BuffData, BuffKind}, projectile, Body, CharacterAbility, Gravity, LightEmitter, Projectile, }, - effect::Effect, + effect::{BuffEffect, Effect}, states::combo_melee, Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect, }; @@ -324,15 +324,14 @@ impl Tool { projectile::Effect::RewardEnergy(50), projectile::Effect::Vanish, projectile::Effect::Buff { - buff: Buff::new( - BuffKind::Bleeding, - BuffData { + buff: BuffEffect { + kind: BuffKind::Bleeding, + data: BuffData { strength: 20.0 * self.base_power(), duration: Some(Duration::from_secs(5)), }, - vec![BuffCategory::Physical], - BuffSource::Unknown, - ), + cat_ids: vec![BuffCategory::Physical], + }, chance: Some(0.10), }, ], @@ -380,15 +379,14 @@ impl Tool { projectile::Effect::Knockback(Knockback::Away(10.0)), projectile::Effect::Vanish, projectile::Effect::Buff { - buff: Buff::new( - BuffKind::Bleeding, - BuffData { + buff: BuffEffect { + kind: BuffKind::Bleeding, + data: BuffData { strength: 20.0 * self.base_power(), duration: Some(Duration::from_secs(5)), }, - vec![BuffCategory::Physical], - BuffSource::Unknown, - ), + cat_ids: vec![BuffCategory::Physical], + }, chance: Some(0.10), }, ], diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index f24bd79b50..470135f2c5 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -1,4 +1,4 @@ -use crate::{comp::Buff, sync::Uid, Damage, Explosion, GroupTarget, Knockback}; +use crate::{effect::BuffEffect, sync::Uid, Damage, Explosion, GroupTarget, Knockback}; use serde::{Deserialize, Serialize}; use specs::{Component, FlaggedStorage}; use specs_idvs::IdvStorage; @@ -13,7 +13,10 @@ pub enum Effect { Vanish, Stick, Possess, - Buff { buff: Buff, chance: Option }, + Buff { + buff: BuffEffect, + chance: Option, + }, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 951dac68e0..73e27ba4c6 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -1,9 +1,10 @@ use crate::{ comp::{ - buff::{Buff, BuffCategory, BuffData, BuffKind, BuffSource}, + buff::{BuffCategory, BuffData, BuffKind}, projectile, Body, CharacterState, EnergyChange, EnergySource, Gravity, LightEmitter, Projectile, StateUpdate, }, + effect::BuffEffect, event::ServerEvent, states::utils::*, sys::character_behavior::{CharacterBehavior, JoinData}, @@ -105,15 +106,14 @@ impl CharacterBehavior for Data { projectile::Effect::Knockback(Knockback::Away(knockback)), projectile::Effect::Vanish, projectile::Effect::Buff { - buff: Buff::new( - BuffKind::Bleeding, - BuffData { + buff: BuffEffect { + kind: BuffKind::Bleeding, + data: BuffData { strength: damage.value / 5.0, duration: Some(Duration::from_secs(5)), }, - vec![BuffCategory::Physical], - BuffSource::Unknown, - ), + cat_ids: vec![BuffCategory::Physical], + }, chance: Some(0.10), }, ], diff --git a/common/src/sys/projectile.rs b/common/src/sys/projectile.rs index 9e3f66b958..1ef563ab5a 100644 --- a/common/src/sys/projectile.rs +++ b/common/src/sys/projectile.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ - buff::{BuffChange, BuffSource}, + buff::{Buff, BuffChange, BuffSource}, projectile, EnergyChange, EnergySource, Group, HealthSource, Loadout, Ori, PhysicsState, Pos, Projectile, Vel, }, @@ -176,10 +176,13 @@ impl<'a> System<'a> for Sys { uid_allocator.retrieve_entity_internal(other.into()) { if chance.map_or(true, |c| thread_rng().gen::() < c) { - let mut buff = buff.clone(); - if let Some(uid) = projectile.owner { - buff.source = BuffSource::Character { by: uid }; - } + let source = if let Some(owner) = projectile.owner { + BuffSource::Character { by: owner } + } else { + BuffSource::Unknown + }; + let buff = + Buff::new(buff.kind, buff.data, buff.cat_ids, source); server_emitter.emit(ServerEvent::Buff { entity, buff_change: BuffChange::Add(buff), From 838c62f56b2a28d5f74c4859187f867b67915c40 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 8 Nov 2020 22:04:51 -0600 Subject: [PATCH 04/10] Added projectile constructor. Removed a bunch of cloning. --- assets/common/abilities/bow/basic.ron | 29 +-- assets/common/abilities/bow/repeater.ron | 28 +-- .../common/abilities/sceptre/healingbomb.ron | 54 +----- assets/common/abilities/staff/firebomb.ron | 36 +--- common/src/comp/ability.rs | 11 +- common/src/comp/inventory/item/tool.rs | 164 +++-------------- common/src/comp/mod.rs | 2 +- common/src/comp/projectile.rs | 167 +++++++++++++++++- common/src/states/basic_ranged.rs | 16 +- common/src/states/charged_ranged.rs | 5 +- common/src/states/repeater_ranged.rs | 20 +-- 11 files changed, 226 insertions(+), 306 deletions(-) diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/basic.ron index fe15b34c37..d2de738791 100644 --- a/assets/common/abilities/bow/basic.ron +++ b/assets/common/abilities/bow/basic.ron @@ -2,31 +2,10 @@ BasicRanged( energy_cost: 0, buildup_duration: 100, recover_duration: 400, - projectile: ( - hit_solid: [Stick], - hit_entity: [ - Damage(Some(OutOfGroup), ( - source: Projectile, - value: 40.0, - )), - Knockback(Away(10.0)), - RewardEnergy(50), - Vanish, - Buff( - buff: ( - kind: Bleeding, - data: ( - strength: 20.0, - duration: Some(5), // secs - ), - cat_ids: [Physical], - ), - chance: Some(0.10), - ), - ], - time_left: 15, // seconds - owner: None, - ignore_group: true, + projectile: Arrow( + damage: 40.0, + knockback: 10.0, + energy_regen: 50, ), projectile_body: Object(Arrow), projectile_light: None, diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index 143e610fac..520e3811d0 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -5,30 +5,10 @@ RepeaterRanged( shoot_duration: 200, recover_duration: 800, leap: Some(5.0), - projectile: ( - hit_solid: [Stick], - hit_entity: [ - Damage(Some(OutOfGroup), ( - source: Projectile, - value: 40.0, - )), - Knockback(Away(10.0)), - Vanish, - Buff( - buff: ( - kind: Bleeding, - data: ( - strength: 20.0, - duration: Some(5), // secs - ), - cat_ids: [Physical], - ), - chance: Some(0.10), - ), - ], - time_left: 15, // seconds - owner: None, - ignore_group: true, + projectile: Arrow( + damage: 40.0, + knockback: 10.0, + energy_regen: 0, ), projectile_body: Object(Arrow), projectile_light: None, diff --git a/assets/common/abilities/sceptre/healingbomb.ron b/assets/common/abilities/sceptre/healingbomb.ron index 950b911679..2a0204ba08 100644 --- a/assets/common/abilities/sceptre/healingbomb.ron +++ b/assets/common/abilities/sceptre/healingbomb.ron @@ -2,56 +2,10 @@ BasicRanged( energy_cost: 800, buildup_duration: 800, recover_duration: 50, - projectile: ( - hit_solid: [ - Explode(( - effects: [ - Entity( - Some(OutOfGroup), - Damage(( - source: Explosion, - value: 50.0, - )), - ), - Entity( - Some(InGroup), - Damage(( - source: Healing, - value: 140.0, - )), - ), - ], - radius: 6.0, - energy_regen: 0, - )), - Vanish, - ], - hit_entity: [ - Explode(( - effects: [ - Entity( - Some(OutOfGroup), - Damage(( - source: Explosion, - value: 50.0, - )), - ), - Entity( - Some(InGroup), - Damage(( - source: Healing, - value: 140.0, - )), - ), - ], - radius: 6.0, - energy_regen: 0, - )), - Vanish, - ], - time_left: 20, // seconds - owner: None, - ignore_group: true, + projectile: Heal( + heal: 140.0, + damage: 50.0, + radius: 6.0, ), projectile_body: Object(BoltNature), /*projectile_light: Some(LightEmitter { diff --git a/assets/common/abilities/staff/firebomb.ron b/assets/common/abilities/staff/firebomb.ron index 5cb53cf5fa..f2c75d5cf7 100644 --- a/assets/common/abilities/staff/firebomb.ron +++ b/assets/common/abilities/staff/firebomb.ron @@ -2,38 +2,10 @@ BasicRanged( energy_cost: 0, buildup_duration: 500, recover_duration: 350, - projectile: ( - hit_solid: [ - Explode(( - effects: [Entity( - Some(OutOfGroup), - Damage(( - source: Explosion, - value: 100.0, - )), - )], - radius: 5.0, - energy_regen: 50, - )), - Vanish, - ], - hit_entity: vec![ - Explode(( - effects: [Entity( - Some(OutOfGroup), - Damage(( - source: Explosion, - value: 100.0, - )), - )], - radius: 5.0, - energy_regen: 50, - )), - Vanish, - ], - time_left: 20, // seconds - owner: None, - ignore_group: true, + projectile: Fireball( + damage: 100.0, + radius: 5.0, + energy_regen: 0, ), projectile_body: Object(BoltFire), /*projectile_light: Some(LightEmitter { diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index b88392fe8b..621b80407f 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1,7 +1,8 @@ use crate::{ comp::{ item::{armor::Protection, Item, ItemKind}, - Body, CharacterState, EnergySource, Gravity, LightEmitter, Projectile, StateUpdate, + projectile::ProjectileConstructor, + Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate, }, states::{ utils::{AbilityKey, StageSection}, @@ -71,7 +72,7 @@ pub enum CharacterAbility { energy_cost: u32, buildup_duration: Duration, recover_duration: Duration, - projectile: Projectile, + projectile: ProjectileConstructor, projectile_body: Body, projectile_light: Option, projectile_gravity: Option, @@ -85,7 +86,7 @@ pub enum CharacterAbility { shoot_duration: Duration, recover_duration: Duration, leap: Option, - projectile: Projectile, + projectile: ProjectileConstructor, projectile_body: Body, projectile_light: Option, projectile_gravity: Option, @@ -418,7 +419,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { static_data: basic_ranged::StaticData { buildup_duration: *buildup_duration, recover_duration: *recover_duration, - projectile: projectile.clone(), + projectile: *projectile, projectile_body: *projectile_body, projectile_light: *projectile_light, projectile_gravity: *projectile_gravity, @@ -681,7 +682,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { shoot_duration: *shoot_duration, recover_duration: *recover_duration, leap: *leap, - projectile: projectile.clone(), + projectile: *projectile, projectile_body: *projectile_body, projectile_light: *projectile_light, projectile_gravity: *projectile_gravity, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 37a6751292..584001b427 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -3,13 +3,11 @@ use crate::{ comp::{ - body::object, - buff::{BuffCategory, BuffData, BuffKind}, - projectile, Body, CharacterAbility, Gravity, LightEmitter, Projectile, + body::object, projectile::ProjectileConstructor, Body, CharacterAbility, Gravity, + LightEmitter, }, - effect::{BuffEffect, Effect}, states::combo_melee, - Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect, + Knockback, }; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -95,6 +93,7 @@ impl Tool { Duration::from_millis(millis).div_f32(self.base_speed()) } + // TODO: Before merging ron file branch, ensure these are double checked against ron files. pub fn get_abilities(&self) -> Vec { use CharacterAbility::*; use ToolKind::*; @@ -313,31 +312,10 @@ impl Tool { energy_cost: 0, buildup_duration: self.adjusted_duration(200), recover_duration: self.adjusted_duration(300), - projectile: Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), Damage { - source: DamageSource::Projectile, - value: 40.0 * self.base_power(), - }), - projectile::Effect::Knockback(Knockback::Away(10.0)), - projectile::Effect::RewardEnergy(50), - projectile::Effect::Vanish, - projectile::Effect::Buff { - buff: BuffEffect { - kind: BuffKind::Bleeding, - data: BuffData { - strength: 20.0 * self.base_power(), - duration: Some(Duration::from_secs(5)), - }, - cat_ids: vec![BuffCategory::Physical], - }, - chance: Some(0.10), - }, - ], - time_left: Duration::from_secs(15), - owner: None, - ignore_group: true, + projectile: ProjectileConstructor::Arrow { + damage: 40.0 * self.base_power(), + knockback: 10.0, + energy_regen: 50, }, projectile_body: Body::Object(object::Body::Arrow), projectile_light: None, @@ -369,30 +347,10 @@ impl Tool { shoot_duration: self.adjusted_duration(200), recover_duration: self.adjusted_duration(800), leap: Some(5.0), - projectile: Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), Damage { - source: DamageSource::Projectile, - value: 40.0 * self.base_power(), - }), - projectile::Effect::Knockback(Knockback::Away(10.0)), - projectile::Effect::Vanish, - projectile::Effect::Buff { - buff: BuffEffect { - kind: BuffKind::Bleeding, - data: BuffData { - strength: 20.0 * self.base_power(), - duration: Some(Duration::from_secs(5)), - }, - cat_ids: vec![BuffCategory::Physical], - }, - chance: Some(0.10), - }, - ], - time_left: Duration::from_secs(15), - owner: None, - ignore_group: true, + projectile: ProjectileConstructor::Arrow { + damage: 40.0 * self.base_power(), + knockback: 10.0, + energy_regen: 0, }, projectile_body: Body::Object(object::Body::Arrow), projectile_light: None, @@ -430,56 +388,10 @@ impl Tool { energy_cost: 800, buildup_duration: self.adjusted_duration(800), recover_duration: self.adjusted_duration(50), - projectile: Projectile { - hit_solid: vec![ - projectile::Effect::Explode(Explosion { - effects: vec![ - RadiusEffect::Entity( - Some(GroupTarget::OutOfGroup), - Effect::Damage(Damage { - source: DamageSource::Explosion, - value: 50.0 * self.base_power(), - }), - ), - RadiusEffect::Entity( - Some(GroupTarget::InGroup), - Effect::Damage(Damage { - source: DamageSource::Healing, - value: 140.0 * self.base_power(), - }), - ), - ], - radius: 3.0 + 2.5 * self.base_power(), - energy_regen: 0, - }), - projectile::Effect::Vanish, - ], - hit_entity: vec![ - projectile::Effect::Explode(Explosion { - effects: vec![ - RadiusEffect::Entity( - Some(GroupTarget::OutOfGroup), - Effect::Damage(Damage { - source: DamageSource::Explosion, - value: 50.0 * self.base_power(), - }), - ), - RadiusEffect::Entity( - Some(GroupTarget::InGroup), - Effect::Damage(Damage { - source: DamageSource::Healing, - value: 140.0 * self.base_power(), - }), - ), - ], - radius: 3.0 + 2.5 * self.base_power(), - energy_regen: 0, - }), - projectile::Effect::Vanish, - ], - time_left: Duration::from_secs(20), - owner: None, - ignore_group: true, + projectile: ProjectileConstructor::Heal { + heal: 140.0 * self.base_power(), + damage: 50.0 * self.base_power(), + radius: 3.0 + 2.5 * self.base_power(), }, projectile_body: Body::Object(object::Body::BoltNature), projectile_light: Some(LightEmitter { @@ -496,38 +408,10 @@ impl Tool { energy_cost: 0, buildup_duration: self.adjusted_duration(500), recover_duration: self.adjusted_duration(350), - projectile: Projectile { - hit_solid: vec![ - projectile::Effect::Explode(Explosion { - effects: vec![RadiusEffect::Entity( - Some(GroupTarget::OutOfGroup), - Effect::Damage(Damage { - source: DamageSource::Explosion, - value: 100.0 * self.base_power(), - }), - )], - radius: 5.0, - energy_regen: 50, - }), - projectile::Effect::Vanish, - ], - hit_entity: vec![ - projectile::Effect::Explode(Explosion { - effects: vec![RadiusEffect::Entity( - Some(GroupTarget::OutOfGroup), - Effect::Damage(Damage { - source: DamageSource::Explosion, - value: 100.0 * self.base_power(), - }), - )], - radius: 5.0, - energy_regen: 50, - }), - projectile::Effect::Vanish, - ], - time_left: Duration::from_secs(20), - owner: None, - ignore_group: true, + projectile: ProjectileConstructor::Fireball { + damage: 100.0 * self.base_power(), + radius: 5.0, + energy_regen: 50, }, projectile_body: Body::Object(object::Body::BoltFire), projectile_light: Some(LightEmitter { @@ -628,13 +512,7 @@ impl Tool { energy_cost: 0, buildup_duration: Duration::from_millis(0), recover_duration: self.adjusted_duration(10), - projectile: Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![projectile::Effect::Stick, projectile::Effect::Possess], - time_left: Duration::from_secs(10), - owner: None, - ignore_group: false, - }, + projectile: ProjectileConstructor::Possess, projectile_body: Body::Object(object::Body::ArrowSnake), projectile_light: Some(LightEmitter { col: (0.0, 1.0, 0.33).into(), diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 53f6a2e27a..362d0ad06a 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -61,7 +61,7 @@ pub use phys::{ Sticky, Vel, }; pub use player::Player; -pub use projectile::Projectile; +pub use projectile::{Projectile, ProjectileConstructor}; pub use shockwave::{Shockwave, ShockwaveHitEntities}; pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet}; pub use stats::{Exp, Level, Stats}; diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 470135f2c5..d0cf49facd 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -1,4 +1,9 @@ -use crate::{effect::BuffEffect, sync::Uid, Damage, Explosion, GroupTarget, Knockback}; +use crate::{ + comp::buff::{BuffCategory, BuffData, BuffKind}, + effect::{BuffEffect, Effect as EffectB}, + sync::Uid, + Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect, +}; use serde::{Deserialize, Serialize}; use specs::{Component, FlaggedStorage}; use specs_idvs::IdvStorage; @@ -35,3 +40,163 @@ pub struct Projectile { impl Component for Projectile { type Storage = FlaggedStorage>; } + +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +pub enum ProjectileConstructor { + Arrow { + damage: f32, + knockback: f32, + energy_regen: u32, + }, + Fireball { + damage: f32, + radius: f32, + energy_regen: u32, + }, + Heal { + heal: f32, + damage: f32, + radius: f32, + }, + Possess, +} + +impl ProjectileConstructor { + pub fn create_projectile(self, owner: Option) -> Projectile { + use ProjectileConstructor::*; + match self { + Arrow { + damage, + knockback, + energy_regen, + } => { + let buff = BuffEffect { + kind: BuffKind::Bleeding, + data: BuffData { + strength: damage / 2.0, + duration: Some(Duration::from_secs(5)), + }, + cat_ids: vec![BuffCategory::Physical], + }; + Projectile { + hit_solid: vec![Effect::Stick], + hit_entity: vec![ + Effect::Damage(Some(GroupTarget::OutOfGroup), Damage { + source: DamageSource::Projectile, + value: damage, + }), + Effect::Knockback(Knockback::Away(knockback)), + Effect::RewardEnergy(energy_regen), + Effect::Vanish, + Effect::Buff { + buff, + chance: Some(0.10), + }, + ], + time_left: Duration::from_secs(15), + owner, + ignore_group: true, + } + }, + Fireball { + damage, + radius, + energy_regen, + } => Projectile { + hit_solid: vec![ + Effect::Explode(Explosion { + effects: vec![RadiusEffect::Entity( + Some(GroupTarget::OutOfGroup), + EffectB::Damage(Damage { + source: DamageSource::Explosion, + value: damage, + }), + )], + radius, + energy_regen, + }), + Effect::Vanish, + ], + hit_entity: vec![ + Effect::Explode(Explosion { + effects: vec![RadiusEffect::Entity( + Some(GroupTarget::OutOfGroup), + EffectB::Damage(Damage { + source: DamageSource::Explosion, + value: damage, + }), + )], + radius, + energy_regen, + }), + Effect::Vanish, + ], + time_left: Duration::from_secs(20), + owner, + ignore_group: true, + }, + Heal { + heal, + damage, + radius, + } => Projectile { + hit_solid: vec![ + Effect::Explode(Explosion { + effects: vec![ + RadiusEffect::Entity( + Some(GroupTarget::OutOfGroup), + EffectB::Damage(Damage { + source: DamageSource::Explosion, + value: damage, + }), + ), + RadiusEffect::Entity( + Some(GroupTarget::InGroup), + EffectB::Damage(Damage { + source: DamageSource::Healing, + value: heal, + }), + ), + ], + radius, + energy_regen: 0, + }), + Effect::Vanish, + ], + hit_entity: vec![ + Effect::Explode(Explosion { + effects: vec![ + RadiusEffect::Entity( + Some(GroupTarget::OutOfGroup), + EffectB::Damage(Damage { + source: DamageSource::Explosion, + value: damage, + }), + ), + RadiusEffect::Entity( + Some(GroupTarget::InGroup), + EffectB::Damage(Damage { + source: DamageSource::Healing, + value: heal, + }), + ), + ], + radius, + energy_regen: 0, + }), + Effect::Vanish, + ], + time_left: Duration::from_secs(20), + owner, + ignore_group: true, + }, + Possess => Projectile { + hit_solid: vec![Effect::Stick], + hit_entity: vec![Effect::Stick, Effect::Possess], + time_left: Duration::from_secs(10), + owner, + ignore_group: false, + }, + } + } +} diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index d919f0cb6d..dedd9ca207 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate}, + comp::{Body, CharacterState, Gravity, LightEmitter, ProjectileConstructor, StateUpdate}, event::ServerEvent, states::utils::*, sys::character_behavior::{CharacterBehavior, JoinData}, @@ -8,14 +8,14 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; /// Separated out to condense update portions of character state -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct StaticData { /// How much buildup is required before the attack pub buildup_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, /// Projectile variables - pub projectile: Projectile, + pub projectile: ProjectileConstructor, pub projectile_body: Body, pub projectile_light: Option, pub projectile_gravity: Option, @@ -54,7 +54,6 @@ impl CharacterBehavior for Data { if self.timer < self.static_data.buildup_duration { // Build up update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -64,7 +63,6 @@ impl CharacterBehavior for Data { } else { // Transitions to recover section of stage update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Recover, ..*self @@ -74,8 +72,10 @@ impl CharacterBehavior for Data { StageSection::Recover => { if !self.exhausted { // Fire - let mut projectile = self.static_data.projectile.clone(); - projectile.owner = Some(*data.uid); + let projectile = self + .static_data + .projectile + .create_projectile(Some(*data.uid)); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, dir: data.inputs.look_dir, @@ -87,7 +87,6 @@ impl CharacterBehavior for Data { }); update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), exhausted: true, continue_next: false, ..*self @@ -118,7 +117,6 @@ impl CharacterBehavior for Data { } else if self.continue_next { // Restarts character state update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Buildup, exhausted: false, diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 73e27ba4c6..6074edd2bf 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -99,7 +99,7 @@ impl CharacterBehavior for Data { * (self.static_data.max_knockback - self.static_data.initial_knockback) as f32); // Fire - let mut projectile = Projectile { + let projectile = Projectile { hit_solid: vec![projectile::Effect::Stick], hit_entity: vec![ projectile::Effect::Damage(Some(GroupTarget::OutOfGroup), damage), @@ -118,10 +118,9 @@ impl CharacterBehavior for Data { }, ], time_left: Duration::from_secs(15), - owner: None, + owner: Some(*data.uid), ignore_group: true, }; - projectile.owner = Some(*data.uid); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, dir: data.inputs.look_dir, diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index b6ee044680..1540814697 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -1,5 +1,5 @@ use crate::{ - comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate}, + comp::{Body, CharacterState, Gravity, LightEmitter, ProjectileConstructor, StateUpdate}, event::ServerEvent, states::utils::{StageSection, *}, sys::character_behavior::*, @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; use vek::Vec3; -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] /// Separated out to condense update portions of character state pub struct StaticData { /// How long the state is in movement @@ -23,7 +23,7 @@ pub struct StaticData { /// Whether there should be a jump and how strong the leap is pub leap: Option, /// Projectile options - pub projectile: Projectile, + pub projectile: ProjectileConstructor, pub projectile_body: Body, pub projectile_light: Option, pub projectile_gravity: Option, @@ -71,7 +71,6 @@ impl CharacterBehavior for Data { if self.timer < self.static_data.movement_duration { // Do movement update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -81,7 +80,6 @@ impl CharacterBehavior for Data { } else { // Transition to buildup update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Buildup, ..*self @@ -101,7 +99,6 @@ impl CharacterBehavior for Data { if self.timer < self.static_data.buildup_duration { // Buildup to attack update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -111,7 +108,6 @@ impl CharacterBehavior for Data { } else { // Transition to shoot update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Shoot, ..*self @@ -125,8 +121,10 @@ impl CharacterBehavior for Data { } if self.reps_remaining > 0 { // Fire - let mut projectile = self.static_data.projectile.clone(); - projectile.owner = Some(*data.uid); + let projectile = self + .static_data + .projectile + .create_projectile(Some(*data.uid)); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, // Provides slight variation to projectile direction @@ -155,7 +153,6 @@ impl CharacterBehavior for Data { // Shoot projectiles update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -166,7 +163,6 @@ impl CharacterBehavior for Data { } else if self.timer < self.static_data.shoot_duration { // Finish shooting update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -176,7 +172,6 @@ impl CharacterBehavior for Data { } else { // Transition to recover update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Recover, ..*self @@ -190,7 +185,6 @@ impl CharacterBehavior for Data { } else if self.timer < self.static_data.recover_duration { // Recover from attack update.character = CharacterState::RepeaterRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) From fe8c634bbc22dcefb867d9fe6799ef58b9c16975 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 9 Nov 2020 15:31:41 -0600 Subject: [PATCH 05/10] Created manifest file to tie abilities to a particular weapon kind. --- assets/common/abilities/empty/basic.ron | 10 +++ .../abilities/weapon_ability_manifest.ron | 81 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 assets/common/abilities/empty/basic.ron create mode 100644 assets/common/abilities/weapon_ability_manifest.ron diff --git a/assets/common/abilities/empty/basic.ron b/assets/common/abilities/empty/basic.ron new file mode 100644 index 0000000000..3562af81b5 --- /dev/null +++ b/assets/common/abilities/empty/basic.ron @@ -0,0 +1,10 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0, + swing_duration: 100, + recover_duration: 900, + base_damage: 20, + knockback: 0.0, + range: 3.5, + max_angle: 15.0, +) \ No newline at end of file diff --git a/assets/common/abilities/weapon_ability_manifest.ron b/assets/common/abilities/weapon_ability_manifest.ron new file mode 100644 index 0000000000..c8383f77d8 --- /dev/null +++ b/assets/common/abilities/weapon_ability_manifest.ron @@ -0,0 +1,81 @@ +// Maps a tool kind to a set of abilities +// A set of abilities is a primary, a secondary, and a vec of all extra abilities +({ + Sword: ( + primary: "common.abilities.sword.triplestrike", + secondary: "common.abilities.sword.dash", + skills: [ + "common.abilities.sword.spin", + ], + ), + Axe: ( + primary: "common.abilities.axe.tempbasic", + secondary: "common.abilities.axe.spin", + skills: [ + "common.abilities.axe.leap", + ], + ), + Hammer: ( + primary: "common.abilities.hammer.tempbasic", + secondary: "common.abilities.hammer.charged", + skills: [ + "common.abilities.hammer.leap", + ], + ), + Bow: ( + primary: "common.abilities.bow.basic", + secondary: "common.abilities.bow.charged", + skills: [ + "common.abilities.bow.repeater", + ], + ), + Staff: ( + primary: "common.abilities.staff.firebomb", + secondary: "common.abilities.staff.flamethrower", + skills: [ + "common.abilities.staff.fireshockwave", + ], + ), + Sceptre: ( + primary: "common.abilities.sceptre.healingbeam", + secondary: "common.abilities.sceptre.healingbomb", + skills: [], + ), + Dagger: ( + primary: "common.abilities.dagger.tempbasic", + secondary: "common.abilities.dagger.tempbasic", + skills: [], + ), + Shield: ( + primary: "common.abilities.shield.tempbasic", + secondary: "common.abilities.shield.tempbasic", + skills: [], + ), + Unique(StoneGolemFist): ( + primary: "common.abilities.unique.stonegolemfist.basic", + secondary: "common.abilities.unique.stonegolemfist.shockwave", + skills: [], + ), + Unique(BeastClaws): ( + primary: "common.abilities.unique.beastclaws.basic", + secondary: "common.abilities.unique.beastclaws.basic", + skills: [], + ), + Debug: ( + primary: "common.abilities.debug.forwardboost", + secondary: "common.abilities.debug.upboost", + skills: [ + "common.abilities.debug.possess", + ], + ), + Farming: ( + primary: "common.abilities.farming.basic", + secondary: "common.abilities.farming.basic", + skills: [], + ), + Empty: ( + primary: "common.abilities.empty.basic", + secondary: "common.abilities.empty.basic", + skills: [], + ), +}) \ No newline at end of file From d9487771767ed05d5b8e260dd593ad9bea36c648 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 10 Nov 2020 19:49:05 -0600 Subject: [PATCH 06/10] Abilities are now loaded from .ron files. --- assets/common/abilities/axe/doublestrike.ron | 36 ++++ assets/common/abilities/axe/leap.ron | 2 +- assets/common/abilities/axe/spin.ron | 2 +- assets/common/abilities/axe/tempbasic.ron | 10 - assets/common/abilities/bow/basic.ron | 7 +- assets/common/abilities/bow/charged.ron | 3 +- assets/common/abilities/bow/repeater.ron | 2 +- .../common/abilities/debug/forwardboost.ron | 4 +- assets/common/abilities/debug/possess.ron | 11 +- assets/common/abilities/debug/upboost.ron | 4 +- assets/common/abilities/farming/basic.ron | 2 +- assets/common/abilities/hammer/charged.ron | 5 +- assets/common/abilities/hammer/leap.ron | 2 +- .../common/abilities/hammer/singlestrike.ron | 21 ++ assets/common/abilities/hammer/tempbasic.ron | 10 - .../common/abilities/sceptre/healingbeam.ron | 2 +- .../common/abilities/sceptre/healingbomb.ron | 3 +- assets/common/abilities/shield/block.ron | 1 + assets/common/abilities/shield/tempbasic.ron | 2 +- assets/common/abilities/staff/firebomb.ron | 5 +- .../common/abilities/staff/fireshockwave.ron | 2 +- .../common/abilities/staff/flamethrower.ron | 2 +- assets/common/abilities/sword/dash.ron | 2 +- assets/common/abilities/sword/spin.ron | 2 +- .../common/abilities/sword/triplestrike.ron | 6 +- .../abilities/unique/stonegolemfist/basic.ron | 2 +- .../unique/stonegolemfist/shockwave.ron | 2 +- .../abilities/weapon_ability_manifest.ron | 6 +- common/src/comp/ability.rs | 197 ++++++++++-------- common/src/comp/inventory/item/tool.rs | 83 +++++++- common/src/loadout_builder.rs | 12 +- common/src/states/combo_melee.rs | 28 ++- 32 files changed, 319 insertions(+), 159 deletions(-) create mode 100644 assets/common/abilities/axe/doublestrike.ron delete mode 100644 assets/common/abilities/axe/tempbasic.ron create mode 100644 assets/common/abilities/hammer/singlestrike.ron delete mode 100644 assets/common/abilities/hammer/tempbasic.ron create mode 100644 assets/common/abilities/shield/block.ron diff --git a/assets/common/abilities/axe/doublestrike.ron b/assets/common/abilities/axe/doublestrike.ron new file mode 100644 index 0000000000..7151798fd1 --- /dev/null +++ b/assets/common/abilities/axe/doublestrike.ron @@ -0,0 +1,36 @@ +ComboMelee( + stage_data: [ + ( + stage: 1, + base_damage: 90, + max_damage: 110, + damage_increase: 10, + knockback: 8.0, + range: 3.5, + angle: 50.0, + base_buildup_duration: 350, + base_swing_duration: 75, + base_recover_duration: 400, + forward_movement: 0.5, + ), + ( + stage: 2, + base_damage: 130, + max_damage: 160, + damage_increase: 15, + knockback: 12.0, + range: 3.5, + angle: 30.0, + base_buildup_duration: 500, + base_swing_duration: 100, + base_recover_duration: 500, + forward_movement: 0.25, + ), + ], + initial_energy_gain: 0, + max_energy_gain: 100, + energy_increase: 20, + speed_increase: 0.05, + max_speed_increase: 1.6, + is_interruptible: false, +) \ No newline at end of file diff --git a/assets/common/abilities/axe/leap.ron b/assets/common/abilities/axe/leap.ron index dc0c2fb266..1b6cd34c6d 100644 --- a/assets/common/abilities/axe/leap.ron +++ b/assets/common/abilities/axe/leap.ron @@ -10,4 +10,4 @@ LeapMelee( max_angle: 30.0, forward_leap_strength: 28.0, vertical_leap_strength: 8.0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/axe/spin.ron b/assets/common/abilities/axe/spin.ron index 1ec1f743fb..8a31ce4361 100644 --- a/assets/common/abilities/axe/spin.ron +++ b/assets/common/abilities/axe/spin.ron @@ -11,4 +11,4 @@ SpinMelee( is_interruptible: false, forward_speed: 0.0, num_spins: 1, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/axe/tempbasic.ron b/assets/common/abilities/axe/tempbasic.ron deleted file mode 100644 index 001e96f0f6..0000000000 --- a/assets/common/abilities/axe/tempbasic.ron +++ /dev/null @@ -1,10 +0,0 @@ -BasicMelee( - energy_cost: 0, - buildup_duration: 600, - swing_duration: 100, - recover_duration: 300, - base_damage: 120, - knockback: 0.0, - range: 3.5, - max_angle: 20.0, -), \ No newline at end of file diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/basic.ron index d2de738791..4747e5a087 100644 --- a/assets/common/abilities/bow/basic.ron +++ b/assets/common/abilities/bow/basic.ron @@ -1,7 +1,7 @@ BasicRanged( energy_cost: 0, - buildup_duration: 100, - recover_duration: 400, + buildup_duration: 200, + recover_duration: 300, projectile: Arrow( damage: 40.0, knockback: 10.0, @@ -11,4 +11,5 @@ BasicRanged( projectile_light: None, projectile_gravity: Some(Gravity(0.2)), projectile_speed: 100.0, -), \ No newline at end of file + can_continue: true, +) \ No newline at end of file diff --git a/assets/common/abilities/bow/charged.ron b/assets/common/abilities/bow/charged.ron index 1f3ebd47c1..8de9cf9fbc 100644 --- a/assets/common/abilities/bow/charged.ron +++ b/assets/common/abilities/bow/charged.ron @@ -5,6 +5,7 @@ ChargedRanged( max_damage: 200, initial_knockback: 10.0, max_knockback: 20.0, + speed: 1.0, buildup_duration: 100, charge_duration: 1500, recover_duration: 500, @@ -13,4 +14,4 @@ ChargedRanged( projectile_gravity: Some(Gravity(0.2)), initial_projectile_speed: 100.0, max_projectile_speed: 500.0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index 520e3811d0..619c326200 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -15,4 +15,4 @@ RepeaterRanged( projectile_gravity: Some(Gravity(0.2)), projectile_speed: 100.0, reps_remaining: 5, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/debug/forwardboost.ron b/assets/common/abilities/debug/forwardboost.ron index eebed9703c..81aefd978e 100644 --- a/assets/common/abilities/debug/forwardboost.ron +++ b/assets/common/abilities/debug/forwardboost.ron @@ -1,4 +1,4 @@ -CharacterAbility::Boost( +Boost( movement_duration: 50, only_up: false, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/debug/possess.ron b/assets/common/abilities/debug/possess.ron index 7a620b87e8..99563c1e78 100644 --- a/assets/common/abilities/debug/possess.ron +++ b/assets/common/abilities/debug/possess.ron @@ -2,13 +2,7 @@ BasicRanged( energy_cost: 0, buildup_duration: 0, recover_duration: 10, - projectile: ( - hit_solid: [Stick], - hit_entity: [Stick, Possess], - time_left: 10, // secs - owner: None, - ignore_group: false, - ), + projectile: Possess, projectile_body: Object(ArrowSnake), /*projectile_light: Some(LightEmitter { col: (0.0, 1.0, 0.33).into(), @@ -16,4 +10,5 @@ BasicRanged( }),*/ projectile_gravity: None, projectile_speed: 100.0, -), \ No newline at end of file + can_continue: false, +) \ No newline at end of file diff --git a/assets/common/abilities/debug/upboost.ron b/assets/common/abilities/debug/upboost.ron index 6b293a83b8..d0456d54ba 100644 --- a/assets/common/abilities/debug/upboost.ron +++ b/assets/common/abilities/debug/upboost.ron @@ -1,4 +1,4 @@ -CharacterAbility::Boost( +Boost( movement_duration: 50, only_up: true, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/farming/basic.ron b/assets/common/abilities/farming/basic.ron index 3b7aa36fca..0a60b62df7 100644 --- a/assets/common/abilities/farming/basic.ron +++ b/assets/common/abilities/farming/basic.ron @@ -1,5 +1,5 @@ BasicMelee( - energy_cost: 1, + energy_cost: 0, buildup_duration: 600, swing_duration: 100, recover_duration: 150, diff --git a/assets/common/abilities/hammer/charged.ron b/assets/common/abilities/hammer/charged.ron index 4998616bd1..5b69a8d716 100644 --- a/assets/common/abilities/hammer/charged.ron +++ b/assets/common/abilities/hammer/charged.ron @@ -1,5 +1,5 @@ ChargedMelee( - energy_cost: 1, + energy_cost: 0, energy_drain: 300, initial_damage: 10, max_damage: 170, @@ -7,7 +7,8 @@ ChargedMelee( max_knockback: 60.0, range: 3.5, max_angle: 30.0, + speed: 1.0, charge_duration: 1200, swing_duration: 200, recover_duration: 300, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/hammer/leap.ron b/assets/common/abilities/hammer/leap.ron index f83731582f..70ec3019bf 100644 --- a/assets/common/abilities/hammer/leap.ron +++ b/assets/common/abilities/hammer/leap.ron @@ -10,4 +10,4 @@ LeapMelee( max_angle: 360.0, forward_leap_strength: 28.0, vertical_leap_strength: 8.0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/hammer/singlestrike.ron b/assets/common/abilities/hammer/singlestrike.ron new file mode 100644 index 0000000000..57fc0ffa8a --- /dev/null +++ b/assets/common/abilities/hammer/singlestrike.ron @@ -0,0 +1,21 @@ +ComboMelee( + stage_data: [( + stage: 1, + base_damage: 120, + max_damage: 150, + damage_increase: 10, + knockback: 0.0, + range: 3.5, + angle: 20.0, + base_buildup_duration: 600, + base_swing_duration: 60, + base_recover_duration: 300, + forward_movement: 0.0, + )], + initial_energy_gain: 0, + max_energy_gain: 100, + energy_increase: 20, + speed_increase: 0.05, + max_speed_increase: 1.4, + is_interruptible: false, +) \ No newline at end of file diff --git a/assets/common/abilities/hammer/tempbasic.ron b/assets/common/abilities/hammer/tempbasic.ron deleted file mode 100644 index 001e96f0f6..0000000000 --- a/assets/common/abilities/hammer/tempbasic.ron +++ /dev/null @@ -1,10 +0,0 @@ -BasicMelee( - energy_cost: 0, - buildup_duration: 600, - swing_duration: 100, - recover_duration: 300, - base_damage: 120, - knockback: 0.0, - range: 3.5, - max_angle: 20.0, -), \ No newline at end of file diff --git a/assets/common/abilities/sceptre/healingbeam.ron b/assets/common/abilities/sceptre/healingbeam.ron index 91b7c19d1a..88fc4f02eb 100644 --- a/assets/common/abilities/sceptre/healingbeam.ron +++ b/assets/common/abilities/sceptre/healingbeam.ron @@ -11,4 +11,4 @@ BasicBeam( energy_regen: 50, energy_cost: 100, energy_drain: 0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/sceptre/healingbomb.ron b/assets/common/abilities/sceptre/healingbomb.ron index 2a0204ba08..427cd42424 100644 --- a/assets/common/abilities/sceptre/healingbomb.ron +++ b/assets/common/abilities/sceptre/healingbomb.ron @@ -14,4 +14,5 @@ BasicRanged( }),*/ projectile_gravity: Some(Gravity(0.5)), projectile_speed: 40.0, -), \ No newline at end of file + can_continue: false, +) \ No newline at end of file diff --git a/assets/common/abilities/shield/block.ron b/assets/common/abilities/shield/block.ron new file mode 100644 index 0000000000..ca0309ede7 --- /dev/null +++ b/assets/common/abilities/shield/block.ron @@ -0,0 +1 @@ +BasicBlock \ No newline at end of file diff --git a/assets/common/abilities/shield/tempbasic.ron b/assets/common/abilities/shield/tempbasic.ron index d0023f388c..eca1996eb1 100644 --- a/assets/common/abilities/shield/tempbasic.ron +++ b/assets/common/abilities/shield/tempbasic.ron @@ -7,4 +7,4 @@ BasicMelee( knockback: 0.0, range: 3.0, max_angle: 120.0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/staff/firebomb.ron b/assets/common/abilities/staff/firebomb.ron index f2c75d5cf7..05a18db3d3 100644 --- a/assets/common/abilities/staff/firebomb.ron +++ b/assets/common/abilities/staff/firebomb.ron @@ -5,7 +5,7 @@ BasicRanged( projectile: Fireball( damage: 100.0, radius: 5.0, - energy_regen: 0, + energy_regen: 50, ), projectile_body: Object(BoltFire), /*projectile_light: Some(LightEmitter { @@ -14,4 +14,5 @@ BasicRanged( }),*/ projectile_gravity: Some(Gravity(0.3)), projectile_speed: 60.0, -), \ No newline at end of file + can_continue: true, +) \ No newline at end of file diff --git a/assets/common/abilities/staff/fireshockwave.ron b/assets/common/abilities/staff/fireshockwave.ron index f5eed9d021..fabf1b00b5 100644 --- a/assets/common/abilities/staff/fireshockwave.ron +++ b/assets/common/abilities/staff/fireshockwave.ron @@ -11,4 +11,4 @@ Shockwave( shockwave_duration: 500, requires_ground: false, move_efficiency: 0.1, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/staff/flamethrower.ron b/assets/common/abilities/staff/flamethrower.ron index acc4a510f9..1fccd24fe3 100644 --- a/assets/common/abilities/staff/flamethrower.ron +++ b/assets/common/abilities/staff/flamethrower.ron @@ -11,4 +11,4 @@ BasicBeam( energy_regen: 0, energy_cost: 0, energy_drain: 350, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/sword/dash.ron b/assets/common/abilities/sword/dash.ron index 2935ff810b..2f08b14737 100644 --- a/assets/common/abilities/sword/dash.ron +++ b/assets/common/abilities/sword/dash.ron @@ -14,4 +14,4 @@ DashMelee( recover_duration: 500, infinite_charge: true, is_interruptible: true, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/sword/spin.ron b/assets/common/abilities/sword/spin.ron index 1ae86a7853..94b55b93bc 100644 --- a/assets/common/abilities/sword/spin.ron +++ b/assets/common/abilities/sword/spin.ron @@ -11,4 +11,4 @@ SpinMelee( is_interruptible: true, forward_speed: 1.0, num_spins: 3, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/sword/triplestrike.ron b/assets/common/abilities/sword/triplestrike.ron index b699b78544..ffdd3097b8 100644 --- a/assets/common/abilities/sword/triplestrike.ron +++ b/assets/common/abilities/sword/triplestrike.ron @@ -1,4 +1,4 @@ -ComboMelee ( +ComboMelee( stage_data: [ ( stage: 1, @@ -23,7 +23,7 @@ ComboMelee ( angle: 180.0, base_buildup_duration: 400, base_swing_duration: 600, - base_recover_duration: 400 + base_recover_duration: 400, forward_movement: 0.0, ), ( @@ -46,4 +46,4 @@ ComboMelee ( speed_increase: 0.05, max_speed_increase: 1.8, is_interruptible: true, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/unique/stonegolemfist/basic.ron b/assets/common/abilities/unique/stonegolemfist/basic.ron index 53f8993be6..2ce4d66744 100644 --- a/assets/common/abilities/unique/stonegolemfist/basic.ron +++ b/assets/common/abilities/unique/stonegolemfist/basic.ron @@ -7,4 +7,4 @@ BasicMelee( base_damage: 200, range: 5.0, max_angle: 120.0, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/unique/stonegolemfist/shockwave.ron b/assets/common/abilities/unique/stonegolemfist/shockwave.ron index ecac0f22c1..ac29382ee5 100644 --- a/assets/common/abilities/unique/stonegolemfist/shockwave.ron +++ b/assets/common/abilities/unique/stonegolemfist/shockwave.ron @@ -11,4 +11,4 @@ Shockwave( shockwave_duration: 2000, requires_ground: true, move_efficiency: 0.05, -), \ No newline at end of file +) \ No newline at end of file diff --git a/assets/common/abilities/weapon_ability_manifest.ron b/assets/common/abilities/weapon_ability_manifest.ron index c8383f77d8..6694484688 100644 --- a/assets/common/abilities/weapon_ability_manifest.ron +++ b/assets/common/abilities/weapon_ability_manifest.ron @@ -9,14 +9,14 @@ ], ), Axe: ( - primary: "common.abilities.axe.tempbasic", + primary: "common.abilities.axe.doublestrike", secondary: "common.abilities.axe.spin", skills: [ "common.abilities.axe.leap", ], ), Hammer: ( - primary: "common.abilities.hammer.tempbasic", + primary: "common.abilities.hammer.singlestrike", secondary: "common.abilities.hammer.charged", skills: [ "common.abilities.hammer.leap", @@ -48,7 +48,7 @@ ), Shield: ( primary: "common.abilities.shield.tempbasic", - secondary: "common.abilities.shield.tempbasic", + secondary: "common.abilities.shield.block", skills: [], ), Unique(StoneGolemFist): ( diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 621b80407f..46ca1a9fe4 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1,4 +1,5 @@ use crate::{ + assets::{self, Asset}, comp::{ item::{armor::Protection, Item, ItemKind}, projectile::ProjectileConstructor, @@ -15,7 +16,7 @@ use arraygen::Arraygen; use serde::{Deserialize, Serialize}; use specs::{Component, FlaggedStorage}; use specs_idvs::IdvStorage; -use std::time::Duration; +use std::{fs::File, io::BufReader, time::Duration}; use vek::Vec3; #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)] @@ -60,9 +61,9 @@ impl From<&CharacterState> for CharacterAbilityType { pub enum CharacterAbility { BasicMelee { energy_cost: u32, - buildup_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + swing_duration: u64, + recover_duration: u64, base_damage: u32, knockback: f32, range: f32, @@ -70,8 +71,8 @@ pub enum CharacterAbility { }, BasicRanged { energy_cost: u32, - buildup_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + recover_duration: u64, projectile: ProjectileConstructor, projectile_body: Body, projectile_light: Option, @@ -81,10 +82,10 @@ pub enum CharacterAbility { }, RepeaterRanged { energy_cost: u32, - movement_duration: Duration, - buildup_duration: Duration, - shoot_duration: Duration, - recover_duration: Duration, + movement_duration: u64, + buildup_duration: u64, + shoot_duration: u64, + recover_duration: u64, leap: Option, projectile: ProjectileConstructor, projectile_body: Body, @@ -94,7 +95,7 @@ pub enum CharacterAbility { reps_remaining: u32, }, Boost { - movement_duration: Duration, + movement_duration: u64, only_up: bool, }, DashMelee { @@ -107,23 +108,23 @@ pub enum CharacterAbility { angle: f32, energy_drain: u32, forward_speed: f32, - buildup_duration: Duration, - charge_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + charge_duration: u64, + swing_duration: u64, + recover_duration: u64, infinite_charge: bool, is_interruptible: bool, }, BasicBlock, Roll { energy_cost: u32, - buildup_duration: Duration, - movement_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + movement_duration: u64, + recover_duration: u64, roll_strength: f32, }, ComboMelee { - stage_data: Vec, + stage_data: Vec>, initial_energy_gain: u32, max_energy_gain: u32, energy_increase: u32, @@ -133,10 +134,10 @@ pub enum CharacterAbility { }, LeapMelee { energy_cost: u32, - buildup_duration: Duration, - movement_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + movement_duration: u64, + swing_duration: u64, + recover_duration: u64, base_damage: u32, range: f32, max_angle: f32, @@ -145,9 +146,9 @@ pub enum CharacterAbility { vertical_leap_strength: f32, }, SpinMelee { - buildup_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + swing_duration: u64, + recover_duration: u64, base_damage: u32, knockback: f32, range: f32, @@ -168,9 +169,9 @@ pub enum CharacterAbility { range: f32, max_angle: f32, speed: f32, - charge_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + charge_duration: u64, + swing_duration: u64, + recover_duration: u64, }, ChargedRanged { energy_cost: u32, @@ -180,9 +181,9 @@ pub enum CharacterAbility { initial_knockback: f32, max_knockback: f32, speed: f32, - buildup_duration: Duration, - charge_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + charge_duration: u64, + recover_duration: u64, projectile_body: Body, projectile_light: Option, projectile_gravity: Option, @@ -191,22 +192,22 @@ pub enum CharacterAbility { }, Shockwave { energy_cost: u32, - buildup_duration: Duration, - swing_duration: Duration, - recover_duration: Duration, + buildup_duration: u64, + swing_duration: u64, + recover_duration: u64, damage: u32, knockback: Knockback, shockwave_angle: f32, shockwave_vertical_angle: f32, shockwave_speed: f32, - shockwave_duration: Duration, + shockwave_duration: u64, requires_ground: bool, move_efficiency: f32, }, BasicBeam { - buildup_duration: Duration, - recover_duration: Duration, - beam_duration: Duration, + buildup_duration: u64, + recover_duration: u64, + beam_duration: u64, base_hps: u32, base_dps: u32, tick_rate: f32, @@ -219,6 +220,29 @@ pub enum CharacterAbility { }, } +impl Default for CharacterAbility { + fn default() -> Self { + CharacterAbility::BasicMelee { + energy_cost: 0, + buildup_duration: 250, + swing_duration: 250, + recover_duration: 500, + base_damage: 10, + knockback: 0.0, + range: 3.5, + max_angle: 15.0, + } + } +} + +impl Asset for CharacterAbility { + const ENDINGS: &'static [&'static str] = &["ron"]; + + fn parse(buf_reader: BufReader, _specifier: &str) -> Result { + ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error) + } +} + impl CharacterAbility { /// Attempts to fulfill requirements, mutating `update` (taking energy) if /// applicable. @@ -283,9 +307,9 @@ impl CharacterAbility { fn default_roll() -> CharacterAbility { CharacterAbility::Roll { energy_cost: 100, - buildup_duration: Duration::from_millis(100), - movement_duration: Duration::from_millis(250), - recover_duration: Duration::from_millis(150), + buildup_duration: 100, + movement_duration: 250, + recover_duration: 150, roll_strength: 2.5, } } @@ -304,14 +328,13 @@ pub struct ItemConfig { impl From for ItemConfig { fn from(item: Item) -> Self { if let ItemKind::Tool(tool) = &item.kind() { - let mut abilities = tool.get_abilities(); - let mut ability_drain = abilities.drain(..); + let abilities = tool.get_abilities().clone(); return ItemConfig { item, - ability1: ability_drain.next(), - ability2: ability_drain.next(), - ability3: ability_drain.next(), + ability1: Some(abilities.primary), + ability2: Some(abilities.secondary), + ability3: abilities.skills.get(0).map(|x| x.clone()), block_ability: None, dodge_ability: Some(CharacterAbility::default_roll()), }; @@ -393,9 +416,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { energy_cost: _, } => CharacterState::BasicMelee(basic_melee::Data { static_data: basic_melee::StaticData { - buildup_duration: *buildup_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), base_damage: *base_damage, knockback: *knockback, range: *range, @@ -417,8 +440,8 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { energy_cost: _, } => CharacterState::BasicRanged(basic_ranged::Data { static_data: basic_ranged::StaticData { - buildup_duration: *buildup_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + recover_duration: Duration::from_millis(*recover_duration), projectile: *projectile, projectile_body: *projectile_body, projectile_light: *projectile_light, @@ -437,7 +460,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { only_up, } => CharacterState::Boost(boost::Data { static_data: boost::StaticData { - movement_duration: *movement_duration, + movement_duration: Duration::from_millis(*movement_duration), only_up: *only_up, }, timer: Duration::default(), @@ -469,10 +492,10 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { energy_drain: *energy_drain, forward_speed: *forward_speed, infinite_charge: *infinite_charge, - buildup_duration: *buildup_duration, - charge_duration: *charge_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + charge_duration: Duration::from_millis(*charge_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), is_interruptible: *is_interruptible, ability_key: key, }, @@ -491,9 +514,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { roll_strength, } => CharacterState::Roll(roll::Data { static_data: roll::StaticData { - buildup_duration: *buildup_duration, - movement_duration: *movement_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + movement_duration: Duration::from_millis(*movement_duration), + recover_duration: Duration::from_millis(*recover_duration), roll_strength: *roll_strength, }, timer: Duration::default(), @@ -512,7 +535,11 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { } => CharacterState::ComboMelee(combo_melee::Data { static_data: combo_melee::StaticData { num_stages: stage_data.len() as u32, - stage_data: stage_data.clone(), + stage_data: stage_data + .clone() + .into_iter() + .map(|stage| stage.to_duration()) + .collect(), initial_energy_gain: *initial_energy_gain, max_energy_gain: *max_energy_gain, energy_increase: *energy_increase, @@ -541,10 +568,10 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { vertical_leap_strength, } => CharacterState::LeapMelee(leap_melee::Data { static_data: leap_melee::StaticData { - buildup_duration: *buildup_duration, - movement_duration: *movement_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + movement_duration: Duration::from_millis(*movement_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), base_damage: *base_damage, knockback: *knockback, range: *range, @@ -571,9 +598,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { num_spins, } => CharacterState::SpinMelee(spin_melee::Data { static_data: spin_melee::StaticData { - buildup_duration: *buildup_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), base_damage: *base_damage, knockback: *knockback, range: *range, @@ -614,9 +641,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { speed: *speed, range: *range, max_angle: *max_angle, - charge_duration: *charge_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + charge_duration: Duration::from_millis(*charge_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), ability_key: key, }, stage_section: StageSection::Charge, @@ -642,9 +669,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { max_projectile_speed, } => CharacterState::ChargedRanged(charged_ranged::Data { static_data: charged_ranged::StaticData { - buildup_duration: *buildup_duration, - charge_duration: *charge_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + charge_duration: Duration::from_millis(*charge_duration), + recover_duration: Duration::from_millis(*recover_duration), energy_drain: *energy_drain, initial_damage: *initial_damage, max_damage: *max_damage, @@ -677,10 +704,10 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { reps_remaining, } => CharacterState::RepeaterRanged(repeater_ranged::Data { static_data: repeater_ranged::StaticData { - movement_duration: *movement_duration, - buildup_duration: *buildup_duration, - shoot_duration: *shoot_duration, - recover_duration: *recover_duration, + movement_duration: Duration::from_millis(*movement_duration), + buildup_duration: Duration::from_millis(*buildup_duration), + shoot_duration: Duration::from_millis(*shoot_duration), + recover_duration: Duration::from_millis(*recover_duration), leap: *leap, projectile: *projectile, projectile_body: *projectile_body, @@ -707,15 +734,15 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { move_efficiency, } => CharacterState::Shockwave(shockwave::Data { static_data: shockwave::StaticData { - buildup_duration: *buildup_duration, - swing_duration: *swing_duration, - recover_duration: *recover_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + swing_duration: Duration::from_millis(*swing_duration), + recover_duration: Duration::from_millis(*recover_duration), damage: *damage, knockback: *knockback, shockwave_angle: *shockwave_angle, shockwave_vertical_angle: *shockwave_vertical_angle, shockwave_speed: *shockwave_speed, - shockwave_duration: *shockwave_duration, + shockwave_duration: Duration::from_millis(*shockwave_duration), requires_ground: *requires_ground, move_efficiency: *move_efficiency, }, @@ -737,9 +764,9 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { energy_drain, } => CharacterState::BasicBeam(basic_beam::Data { static_data: basic_beam::StaticData { - buildup_duration: *buildup_duration, - recover_duration: *recover_duration, - beam_duration: *beam_duration, + buildup_duration: Duration::from_millis(*buildup_duration), + recover_duration: Duration::from_millis(*recover_duration), + beam_duration: Duration::from_millis(*beam_duration), base_hps: *base_hps, base_dps: *base_dps, tick_rate: *tick_rate, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 584001b427..351802fbe9 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -2,6 +2,7 @@ // version in voxygen\src\meta.rs in order to reset save files to being empty use crate::{ + assets::{self, Asset}, comp::{ body::object, projectile::ProjectileConstructor, Body, CharacterAbility, Gravity, LightEmitter, @@ -10,7 +11,8 @@ use crate::{ Knockback, }; use serde::{Deserialize, Serialize}; -use std::time::Duration; +use std::{collections::HashMap, fs::File, io::BufReader, time::Duration}; +use tracing::error; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ToolKind { @@ -93,8 +95,20 @@ impl Tool { Duration::from_millis(millis).div_f32(self.base_speed()) } - // TODO: Before merging ron file branch, ensure these are double checked against ron files. - pub fn get_abilities(&self) -> Vec { + pub fn get_abilities(&self) -> AbilitySet { + let base_abilities = match AbilityMap::load("common.abilities.weapon_ability_manifest") { + Ok(map) => map.0.get(&self.kind).map(|a| a.clone()).unwrap_or_default(), + Err(err) => { + error!(?err, "Error unwrapping"); + AbilitySet::default() + }, + }; + base_abilities + } + + // TODO: Before merging ron file branch, ensure these are double checked against + // ron files. + /*pub fn get_abilities(&self) -> Vec { use CharacterAbility::*; use ToolKind::*; @@ -534,6 +548,69 @@ impl Tool { max_angle: 15.0, }], } + }*/ +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct AbilitySet { + pub primary: T, + pub secondary: T, + pub skills: Vec, +} + +impl AbilitySet { + pub fn map U>(self, mut f: F) -> AbilitySet { + AbilitySet { + primary: f(self.primary), + secondary: f(self.secondary), + skills: self.skills.iter().map(|x| f(x.clone())).collect(), + } + } +} + +impl Default for AbilitySet { + fn default() -> Self { + AbilitySet { + primary: CharacterAbility::default(), + secondary: CharacterAbility::default(), + skills: vec![], + } + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct AbilityMap(HashMap>); +impl Asset for AbilityMap { + const ENDINGS: &'static [&'static str] = &["ron"]; + + fn parse(buf_reader: BufReader, specifier: &str) -> Result { + ron::de::from_reader::, AbilityMap>(buf_reader) + .map(|map| { + AbilityMap( + map.0 + .into_iter() + .map(|(kind, set)| { + ( + kind, + set.map(|s| match CharacterAbility::load(&s) { + Ok(ability) => ability.as_ref().clone(), + Err(err) => { + error!( + ?err, + "Error loading CharacterAbility: {} for the ability \ + map: {} replacing with default", + s, + specifier + ); + CharacterAbility::default() + }, + }), + ) + }) + .collect(), + ) + }) + .map_err(assets::Error::parse_error) } } diff --git a/common/src/loadout_builder.rs b/common/src/loadout_builder.rs index c816a0dc09..2811771d2e 100644 --- a/common/src/loadout_builder.rs +++ b/common/src/loadout_builder.rs @@ -152,9 +152,9 @@ impl LoadoutBuilder { item: Item::new_from_asset_expect("common.items.weapons.empty.empty"), ability1: Some(CharacterAbility::BasicMelee { energy_cost: 0, - buildup_duration: Duration::from_millis(0), - swing_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(300), + buildup_duration: 0, + swing_duration: 100, + recover_duration: 300, base_damage: 40, knockback: 0.0, range: 3.5, @@ -334,9 +334,9 @@ impl LoadoutBuilder { item: Item::new_from_asset_expect("common.items.weapons.empty.empty"), ability1: Some(CharacterAbility::BasicMelee { energy_cost: 10, - buildup_duration: Duration::from_millis(500), - swing_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(100), + buildup_duration: 500, + swing_duration: 100, + recover_duration: 100, base_damage: body.base_dmg(), knockback: 0.0, range: body.base_range(), diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index ad3a3aae84..b4cfde8b80 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Stage { +pub struct Stage { /// Specifies which stage the combo attack is in pub stage: u32, /// Initial damage of stage @@ -24,23 +24,41 @@ pub struct Stage { /// Angle of attack pub angle: f32, /// Initial buildup duration of stage (how long until state can deal damage) - pub base_buildup_duration: Duration, + pub base_buildup_duration: T, /// Duration of stage spent in swing (controls animation stuff, and can also /// be used to handle movement separately to buildup) - pub base_swing_duration: Duration, + pub base_swing_duration: T, /// Initial recover duration of stage (how long until character exits state) - pub base_recover_duration: Duration, + pub base_recover_duration: T, /// How much forward movement there is in the swing portion of the stage pub forward_movement: f32, } +impl Stage { + pub fn to_duration(self) -> Stage { + Stage:: { + stage: self.stage, + base_damage: self.base_damage, + max_damage: self.max_damage, + damage_increase: self.damage_increase, + knockback: self.knockback, + range: self.range, + angle: self.angle, + base_buildup_duration: Duration::from_millis(self.base_buildup_duration), + base_swing_duration: Duration::from_millis(self.base_swing_duration), + base_recover_duration: Duration::from_millis(self.base_recover_duration), + forward_movement: self.forward_movement, + } + } +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] /// Separated out to condense update portions of character state pub struct StaticData { /// Indicates number of stages in combo pub num_stages: u32, /// Data for each stage - pub stage_data: Vec, + pub stage_data: Vec>, /// Initial energy gain per strike pub initial_energy_gain: u32, /// Max energy gain per strike From 275deabae9819e5666753763ad0837dfe817e57e Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 11 Nov 2020 23:00:17 -0600 Subject: [PATCH 07/10] Started moving loading of ability manifest to an ecs variable. --- common/src/comp/ability.rs | 8 +-- common/src/comp/inventory/item/mod.rs | 2 +- common/src/comp/inventory/item/tool.rs | 2 +- common/src/comp/inventory/slot.rs | 50 ++++++++++--------- common/src/loadout_builder.rs | 22 +++----- common/src/state.rs | 2 + server/src/character_creator.rs | 5 +- server/src/cmd.rs | 9 ++-- server/src/events/interaction.rs | 8 +-- server/src/events/inventory_manip.rs | 16 ++++-- server/src/lib.rs | 8 +-- server/src/persistence/character.rs | 13 +++-- .../src/persistence/character/conversions.rs | 8 +-- server/src/persistence/character_loader.rs | 16 ++++-- server/src/sys/msg/character_screen.rs | 7 ++- server/src/sys/terrain.rs | 8 +-- voxygen/src/lib.rs | 4 +- voxygen/src/main.rs | 2 +- voxygen/src/menu/char_selection/mod.rs | 6 +-- voxygen/src/menu/char_selection/ui/mod.rs | 16 +++--- voxygen/src/menu/main/mod.rs | 6 +-- voxygen/src/run.rs | 11 ++-- voxygen/src/session.rs | 4 +- voxygen/src/singleplayer.rs | 4 +- 24 files changed, 133 insertions(+), 104 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 46ca1a9fe4..77b6fb6175 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1,7 +1,7 @@ use crate::{ assets::{self, Asset}, comp::{ - item::{armor::Protection, Item, ItemKind}, + item::{armor::Protection, tool::AbilityMap, Item, ItemKind}, projectile::ProjectileConstructor, Body, CharacterState, EnergySource, Gravity, LightEmitter, StateUpdate, }, @@ -325,10 +325,10 @@ pub struct ItemConfig { pub dodge_ability: Option, } -impl From for ItemConfig { - fn from(item: Item) -> Self { +impl From<(Item, &AbilityMap)> for ItemConfig { + fn from((item, map): (Item, &AbilityMap)) -> Self { if let ItemKind::Tool(tool) = &item.kind() { - let abilities = tool.get_abilities().clone(); + let abilities = tool.get_abilities(map).clone(); return ItemConfig { item, diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 6aa649971b..7933596660 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -2,7 +2,7 @@ pub mod armor; pub mod tool; // Reexports -pub use tool::{Hands, Tool, ToolKind, UniqueKind}; +pub use tool::{AbilitySet, Hands, Tool, ToolKind, UniqueKind}; use crate::{ assets::{self, Asset, Error}, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 351802fbe9..bc19b56ea7 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -95,7 +95,7 @@ impl Tool { Duration::from_millis(millis).div_f32(self.base_speed()) } - pub fn get_abilities(&self) -> AbilitySet { + pub fn get_abilities(&self, map: &AbilityMap) -> AbilitySet { let base_abilities = match AbilityMap::load("common.abilities.weapon_ability_manifest") { Ok(map) => map.0.get(&self.kind).map(|a| a.clone()).unwrap_or_default(), Err(err) => { diff --git a/common/src/comp/inventory/slot.rs b/common/src/comp/inventory/slot.rs index b199c7417e..2298623184 100644 --- a/common/src/comp/inventory/slot.rs +++ b/common/src/comp/inventory/slot.rs @@ -1,6 +1,6 @@ use crate::{ comp, - comp::{item, item::armor, ItemConfig}, + comp::{item::{self, armor, tool::AbilityMap}, ItemConfig}, }; use comp::{Inventory, Loadout}; use serde::{Deserialize, Serialize}; @@ -90,6 +90,7 @@ fn loadout_replace( equip_slot: EquipSlot, item: Option, loadout: &mut Loadout, + map: &AbilityMap, ) -> Option { use std::mem::replace; match equip_slot { @@ -107,10 +108,10 @@ fn loadout_replace( EquipSlot::Lantern => replace(&mut loadout.lantern, item), EquipSlot::Glider => replace(&mut loadout.glider, item), EquipSlot::Mainhand => { - replace(&mut loadout.active_item, item.map(ItemConfig::from)).map(|i| i.item) + replace(&mut loadout.active_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item) }, EquipSlot::Offhand => { - replace(&mut loadout.second_item, item.map(ItemConfig::from)).map(|i| i.item) + replace(&mut loadout.second_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item) }, } } @@ -122,8 +123,9 @@ fn loadout_insert( equip_slot: EquipSlot, item: item::Item, loadout: &mut Loadout, + map: &AbilityMap, ) -> Option { - loadout_replace(equip_slot, Some(item), loadout) + loadout_replace(equip_slot, Some(item), loadout, map) } /// Remove an item from a loadout. @@ -151,8 +153,8 @@ fn loadout_insert( /// loadout_remove(slot, &mut loadout); /// assert_eq!(None, loadout.active_item); /// ``` -pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout) -> Option { - loadout_replace(equip_slot, None, loadout) +pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout, map: &AbilityMap) -> Option { + loadout_replace(equip_slot, None, loadout, map) } /// Swap item in an inventory slot with one in a loadout slot. @@ -161,6 +163,7 @@ fn swap_inventory_loadout( equip_slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout, + map: &AbilityMap, ) { // Check if loadout slot can hold item if inventory @@ -168,7 +171,7 @@ fn swap_inventory_loadout( .map_or(true, |item| equip_slot.can_hold(&item.kind())) { // Take item from loadout - let from_equip = loadout_remove(equip_slot, loadout); + let from_equip = loadout_remove(equip_slot, loadout, map); // Swap with item in the inventory let from_inv = if let Some(item) = from_equip { // If this fails and we get item back as an err it will just be put back in the @@ -179,14 +182,14 @@ fn swap_inventory_loadout( }; // Put item from the inventory in loadout if let Some(item) = from_inv { - loadout_insert(equip_slot, item, loadout).unwrap_none(); // Can never fail + loadout_insert(equip_slot, item, loadout, map).unwrap_none(); // Can never fail } } } /// Swap items in loadout. Does nothing if items are not compatible with their /// new slots. -fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) { +fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout, map: &AbilityMap) { // Ensure that the slots are not the same if slot_a == slot_b { warn!("Tried to swap equip slot with itself"); @@ -194,19 +197,19 @@ fn swap_loadout(slot_a: EquipSlot, slot_b: EquipSlot, loadout: &mut Loadout) { } // Get items from the slots - let item_a = loadout_remove(slot_a, loadout); - let item_b = loadout_remove(slot_b, loadout); + let item_a = loadout_remove(slot_a, loadout, map); + let item_b = loadout_remove(slot_b, loadout, map); // Check if items can go in the other slots if item_a.as_ref().map_or(true, |i| slot_b.can_hold(&i.kind())) && item_b.as_ref().map_or(true, |i| slot_a.can_hold(&i.kind())) { // Swap - loadout_replace(slot_b, item_a, loadout).unwrap_none(); - loadout_replace(slot_a, item_b, loadout).unwrap_none(); + loadout_replace(slot_b, item_a, loadout, map).unwrap_none(); + loadout_replace(slot_a, item_b, loadout, map).unwrap_none(); } else { // Otherwise put the items back - loadout_replace(slot_a, item_a, loadout).unwrap_none(); - loadout_replace(slot_b, item_b, loadout).unwrap_none(); + loadout_replace(slot_a, item_a, loadout, map).unwrap_none(); + loadout_replace(slot_b, item_b, loadout, map).unwrap_none(); } } @@ -219,6 +222,7 @@ pub fn swap( slot_b: Slot, inventory: Option<&mut Inventory>, loadout: Option<&mut Loadout>, + map: &AbilityMap, ) { match (slot_a, slot_b) { (Slot::Inventory(slot_a), Slot::Inventory(slot_b)) => { @@ -227,12 +231,12 @@ pub fn swap( (Slot::Inventory(inv_slot), Slot::Equip(equip_slot)) | (Slot::Equip(equip_slot), Slot::Inventory(inv_slot)) => { if let Some((inventory, loadout)) = loadout.and_then(|l| inventory.map(|i| (i, l))) { - swap_inventory_loadout(inv_slot, equip_slot, inventory, loadout); + swap_inventory_loadout(inv_slot, equip_slot, inventory, loadout, map); } }, (Slot::Equip(slot_a), Slot::Equip(slot_b)) => { - loadout.map(|l| swap_loadout(slot_a, slot_b, l)); + loadout.map(|l| swap_loadout(slot_a, slot_b, l, map)); }, } } @@ -261,7 +265,7 @@ pub fn swap( /// equip(0, &mut inv, &mut loadout); /// assert_eq!(Some(boots), loadout.foot); /// ``` -pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) { +pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) { use armor::Armor; use item::{armor::ArmorKind, ItemKind}; @@ -289,10 +293,10 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) { // If item is going to mainhand, put mainhand in offhand and place offhand in // inventory if let EquipSlot::Mainhand = equip_slot { - swap_loadout(EquipSlot::Mainhand, EquipSlot::Offhand, loadout); + swap_loadout(EquipSlot::Mainhand, EquipSlot::Offhand, loadout, map); } - swap_inventory_loadout(slot, equip_slot, inventory, loadout); + swap_inventory_loadout(slot, equip_slot, inventory, loadout, map); } } @@ -322,10 +326,10 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout) { /// unequip(slot, &mut inv, &mut loadout); /// assert_eq!(None, loadout.active_item); /// ``` -pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout) { - loadout_remove(slot, loadout) // Remove item from loadout +pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) { + loadout_remove(slot, loadout, map) // Remove item from loadout .and_then(|i| inventory.push(i)) // Insert into inventory - .and_then(|i| loadout_insert(slot, i, loadout)) // If that fails put back in loadout + .and_then(|i| loadout_insert(slot, i, loadout, map)) // If that fails put back in loadout .unwrap_none(); // Never fails } diff --git a/common/src/loadout_builder.rs b/common/src/loadout_builder.rs index 2811771d2e..b224dbb00e 100644 --- a/common/src/loadout_builder.rs +++ b/common/src/loadout_builder.rs @@ -1,6 +1,6 @@ use crate::comp::{ biped_large, golem, - item::{Item, ItemKind}, + item::{tool::AbilityMap, Item, ItemKind}, Alignment, Body, CharacterAbility, ItemConfig, Loadout, }; use rand::Rng; @@ -72,6 +72,7 @@ impl LoadoutBuilder { alignment: Alignment, mut main_tool: Option, is_giant: bool, + map: &AbilityMap, ) -> Self { match body { Body::Golem(golem) => match golem.species { @@ -145,21 +146,12 @@ impl LoadoutBuilder { }; let active_item = if let Some(ItemKind::Tool(_)) = main_tool.as_ref().map(|i| i.kind()) { - main_tool.map(ItemConfig::from) + main_tool.map(|item| ItemConfig::from((item, map))) } else { Some(ItemConfig { // We need the empty item so npcs can attack item: Item::new_from_asset_expect("common.items.weapons.empty.empty"), - ability1: Some(CharacterAbility::BasicMelee { - energy_cost: 0, - buildup_duration: 0, - swing_duration: 100, - recover_duration: 300, - base_damage: 40, - knockback: 0.0, - range: 3.5, - max_angle: 15.0, - }), + ability1: Some(CharacterAbility::default()), ability2: None, ability3: None, block_ability: None, @@ -370,7 +362,7 @@ impl LoadoutBuilder { /// abilities or their timings is desired, you should create and provide /// the item config directly to the [active_item](#method.active_item) /// method - pub fn default_item_config_from_item(item: Item) -> ItemConfig { ItemConfig::from(item) } + pub fn default_item_config_from_item(item: Item, map: &AbilityMap) -> ItemConfig { ItemConfig::from((item, map)) } /// Get an item's (weapon's) default /// [ItemConfig](../comp/struct.ItemConfig.html) @@ -378,8 +370,8 @@ impl LoadoutBuilder { /// the default abilities for that item via the /// [default_item_config_from_item](#method.default_item_config_from_item) /// function - pub fn default_item_config_from_str(item_ref: &str) -> ItemConfig { - Self::default_item_config_from_item(Item::new_from_asset_expect(item_ref)) + pub fn default_item_config_from_str(item_ref: &str, map: &AbilityMap) -> ItemConfig { + Self::default_item_config_from_item(Item::new_from_asset_expect(item_ref), map) } pub fn active_item(mut self, item: Option) -> Self { diff --git a/common/src/state.rs b/common/src/state.rs index 621ae69eb6..23789c14e7 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -1,4 +1,5 @@ use crate::{ + assets::Asset, comp, event::{EventBus, LocalEvent, ServerEvent}, metrics::{PhysicsMetrics, SysMetrics}, @@ -180,6 +181,7 @@ impl State { ecs.insert(BlockChange::default()); ecs.insert(TerrainChanges::default()); ecs.insert(EventBus::::default()); + ecs.insert(comp::item::tool::AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest")); // TODO: only register on the server ecs.insert(EventBus::::default()); ecs.insert(comp::group::GroupManager::default()); diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index ed285d047a..815bc2e852 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -1,6 +1,6 @@ use crate::persistence::character_loader::CharacterLoader; use common::{ - comp::{Body, Inventory, Stats}, + comp::{item::tool::AbilityMap, Body, Inventory, Stats}, loadout_builder::LoadoutBuilder, }; use specs::{Entity, ReadExpect}; @@ -12,13 +12,14 @@ pub fn create_character( character_tool: Option, body: Body, character_loader: &ReadExpect<'_, CharacterLoader>, + map: &AbilityMap, ) { let stats = Stats::new(character_alias.to_string(), body); let loadout = LoadoutBuilder::new() .defaults() .active_item(Some(LoadoutBuilder::default_item_config_from_str( - character_tool.as_deref().unwrap(), + character_tool.as_deref().unwrap(), map ))) .build(); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 7ea9da3e64..bb72face28 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -9,7 +9,7 @@ use crate::{ use chrono::{NaiveTime, Timelike}; use common::{ cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS}, - comp::{self, ChatType, Item, LightEmitter, WaypointArea}, + comp::{self, item::tool::AbilityMap, ChatType, Item, LightEmitter, WaypointArea}, effect::Effect, event::{EventBus, ServerEvent}, msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral}, @@ -655,14 +655,17 @@ fn handle_spawn( let body = body(); + let map = server.state().ecs().fetch::(); + let loadout = LoadoutBuilder::build_loadout(body, alignment, None, false, &map).build(); + drop(map); + let mut entity_base = server .state .create_npc( pos, comp::Stats::new(get_npc_name(id).into(), body), comp::Health::new(body, 1), - LoadoutBuilder::build_loadout(body, alignment, None, false) - .build(), + loadout, body, ) .with(comp::Vel(vel)) diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index 1789f94b22..f7e6c1228a 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -4,7 +4,7 @@ use crate::{ Server, }; use common::{ - comp::{self, item, Pos}, + comp::{self, item::{self, tool::AbilityMap}, Pos}, consts::MAX_MOUNT_RANGE, msg::ServerGeneral, sync::{Uid, WorldSyncExt}, @@ -103,8 +103,8 @@ pub fn handle_unmount(server: &mut Server, mounter: EcsEntity) { #[allow(clippy::nonminimal_bool)] // TODO: Pending review in #587 pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) { - let state = &server.state; - let ecs = state.ecs(); + let ecs = &server.state.ecs(); + let map = ecs.fetch::(); if let (Some(possessor), Some(possesse)) = ( ecs.entity_from_uid(possessor_uid.into()), ecs.entity_from_uid(possesse_uid.into()), @@ -177,7 +177,7 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) { let item = comp::Item::new_from_asset_expect("common.items.debug.possess"); if let item::ItemKind::Tool(_) = item.kind() { - let debug_item = comp::ItemConfig::from(item); + let debug_item = comp::ItemConfig::from((item, &*map)); std::mem::swap(&mut loadout.active_item, &mut loadout.second_item); loadout.active_item = Some(debug_item); } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 2bfa117a08..1b22247ba9 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -1,7 +1,7 @@ use crate::{client::Client, Server, StateExt}; use common::{ comp::{ - self, item, + self, item::{self, tool::AbilityMap}, slot::{self, Slot}, Pos, }, @@ -203,7 +203,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv if let Some(lantern) = lantern_opt { swap_lantern(&mut state.ecs().write_storage(), entity, &lantern); } - slot::equip(slot, inventory, loadout); + let map = state.ecs().fetch::(); + slot::equip(slot, inventory, loadout, &map); Some(comp::InventoryUpdateEvent::Used) } else { None @@ -338,7 +339,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv if slot == slot::EquipSlot::Lantern { snuff_lantern(&mut state.ecs().write_storage(), entity); } - slot::unequip(slot, inventory, loadout); + let map = state.ecs().fetch::(); + slot::unequip(slot, inventory, loadout, &map); Some(comp::InventoryUpdateEvent::Used) } else { error!(?entity, "Entity doesn't have a loadout, can't unequip..."); @@ -364,12 +366,14 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv let mut loadouts = ecs.write_storage(); let inventory = inventories.get_mut(entity); let loadout = loadouts.get_mut(entity); + let map = state.ecs().fetch::(); - slot::swap(a, b, inventory, loadout); + slot::swap(a, b, inventory, loadout, &map); // :/ drop(loadouts); drop(inventories); + drop(map); state.write_component( entity, @@ -378,6 +382,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv }, comp::InventoryManip::Drop(slot) => { + let map = state.ecs().fetch::(); let item = match slot { Slot::Inventory(slot) => state .ecs() @@ -388,8 +393,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .ecs() .write_storage() .get_mut(entity) - .and_then(|ldt| slot::loadout_remove(slot, ldt)), + .and_then(|ldt| slot::loadout_remove(slot, ldt, &map)), }; + drop(map); // FIXME: We should really require the drop and write to be atomic! if let (Some(mut item), Some(pos)) = diff --git a/server/src/lib.rs b/server/src/lib.rs index 79980fbc18..abc5de91ee 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -46,7 +46,7 @@ use crate::{ }; use common::{ cmd::ChatCommand, - comp::{self, ChatType}, + comp::{self, item::tool::AbilityMap, ChatType}, event::{EventBus, ServerEvent}, msg::{ ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg, @@ -159,9 +159,9 @@ impl Server { state .ecs_mut() .insert(CharacterUpdater::new(&persistence_db_dir)?); - state - .ecs_mut() - .insert(CharacterLoader::new(&persistence_db_dir)?); + + let character_loader = CharacterLoader::new(&persistence_db_dir, &*state.ecs().fetch::()); + state.ecs_mut().insert(character_loader); state.ecs_mut().insert(Vec::::new()); // System timers for performance monitoring diff --git a/server/src/persistence/character.rs b/server/src/persistence/character.rs index 66f29d4a03..b54dbd94c1 100644 --- a/server/src/persistence/character.rs +++ b/server/src/persistence/character.rs @@ -25,6 +25,7 @@ use crate::{ }; use common::{ character::{CharacterId, CharacterItem, MAX_CHARACTERS_PER_PLAYER}, + comp::item::tool::AbilityMap, state::Time, }; use core::ops::Range; @@ -60,6 +61,7 @@ pub fn load_character_data( requesting_player_uuid: String, char_id: CharacterId, connection: VelorenTransaction, + map: &AbilityMap, ) -> CharacterDataResult { use schema::{body::dsl::*, character::dsl::*, item::dsl::*, stats::dsl::*}; @@ -102,7 +104,7 @@ pub fn load_character_data( convert_body_from_database(&char_body)?, convert_stats_from_database(&stats_data, character_data.alias), convert_inventory_from_database_items(&inventory_items)?, - convert_loadout_from_database_items(&loadout_items)?, + convert_loadout_from_database_items(&loadout_items, map)?, waypoint, )) } @@ -117,6 +119,7 @@ pub fn load_character_data( pub fn load_character_list( player_uuid_: &str, connection: VelorenTransaction, + map: &AbilityMap, ) -> CharacterListResult { use schema::{body::dsl::*, character::dsl::*, item::dsl::*, stats::dsl::*}; @@ -149,7 +152,7 @@ pub fn load_character_list( .filter(parent_container_item_id.eq(loadout_container_id)) .load::(&*connection)?; - let loadout = convert_loadout_from_database_items(&loadout_items)?; + let loadout = convert_loadout_from_database_items(&loadout_items, map)?; Ok(CharacterItem { character: char, @@ -166,6 +169,7 @@ pub fn create_character( character_alias: &str, persisted_components: PersistedComponents, connection: VelorenTransaction, + map: &AbilityMap, ) -> CharacterListResult { use schema::item::dsl::*; @@ -299,7 +303,7 @@ pub fn create_character( ))); } - load_character_list(uuid, connection) + load_character_list(uuid, connection, map) } /// Delete a character. Returns the updated character list. @@ -307,6 +311,7 @@ pub fn delete_character( requesting_player_uuid: &str, char_id: CharacterId, connection: VelorenTransaction, + map: &AbilityMap, ) -> CharacterListResult { use schema::{body::dsl::*, character::dsl::*, stats::dsl::*}; @@ -387,7 +392,7 @@ pub fn delete_character( ))); } - load_character_list(requesting_player_uuid, connection) + load_character_list(requesting_player_uuid, connection, map) } /// Before creating a character, we ensure that the limit on the number of diff --git a/server/src/persistence/character/conversions.rs b/server/src/persistence/character/conversions.rs index 503b80be8b..0c4c0935ea 100644 --- a/server/src/persistence/character/conversions.rs +++ b/server/src/persistence/character/conversions.rs @@ -9,7 +9,7 @@ use crate::persistence::{ }; use common::{ character::CharacterId, - comp::{Body as CompBody, *}, + comp::{item::tool::AbilityMap, Body as CompBody, *}, loadout_builder, }; use core::{convert::TryFrom, num::NonZeroU64}; @@ -240,7 +240,7 @@ pub fn convert_inventory_from_database_items(database_items: &[Item]) -> Result< Ok(inventory) } -pub fn convert_loadout_from_database_items(database_items: &[Item]) -> Result { +pub fn convert_loadout_from_database_items(database_items: &[Item], map: &AbilityMap) -> Result { let mut loadout = loadout_builder::LoadoutBuilder::new(); for db_item in database_items.iter() { let item = common::comp::Item::new_from_asset(db_item.item_definition_id.as_str())?; @@ -251,8 +251,8 @@ pub fn convert_loadout_from_database_items(database_items: &[Item]) -> Result loadout = loadout.active_item(Some(ItemConfig::from(item))), - "second_item" => loadout = loadout.second_item(Some(ItemConfig::from(item))), + "active_item" => loadout = loadout.active_item(Some(ItemConfig::from((item, map)))), + "second_item" => loadout = loadout.second_item(Some(ItemConfig::from((item, map)))), "lantern" => loadout = loadout.lantern(Some(item)), "shoulder" => loadout = loadout.shoulder(Some(item)), "chest" => loadout = loadout.chest(Some(item)), diff --git a/server/src/persistence/character_loader.rs b/server/src/persistence/character_loader.rs index 049a0c47c1..2dd27f0d5f 100644 --- a/server/src/persistence/character_loader.rs +++ b/server/src/persistence/character_loader.rs @@ -3,7 +3,10 @@ use crate::persistence::{ error::Error, establish_connection, PersistedComponents, }; -use common::character::{CharacterId, CharacterItem}; +use common::{ + character::{CharacterId, CharacterItem}, + comp::item::tool::AbilityMap, +}; use crossbeam::{channel, channel::TryIter}; use std::path::Path; use tracing::error; @@ -65,12 +68,14 @@ pub struct CharacterLoader { } impl CharacterLoader { - pub fn new(db_dir: &Path) -> diesel::QueryResult { + pub fn new(db_dir: &Path, map: &AbilityMap) -> diesel::QueryResult { let (update_tx, internal_rx) = channel::unbounded::(); let (internal_tx, update_rx) = channel::unbounded::(); let mut conn = establish_connection(db_dir)?; + let map = map.clone(); + std::thread::spawn(move || { for request in internal_rx { let (entity, kind) = request; @@ -88,6 +93,7 @@ impl CharacterLoader { &character_alias, persisted_components, txn, + &map, ) })), CharacterLoaderRequestKind::DeleteCharacter { @@ -95,12 +101,12 @@ impl CharacterLoader { character_id, } => { CharacterLoaderResponseType::CharacterList(conn.transaction(|txn| { - delete_character(&player_uuid, character_id, txn) + delete_character(&player_uuid, character_id, txn, &map) })) }, CharacterLoaderRequestKind::LoadCharacterList { player_uuid } => { CharacterLoaderResponseType::CharacterList( - conn.transaction(|txn| load_character_list(&player_uuid, txn)), + conn.transaction(|txn| load_character_list(&player_uuid, txn, &map)), ) }, CharacterLoaderRequestKind::LoadCharacterData { @@ -108,7 +114,7 @@ impl CharacterLoader { character_id, } => { CharacterLoaderResponseType::CharacterData(Box::new(conn.transaction( - |txn| load_character_data(player_uuid, character_id, txn), + |txn| load_character_data(player_uuid, character_id, txn, &map), ))) }, }, diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index 6dae2482fb..d9667b8f1f 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -4,7 +4,7 @@ use crate::{ persistence::character_loader::CharacterLoader, presence::Presence, EditableSettings, }; use common::{ - comp::{ChatType, Player, UnresolvedChatMsg}, + comp::{item::tool::AbilityMap, ChatType, Player, UnresolvedChatMsg}, event::{EventBus, ServerEvent}, msg::{ClientGeneral, ServerGeneral}, span, @@ -28,6 +28,7 @@ impl Sys { editable_settings: &ReadExpect<'_, EditableSettings>, alias_validator: &ReadExpect<'_, AliasValidator>, msg: ClientGeneral, + map: &AbilityMap, ) -> Result<(), crate::error::Error> { match msg { // Request spectator state @@ -101,6 +102,7 @@ impl Sys { tool, body, character_loader, + map, ); } }, @@ -134,6 +136,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Presence>, ReadExpect<'a, EditableSettings>, ReadExpect<'a, AliasValidator>, + ReadExpect<'a, AbilityMap>, ); fn run( @@ -149,6 +152,7 @@ impl<'a> System<'a> for Sys { presences, editable_settings, alias_validator, + map, ): Self::SystemData, ) { span!(_guard, "run", "msg::character_screen::Sys::run"); @@ -171,6 +175,7 @@ impl<'a> System<'a> for Sys { &editable_settings, &alias_validator, msg, + &map, ) }); } diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 39fdcb37c2..d0f4884dfe 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -1,7 +1,7 @@ use super::SysTimer; use crate::{chunk_generator::ChunkGenerator, client::Client, presence::Presence, Tick}; use common::{ - comp::{self, bird_medium, Alignment, Pos}, + comp::{self, bird_medium, item::tool::AbilityMap, Alignment, Pos}, event::{EventBus, ServerEvent}, generation::get_npc_name, msg::ServerGeneral, @@ -12,7 +12,7 @@ use common::{ LoadoutBuilder, }; use rand::Rng; -use specs::{Join, Read, ReadStorage, System, Write, WriteExpect}; +use specs::{Join, Read, ReadExpect, ReadStorage, System, Write, WriteExpect}; use std::sync::Arc; use vek::*; @@ -35,6 +35,7 @@ impl<'a> System<'a> for Sys { ReadStorage<'a, Pos>, ReadStorage<'a, Presence>, ReadStorage<'a, Client>, + ReadExpect<'a, AbilityMap>, ); fn run( @@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys { positions, presences, clients, + map, ): Self::SystemData, ) { span!(_guard, "run", "terrain::Sys::run"); @@ -143,7 +145,7 @@ impl<'a> System<'a> for Sys { } let loadout = - LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant) + LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant, &map) .build(); let health = comp::Health::new(stats.body_type, stats.level.level()); diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index 12a585f647..09fe7cd42d 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -39,7 +39,7 @@ use crate::{ settings::Settings, window::{Event, Window}, }; -use common::{assets::watch, clock::Clock}; +use common::{assets::watch, clock::Clock, comp::item::tool::AbilityMap}; /// A type used to store state that is shared between all play states. pub struct GlobalState { @@ -110,7 +110,7 @@ pub trait PlayState { fn enter(&mut self, global_state: &mut GlobalState, direction: Direction); /// Tick the play state - fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult; + fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult; /// Get a descriptive name for this state type. fn name(&self) -> &'static str; diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index f87b32d35b..7afd1bdc81 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -192,5 +192,5 @@ fn main() { localization_watcher, }; - run::run(global_state, event_loop); + run::run(global_state, event_loop, map); } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 7fc03783de..073d93daa0 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -10,7 +10,7 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client::{self, Client}; -use common::{assets::Asset, comp, span, state::DeltaTime}; +use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span, state::DeltaTime}; use specs::WorldExt; use std::{cell::RefCell, rc::Rc}; use tracing::error; @@ -62,7 +62,7 @@ impl PlayState for CharSelectionState { self.client.borrow_mut().load_character_list(); } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { span!(_guard, "tick", "::tick"); let (client_presence, client_registered) = { let client = self.client.borrow(); @@ -88,7 +88,7 @@ impl PlayState for CharSelectionState { // Maintain the UI. let events = self .char_selection_ui - .maintain(global_state, &mut self.client.borrow_mut()); + .maintain(global_state, &mut self.client.borrow_mut(), map); for event in events { match event { diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 8fa52d72a0..682dde3055 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -24,7 +24,7 @@ use client::Client; use common::{ assets::Asset, character::{CharacterId, CharacterItem, MAX_CHARACTERS_PER_PLAYER}, - comp::{self, humanoid}, + comp::{self, humanoid, item::tool::AbilityMap}, LoadoutBuilder, }; //ImageFrame, Tooltip, @@ -179,12 +179,12 @@ impl Mode { } } - pub fn create(name: String) -> Self { + pub fn create(name: String, map: &AbilityMap) -> Self { let tool = STARTER_SWORD; let loadout = LoadoutBuilder::new() .defaults() - .active_item(Some(LoadoutBuilder::default_item_config_from_str(tool))) + .active_item(Some(LoadoutBuilder::default_item_config_from_str(tool, map))) .build(); let loadout = Box::new(loadout); @@ -1172,7 +1172,7 @@ impl Controls { .into() } - fn update(&mut self, message: Message, events: &mut Vec, characters: &[CharacterItem]) { + fn update(&mut self, message: Message, events: &mut Vec, characters: &[CharacterItem], map: &AbilityMap) { match message { Message::Back => { if matches!(&self.mode, Mode::Create { .. }) { @@ -1206,7 +1206,7 @@ impl Controls { }, Message::NewCharacter => { if matches!(&self.mode, Mode::Select { .. }) { - self.mode = Mode::create(String::new()); + self.mode = Mode::create(String::new(), map); } }, Message::CreateCharacter => { @@ -1242,7 +1242,7 @@ impl Controls { Message::Tool(value) => { if let Mode::Create { tool, loadout, .. } = &mut self.mode { *tool = value; - loadout.active_item = Some(LoadoutBuilder::default_item_config_from_str(*tool)); + loadout.active_item = Some(LoadoutBuilder::default_item_config_from_str(*tool, map)); } }, Message::RandomizeCharacter => { @@ -1411,7 +1411,7 @@ impl CharSelectionUi { } // TODO: do we need whole client here or just character list? - pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client) -> Vec { + pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client, map: &AbilityMap) -> Vec { let mut events = Vec::new(); let (mut messages, _) = self.ui.maintain( @@ -1426,7 +1426,7 @@ impl CharSelectionUi { messages.into_iter().for_each(|message| { self.controls - .update(message, &mut events, &client.character_list.characters) + .update(message, &mut events, &client.character_list.characters, map) }); events diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index f3b57d1acc..64adf12985 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -12,7 +12,7 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; -use common::{assets::Asset, comp, span}; +use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span}; use tracing::error; use ui::{Event as MainMenuEvent, MainMenuUi}; @@ -48,7 +48,7 @@ impl PlayState for MainMenuState { } } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { span!(_guard, "tick", "::tick"); let mut localized_strings = crate::i18n::Localization::load_expect( &crate::i18n::i18n_asset_key(&global_state.settings.language.selected_language), @@ -263,7 +263,7 @@ impl PlayState for MainMenuState { }, #[cfg(feature = "singleplayer")] MainMenuEvent::StartSingleplayer => { - let singleplayer = Singleplayer::new(None); // TODO: Make client and server use the same thread pool + let singleplayer = Singleplayer::new(None, map); // TODO: Make client and server use the same thread pool global_state.singleplayer = Some(singleplayer); }, diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index 1c75aced18..feedee7e52 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -4,11 +4,11 @@ use crate::{ window::{Event, EventLoop}, Direction, GlobalState, PlayState, PlayStateResult, }; -use common::{no_guard_span, span, util::GuardlessSpan}; +use common::{comp::item::tool::AbilityMap, no_guard_span, span, util::GuardlessSpan}; use std::{mem, time::Duration}; use tracing::debug; -pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { +pub fn run(mut global_state: GlobalState, event_loop: EventLoop, map: &AbilityMap) { // Set up the initial play state. let mut states: Vec> = vec![Box::new(MainMenuState::new(&mut global_state))]; states.last_mut().map(|current_state| { @@ -26,6 +26,8 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { let mut poll_span = None; let mut event_span = None; + let map = map.clone(); + event_loop.run(move |event, _, control_flow| { // Continuously run loop since we handle sleeping *control_flow = winit::event_loop::ControlFlow::Poll; @@ -53,7 +55,7 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { event_span.take(); poll_span.take(); if polled_twice { - handle_main_events_cleared(&mut states, control_flow, &mut global_state); + handle_main_events_cleared(&mut states, control_flow, &mut global_state, &map); } poll_span = Some(no_guard_span!("Poll Winit")); polled_twice = !polled_twice; @@ -82,6 +84,7 @@ fn handle_main_events_cleared( states: &mut Vec>, control_flow: &mut winit::event_loop::ControlFlow, global_state: &mut GlobalState, + map: &AbilityMap, ) { span!(guard, "Handle MainEventsCleared"); // Screenshot / Fullscreen toggle @@ -102,7 +105,7 @@ fn handle_main_events_cleared( let mut exit = true; while let Some(state_result) = states.last_mut().map(|last| { let events = global_state.window.fetch_events(); - last.tick(global_state, events) + last.tick(global_state, events, map) }) { // Implement state transfer logic. match state_result { diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 0a5f8e5503..a49f686d9c 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -15,7 +15,7 @@ use client::{self, Client}; use common::{ assets::Asset, comp, - comp::{ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel}, + comp::{item::tool::AbilityMap, ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel}, consts::{MAX_MOUNT_RANGE, MAX_PICKUP_RANGE}, event::EventBus, msg::PresenceKind, @@ -203,7 +203,7 @@ impl PlayState for SessionState { } } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { span!(_guard, "tick", "::tick"); // TODO: let mut client = self.client.borrow_mut(); // NOTE: Not strictly necessary, but useful for hotloading translation changes. diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index 0bc68f50d9..9b0704afa0 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -1,5 +1,5 @@ use client::Client; -use common::clock::Clock; +use common::{clock::Clock, comp::item::tool::AbilityMap}; use crossbeam::channel::{bounded, unbounded, Receiver, Sender, TryRecvError}; use server::{Error as ServerError, Event, Input, Server}; use std::{ @@ -31,7 +31,7 @@ pub struct Singleplayer { } impl Singleplayer { - pub fn new(client: Option<&Client>) -> Self { + pub fn new(client: Option<&Client>,map: &AbilityMap) -> Self { let (sender, receiver) = unbounded(); // Determine folder to save server data in From c42bdc36415cd340684f5266e9c2be0a1774b156 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 12 Nov 2020 00:27:16 -0500 Subject: [PATCH 08/10] Remove ability map from top level functions --- common/src/comp/inventory/item/tool.rs | 17 +++++++-------- common/src/state.rs | 7 ++++++- server/src/cmd.rs | 8 +++++--- server/src/events/interaction.rs | 6 +++++- server/src/events/inventory_manip.rs | 22 ++++++++++---------- server/src/lib.rs | 6 +++--- voxygen/src/lib.rs | 4 ++-- voxygen/src/main.rs | 2 +- voxygen/src/menu/char_selection/mod.rs | 11 +++++++--- voxygen/src/menu/char_selection/ui/mod.rs | 25 +++++++++++++++++------ voxygen/src/menu/main/mod.rs | 10 ++++++--- voxygen/src/run.rs | 11 ++++------ voxygen/src/session.rs | 4 ++-- voxygen/src/singleplayer.rs | 4 ++-- 14 files changed, 84 insertions(+), 53 deletions(-) diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index bc19b56ea7..f3518c4321 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -96,14 +96,15 @@ impl Tool { } pub fn get_abilities(&self, map: &AbilityMap) -> AbilitySet { - let base_abilities = match AbilityMap::load("common.abilities.weapon_ability_manifest") { - Ok(map) => map.0.get(&self.kind).map(|a| a.clone()).unwrap_or_default(), - Err(err) => { - error!(?err, "Error unwrapping"); - AbilitySet::default() - }, - }; - base_abilities + if let Some(set) = map.0.get(&self.kind).cloned() { + set + } else { + error!( + "ToolKind: {:?} has no AbilitySet in the ability map falling back to default", + &self.kind + ); + Default::default() + } } // TODO: Before merging ron file branch, ensure these are double checked against diff --git a/common/src/state.rs b/common/src/state.rs index 23789c14e7..071ee1366b 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -181,7 +181,9 @@ impl State { ecs.insert(BlockChange::default()); ecs.insert(TerrainChanges::default()); ecs.insert(EventBus::::default()); - ecs.insert(comp::item::tool::AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest")); + ecs.insert(comp::item::tool::AbilityMap::load_expect_cloned( + "common.abilities.weapon_ability_manifest", + )); // TODO: only register on the server ecs.insert(EventBus::::default()); ecs.insert(comp::group::GroupManager::default()); @@ -255,6 +257,9 @@ impl State { /// Get the current delta time. pub fn get_delta_time(&self) -> f32 { self.ecs.read_resource::().0 } + /// Get a reference to this state's ability map. + pub fn ability_map(&self) -> Fetch { self.ecs.read_resource() } + /// Get a reference to this state's terrain. pub fn terrain(&self) -> Fetch { self.ecs.read_resource() } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index bb72face28..92efc769ea 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -9,7 +9,7 @@ use crate::{ use chrono::{NaiveTime, Timelike}; use common::{ cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS}, - comp::{self, item::tool::AbilityMap, ChatType, Item, LightEmitter, WaypointArea}, + comp::{self, ChatType, Item, LightEmitter, WaypointArea}, effect::Effect, event::{EventBus, ServerEvent}, msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral}, @@ -655,8 +655,10 @@ fn handle_spawn( let body = body(); - let map = server.state().ecs().fetch::(); - let loadout = LoadoutBuilder::build_loadout(body, alignment, None, false, &map).build(); + let map = server.state().ability_map(); + let loadout = + LoadoutBuilder::build_loadout(body, alignment, None, false, &map) + .build(); drop(map); let mut entity_base = server diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index f7e6c1228a..bfa9294059 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -4,7 +4,11 @@ use crate::{ Server, }; use common::{ - comp::{self, item::{self, tool::AbilityMap}, Pos}, + comp::{ + self, + item::{self, tool::AbilityMap}, + Pos, + }, consts::MAX_MOUNT_RANGE, msg::ServerGeneral, sync::{Uid, WorldSyncExt}, diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 1b22247ba9..958a7208c0 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -1,7 +1,7 @@ use crate::{client::Client, Server, StateExt}; use common::{ comp::{ - self, item::{self, tool::AbilityMap}, + self, item, slot::{self, Slot}, Pos, }, @@ -203,8 +203,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv if let Some(lantern) = lantern_opt { swap_lantern(&mut state.ecs().write_storage(), entity, &lantern); } - let map = state.ecs().fetch::(); - slot::equip(slot, inventory, loadout, &map); + let ability_map = state.ability_map(); + slot::equip(slot, inventory, loadout, &ability_map); Some(comp::InventoryUpdateEvent::Used) } else { None @@ -339,8 +339,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv if slot == slot::EquipSlot::Lantern { snuff_lantern(&mut state.ecs().write_storage(), entity); } - let map = state.ecs().fetch::(); - slot::unequip(slot, inventory, loadout, &map); + let ability_map = state.ability_map(); + slot::unequip(slot, inventory, loadout, &ability_map); Some(comp::InventoryUpdateEvent::Used) } else { error!(?entity, "Entity doesn't have a loadout, can't unequip..."); @@ -366,14 +366,14 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv let mut loadouts = ecs.write_storage(); let inventory = inventories.get_mut(entity); let loadout = loadouts.get_mut(entity); - let map = state.ecs().fetch::(); + let ability_map = state.ability_map(); - slot::swap(a, b, inventory, loadout, &map); + slot::swap(a, b, inventory, loadout, &ability_map); // :/ drop(loadouts); drop(inventories); - drop(map); + drop(ability_map); state.write_component( entity, @@ -382,7 +382,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv }, comp::InventoryManip::Drop(slot) => { - let map = state.ecs().fetch::(); + let ability_map = state.ability_map(); let item = match slot { Slot::Inventory(slot) => state .ecs() @@ -393,9 +393,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .ecs() .write_storage() .get_mut(entity) - .and_then(|ldt| slot::loadout_remove(slot, ldt, &map)), + .and_then(|ldt| slot::loadout_remove(slot, ldt, &ability_map)), }; - drop(map); + drop(ability_map); // FIXME: We should really require the drop and write to be atomic! if let (Some(mut item), Some(pos)) = diff --git a/server/src/lib.rs b/server/src/lib.rs index abc5de91ee..822d77d319 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -46,7 +46,7 @@ use crate::{ }; use common::{ cmd::ChatCommand, - comp::{self, item::tool::AbilityMap, ChatType}, + comp::{self, ChatType}, event::{EventBus, ServerEvent}, msg::{ ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg, @@ -159,8 +159,8 @@ impl Server { state .ecs_mut() .insert(CharacterUpdater::new(&persistence_db_dir)?); - - let character_loader = CharacterLoader::new(&persistence_db_dir, &*state.ecs().fetch::()); + + let character_loader = CharacterLoader::new(&persistence_db_dir, &*state.ability_map()); state.ecs_mut().insert(character_loader); state.ecs_mut().insert(Vec::::new()); diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index 09fe7cd42d..12a585f647 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -39,7 +39,7 @@ use crate::{ settings::Settings, window::{Event, Window}, }; -use common::{assets::watch, clock::Clock, comp::item::tool::AbilityMap}; +use common::{assets::watch, clock::Clock}; /// A type used to store state that is shared between all play states. pub struct GlobalState { @@ -110,7 +110,7 @@ pub trait PlayState { fn enter(&mut self, global_state: &mut GlobalState, direction: Direction); /// Tick the play state - fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult; + fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult; /// Get a descriptive name for this state type. fn name(&self) -> &'static str; diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 7afd1bdc81..f87b32d35b 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -192,5 +192,5 @@ fn main() { localization_watcher, }; - run::run(global_state, event_loop, map); + run::run(global_state, event_loop); } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 073d93daa0..03e44d2dc0 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -10,7 +10,12 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client::{self, Client}; -use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span, state::DeltaTime}; +use common::{ + assets::Asset, + comp::{self}, + span, + state::DeltaTime, +}; use specs::WorldExt; use std::{cell::RefCell, rc::Rc}; use tracing::error; @@ -62,7 +67,7 @@ impl PlayState for CharSelectionState { self.client.borrow_mut().load_character_list(); } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { span!(_guard, "tick", "::tick"); let (client_presence, client_registered) = { let client = self.client.borrow(); @@ -88,7 +93,7 @@ impl PlayState for CharSelectionState { // Maintain the UI. let events = self .char_selection_ui - .maintain(global_state, &mut self.client.borrow_mut(), map); + .maintain(global_state, &mut self.client.borrow_mut()); for event in events { match event { diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 682dde3055..2ed4463002 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -184,7 +184,9 @@ impl Mode { let loadout = LoadoutBuilder::new() .defaults() - .active_item(Some(LoadoutBuilder::default_item_config_from_str(tool, map))) + .active_item(Some(LoadoutBuilder::default_item_config_from_str( + tool, map, + ))) .build(); let loadout = Box::new(loadout); @@ -1172,7 +1174,13 @@ impl Controls { .into() } - fn update(&mut self, message: Message, events: &mut Vec, characters: &[CharacterItem], map: &AbilityMap) { + fn update( + &mut self, + message: Message, + events: &mut Vec, + characters: &[CharacterItem], + map: &AbilityMap, + ) { match message { Message::Back => { if matches!(&self.mode, Mode::Create { .. }) { @@ -1242,7 +1250,8 @@ impl Controls { Message::Tool(value) => { if let Mode::Create { tool, loadout, .. } = &mut self.mode { *tool = value; - loadout.active_item = Some(LoadoutBuilder::default_item_config_from_str(*tool, map)); + loadout.active_item = + Some(LoadoutBuilder::default_item_config_from_str(*tool, map)); } }, Message::RandomizeCharacter => { @@ -1411,7 +1420,7 @@ impl CharSelectionUi { } // TODO: do we need whole client here or just character list? - pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client, map: &AbilityMap) -> Vec { + pub fn maintain(&mut self, global_state: &mut GlobalState, client: &mut Client) -> Vec { let mut events = Vec::new(); let (mut messages, _) = self.ui.maintain( @@ -1425,8 +1434,12 @@ impl CharSelectionUi { } messages.into_iter().for_each(|message| { - self.controls - .update(message, &mut events, &client.character_list.characters, map) + self.controls.update( + message, + &mut events, + &client.character_list.characters, + &*client.state().ability_map(), + ) }); events diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 64adf12985..e4696ea4d9 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -12,7 +12,11 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; -use common::{assets::Asset, comp::{self, item::tool::AbilityMap}, span}; +use common::{ + assets::Asset, + comp::{self}, + span, +}; use tracing::error; use ui::{Event as MainMenuEvent, MainMenuUi}; @@ -48,7 +52,7 @@ impl PlayState for MainMenuState { } } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { span!(_guard, "tick", "::tick"); let mut localized_strings = crate::i18n::Localization::load_expect( &crate::i18n::i18n_asset_key(&global_state.settings.language.selected_language), @@ -263,7 +267,7 @@ impl PlayState for MainMenuState { }, #[cfg(feature = "singleplayer")] MainMenuEvent::StartSingleplayer => { - let singleplayer = Singleplayer::new(None, map); // TODO: Make client and server use the same thread pool + let singleplayer = Singleplayer::new(None); // TODO: Make client and server use the same thread pool global_state.singleplayer = Some(singleplayer); }, diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index feedee7e52..1c75aced18 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -4,11 +4,11 @@ use crate::{ window::{Event, EventLoop}, Direction, GlobalState, PlayState, PlayStateResult, }; -use common::{comp::item::tool::AbilityMap, no_guard_span, span, util::GuardlessSpan}; +use common::{no_guard_span, span, util::GuardlessSpan}; use std::{mem, time::Duration}; use tracing::debug; -pub fn run(mut global_state: GlobalState, event_loop: EventLoop, map: &AbilityMap) { +pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { // Set up the initial play state. let mut states: Vec> = vec![Box::new(MainMenuState::new(&mut global_state))]; states.last_mut().map(|current_state| { @@ -26,8 +26,6 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop, map: &AbilityMa let mut poll_span = None; let mut event_span = None; - let map = map.clone(); - event_loop.run(move |event, _, control_flow| { // Continuously run loop since we handle sleeping *control_flow = winit::event_loop::ControlFlow::Poll; @@ -55,7 +53,7 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop, map: &AbilityMa event_span.take(); poll_span.take(); if polled_twice { - handle_main_events_cleared(&mut states, control_flow, &mut global_state, &map); + handle_main_events_cleared(&mut states, control_flow, &mut global_state); } poll_span = Some(no_guard_span!("Poll Winit")); polled_twice = !polled_twice; @@ -84,7 +82,6 @@ fn handle_main_events_cleared( states: &mut Vec>, control_flow: &mut winit::event_loop::ControlFlow, global_state: &mut GlobalState, - map: &AbilityMap, ) { span!(guard, "Handle MainEventsCleared"); // Screenshot / Fullscreen toggle @@ -105,7 +102,7 @@ fn handle_main_events_cleared( let mut exit = true; while let Some(state_result) = states.last_mut().map(|last| { let events = global_state.window.fetch_events(); - last.tick(global_state, events, map) + last.tick(global_state, events) }) { // Implement state transfer logic. match state_result { diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index a49f686d9c..0a5f8e5503 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -15,7 +15,7 @@ use client::{self, Client}; use common::{ assets::Asset, comp, - comp::{item::tool::AbilityMap, ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel}, + comp::{ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel}, consts::{MAX_MOUNT_RANGE, MAX_PICKUP_RANGE}, event::EventBus, msg::PresenceKind, @@ -203,7 +203,7 @@ impl PlayState for SessionState { } } - fn tick(&mut self, global_state: &mut GlobalState, events: Vec, map: &AbilityMap) -> PlayStateResult { + fn tick(&mut self, global_state: &mut GlobalState, events: Vec) -> PlayStateResult { span!(_guard, "tick", "::tick"); // TODO: let mut client = self.client.borrow_mut(); // NOTE: Not strictly necessary, but useful for hotloading translation changes. diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index 9b0704afa0..0bc68f50d9 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -1,5 +1,5 @@ use client::Client; -use common::{clock::Clock, comp::item::tool::AbilityMap}; +use common::clock::Clock; use crossbeam::channel::{bounded, unbounded, Receiver, Sender, TryRecvError}; use server::{Error as ServerError, Event, Input, Server}; use std::{ @@ -31,7 +31,7 @@ pub struct Singleplayer { } impl Singleplayer { - pub fn new(client: Option<&Client>,map: &AbilityMap) -> Self { + pub fn new(client: Option<&Client>) -> Self { let (sender, receiver) = unbounded(); // Determine folder to save server data in From 075215793551a07ce249c1bd5826a2777044c59c Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 12 Nov 2020 21:24:19 -0600 Subject: [PATCH 09/10] Speed and power on weapons are now able to modify abilities after they are loaded from ron files. --- common/src/comp/ability.rs | 170 ++++++- common/src/comp/inventory/item/tool.rs | 476 +----------------- common/src/comp/inventory/slot.rs | 34 +- common/src/comp/projectile.rs | 22 + common/src/loadout_builder.rs | 5 +- common/src/states/basic_ranged.rs | 2 - common/src/states/combo_melee.rs | 12 +- server/src/character_creator.rs | 3 +- server/src/lib.rs | 2 +- .../src/persistence/character/conversions.rs | 5 +- server/src/persistence/character_loader.rs | 12 +- server/src/sys/terrain.rs | 11 +- 12 files changed, 270 insertions(+), 484 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 77b6fb6175..9154a23ccb 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -313,6 +313,172 @@ impl CharacterAbility { roll_strength: 2.5, } } + + pub fn adjust_stats(mut self, power: f32, speed: f32) -> Self { + use CharacterAbility::*; + match self { + BasicMelee { + ref mut buildup_duration, + ref mut swing_duration, + ref mut recover_duration, + ref mut base_damage, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *base_damage = (*base_damage as f32 * power) as u32; + }, + BasicRanged { + ref mut buildup_duration, + ref mut recover_duration, + ref mut projectile, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *projectile = projectile.modify_projectile(power); + }, + RepeaterRanged { + ref mut movement_duration, + ref mut buildup_duration, + ref mut shoot_duration, + ref mut recover_duration, + ref mut projectile, + .. + } => { + *movement_duration = (*movement_duration as f32 / speed) as u64; + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *shoot_duration = (*shoot_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *projectile = projectile.modify_projectile(power); + }, + Boost { + ref mut movement_duration, + .. + } => { + *movement_duration = (*movement_duration as f32 / speed) as u64; + }, + DashMelee { + ref mut base_damage, + ref mut max_damage, + ref mut buildup_duration, + ref mut swing_duration, + ref mut recover_duration, + .. + } => { + *base_damage = (*base_damage as f32 * power) as u32; + *max_damage = (*max_damage as f32 * power) as u32; + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + }, + BasicBlock => {}, + Roll { + ref mut buildup_duration, + ref mut movement_duration, + ref mut recover_duration, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *movement_duration = (*movement_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + }, + ComboMelee { + ref mut stage_data, .. + } => { + *stage_data = stage_data + .iter_mut() + .map(|s| s.adjust_stats(power, speed)) + .collect(); + }, + LeapMelee { + ref mut buildup_duration, + ref mut movement_duration, + ref mut swing_duration, + ref mut recover_duration, + ref mut base_damage, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *movement_duration = (*movement_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *base_damage = (*base_damage as f32 * power) as u32; + }, + SpinMelee { + ref mut buildup_duration, + ref mut swing_duration, + ref mut recover_duration, + ref mut base_damage, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *base_damage = (*base_damage as f32 * power) as u32; + }, + ChargedMelee { + ref mut initial_damage, + ref mut max_damage, + speed: ref mut ability_speed, + ref mut charge_duration, + ref mut swing_duration, + ref mut recover_duration, + .. + } => { + *initial_damage = (*initial_damage as f32 * power) as u32; + *max_damage = (*max_damage as f32 * power) as u32; + *ability_speed *= speed; + *charge_duration = (*charge_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + }, + ChargedRanged { + ref mut initial_damage, + ref mut max_damage, + speed: ref mut ability_speed, + ref mut buildup_duration, + ref mut charge_duration, + ref mut recover_duration, + .. + } => { + *initial_damage = (*initial_damage as f32 * power) as u32; + *max_damage = (*max_damage as f32 * power) as u32; + *ability_speed *= speed; + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *charge_duration = (*charge_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + }, + Shockwave { + ref mut buildup_duration, + ref mut swing_duration, + ref mut recover_duration, + ref mut damage, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *swing_duration = (*swing_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *damage = (*damage as f32 * power) as u32; + }, + BasicBeam { + ref mut buildup_duration, + ref mut recover_duration, + ref mut base_hps, + ref mut base_dps, + ref mut tick_rate, + .. + } => { + *buildup_duration = (*buildup_duration as f32 / speed) as u64; + *recover_duration = (*recover_duration as f32 / speed) as u64; + *base_hps = (*base_hps as f32 * power) as u32; + *base_dps = (*base_dps as f32 * power) as u32; + *tick_rate *= speed; + }, + } + self + } } #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] @@ -328,13 +494,13 @@ pub struct ItemConfig { impl From<(Item, &AbilityMap)> for ItemConfig { fn from((item, map): (Item, &AbilityMap)) -> Self { if let ItemKind::Tool(tool) = &item.kind() { - let abilities = tool.get_abilities(map).clone(); + let abilities = tool.get_abilities(map); return ItemConfig { item, ability1: Some(abilities.primary), ability2: Some(abilities.secondary), - ability3: abilities.skills.get(0).map(|x| x.clone()), + ability3: abilities.skills.get(0).cloned(), block_ability: None, dodge_ability: Some(CharacterAbility::default_roll()), }; diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index f3518c4321..cda5a6637d 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -3,12 +3,7 @@ use crate::{ assets::{self, Asset}, - comp::{ - body::object, projectile::ProjectileConstructor, Body, CharacterAbility, Gravity, - LightEmitter, - }, - states::combo_melee, - Knockback, + comp::CharacterAbility, }; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fs::File, io::BufReader, time::Duration}; @@ -90,14 +85,9 @@ impl Tool { Duration::from_millis(self.stats.equip_time_millis as u64) } - /// Converts milliseconds to a `Duration` adjusted by `base_speed()` - pub fn adjusted_duration(&self, millis: u64) -> Duration { - Duration::from_millis(millis).div_f32(self.base_speed()) - } - pub fn get_abilities(&self, map: &AbilityMap) -> AbilitySet { if let Some(set) = map.0.get(&self.kind).cloned() { - set + set.modify_from_tool(&self) } else { error!( "ToolKind: {:?} has no AbilitySet in the ability map falling back to default", @@ -106,450 +96,6 @@ impl Tool { Default::default() } } - - // TODO: Before merging ron file branch, ensure these are double checked against - // ron files. - /*pub fn get_abilities(&self) -> Vec { - use CharacterAbility::*; - use ToolKind::*; - - use UniqueKind::*; - match &self.kind { - Sword => vec![ - ComboMelee { - stage_data: vec![ - combo_melee::Stage { - stage: 1, - base_damage: (100.0 * self.base_power()) as u32, - max_damage: (120.0 * self.base_power()) as u32, - damage_increase: (10.0 * self.base_power()) as u32, - knockback: 10.0, - range: 4.0, - angle: 30.0, - base_buildup_duration: self.adjusted_duration(350), - base_swing_duration: self.adjusted_duration(100), - base_recover_duration: self.adjusted_duration(400), - forward_movement: 0.5, - }, - combo_melee::Stage { - stage: 2, - base_damage: (80.0 * self.base_power()) as u32, - max_damage: (110.0 * self.base_power()) as u32, - damage_increase: (15.0 * self.base_power()) as u32, - knockback: 12.0, - range: 3.5, - angle: 180.0, - base_buildup_duration: self.adjusted_duration(400), - base_swing_duration: self.adjusted_duration(600), - base_recover_duration: self.adjusted_duration(400), - forward_movement: 0.0, - }, - combo_melee::Stage { - stage: 3, - base_damage: (130.0 * self.base_power()) as u32, - max_damage: (170.0 * self.base_power()) as u32, - damage_increase: (20.0 * self.base_power()) as u32, - knockback: 14.0, - range: 6.0, - angle: 10.0, - base_buildup_duration: self.adjusted_duration(500), - base_swing_duration: self.adjusted_duration(200), - base_recover_duration: self.adjusted_duration(300), - forward_movement: 1.2, - }, - ], - initial_energy_gain: 0, - max_energy_gain: 100, - energy_increase: 20, - speed_increase: 0.05, - max_speed_increase: 1.8, - is_interruptible: true, - }, - DashMelee { - energy_cost: 200, - base_damage: (120.0 * self.base_power()) as u32, - max_damage: (240.0 * self.base_power()) as u32, - base_knockback: 8.0, - max_knockback: 15.0, - range: 5.0, - angle: 45.0, - energy_drain: 500, - forward_speed: 4.0, - buildup_duration: self.adjusted_duration(250), - charge_duration: Duration::from_millis(600), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(500), - infinite_charge: true, - is_interruptible: true, - }, - SpinMelee { - buildup_duration: self.adjusted_duration(750), - swing_duration: self.adjusted_duration(500), - recover_duration: self.adjusted_duration(500), - base_damage: (140.0 * self.base_power()) as u32, - knockback: 10.0, - range: 3.5, - energy_cost: 200, - is_infinite: false, - is_helicopter: false, - is_interruptible: true, - forward_speed: 1.0, - num_spins: 3, - }, - ], - Axe => vec![ - ComboMelee { - stage_data: vec![ - combo_melee::Stage { - stage: 1, - base_damage: (90.0 * self.base_power()) as u32, - max_damage: (110.0 * self.base_power()) as u32, - damage_increase: (10.0 * self.base_power()) as u32, - knockback: 8.0, - range: 3.5, - angle: 50.0, - base_buildup_duration: self.adjusted_duration(350), - base_swing_duration: self.adjusted_duration(75), - base_recover_duration: self.adjusted_duration(400), - forward_movement: 0.5, - }, - combo_melee::Stage { - stage: 2, - base_damage: (130.0 * self.base_power()) as u32, - max_damage: (160.0 * self.base_power()) as u32, - damage_increase: (15.0 * self.base_power()) as u32, - knockback: 12.0, - range: 3.5, - angle: 30.0, - base_buildup_duration: self.adjusted_duration(500), - base_swing_duration: self.adjusted_duration(100), - base_recover_duration: self.adjusted_duration(500), - forward_movement: 0.25, - }, - ], - initial_energy_gain: 0, - max_energy_gain: 100, - energy_increase: 20, - speed_increase: 0.05, - max_speed_increase: 1.6, - is_interruptible: false, - }, - SpinMelee { - buildup_duration: self.adjusted_duration(100), - swing_duration: self.adjusted_duration(250), - recover_duration: self.adjusted_duration(100), - base_damage: (60.0 * self.base_power()) as u32, - knockback: 0.0, - range: 3.5, - energy_cost: 100, - is_infinite: true, - is_helicopter: true, - is_interruptible: false, - forward_speed: 0.0, - num_spins: 1, - }, - LeapMelee { - energy_cost: 450, - buildup_duration: self.adjusted_duration(200), - movement_duration: Duration::from_millis(200), - swing_duration: self.adjusted_duration(200), - recover_duration: self.adjusted_duration(200), - base_damage: (240.0 * self.base_power()) as u32, - knockback: 12.0, - range: 4.5, - max_angle: 30.0, - forward_leap_strength: 28.0, - vertical_leap_strength: 8.0, - }, - ], - Hammer => vec![ - ComboMelee { - stage_data: vec![combo_melee::Stage { - stage: 1, - base_damage: (120.0 * self.base_power()) as u32, - max_damage: (150.0 * self.base_power()) as u32, - damage_increase: (10.0 * self.base_power()) as u32, - knockback: 0.0, - range: 3.5, - angle: 20.0, - base_buildup_duration: self.adjusted_duration(600), - base_swing_duration: self.adjusted_duration(60), - base_recover_duration: self.adjusted_duration(300), - forward_movement: 0.0, - }], - initial_energy_gain: 0, - max_energy_gain: 100, - energy_increase: 20, - speed_increase: 0.05, - max_speed_increase: 1.4, - is_interruptible: false, - }, - ChargedMelee { - energy_cost: 1, - energy_drain: 300, - initial_damage: (10.0 * self.base_power()) as u32, - max_damage: (170.0 * self.base_power()) as u32, - initial_knockback: 10.0, - max_knockback: 60.0, - range: 3.5, - max_angle: 30.0, - speed: self.base_speed(), - charge_duration: Duration::from_millis(1200), - swing_duration: self.adjusted_duration(200), - recover_duration: self.adjusted_duration(300), - }, - LeapMelee { - energy_cost: 700, - buildup_duration: self.adjusted_duration(100), - movement_duration: Duration::from_millis(800), - swing_duration: self.adjusted_duration(150), - recover_duration: self.adjusted_duration(200), - base_damage: (240.0 * self.base_power()) as u32, - knockback: 25.0, - range: 4.5, - max_angle: 360.0, - forward_leap_strength: 28.0, - vertical_leap_strength: 8.0, - }, - ], - Farming => vec![BasicMelee { - energy_cost: 1, - buildup_duration: self.adjusted_duration(600), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(150), - base_damage: (50.0 * self.base_power()) as u32, - knockback: 0.0, - range: 3.5, - max_angle: 20.0, - }], - Bow => vec![ - BasicRanged { - energy_cost: 0, - buildup_duration: self.adjusted_duration(200), - recover_duration: self.adjusted_duration(300), - projectile: ProjectileConstructor::Arrow { - damage: 40.0 * self.base_power(), - knockback: 10.0, - energy_regen: 50, - }, - projectile_body: Body::Object(object::Body::Arrow), - projectile_light: None, - projectile_gravity: Some(Gravity(0.2)), - projectile_speed: 100.0, - can_continue: true, - }, - ChargedRanged { - energy_cost: 0, - energy_drain: 300, - initial_damage: (40.0 * self.base_power()) as u32, - max_damage: (200.0 * self.base_power()) as u32, - initial_knockback: 10.0, - max_knockback: 20.0, - speed: self.base_speed(), - buildup_duration: self.adjusted_duration(100), - charge_duration: Duration::from_millis(1500), - recover_duration: self.adjusted_duration(500), - projectile_body: Body::Object(object::Body::MultiArrow), - projectile_light: None, - projectile_gravity: Some(Gravity(0.2)), - initial_projectile_speed: 100.0, - max_projectile_speed: 500.0, - }, - RepeaterRanged { - energy_cost: 450, - movement_duration: Duration::from_millis(300), - buildup_duration: self.adjusted_duration(200), - shoot_duration: self.adjusted_duration(200), - recover_duration: self.adjusted_duration(800), - leap: Some(5.0), - projectile: ProjectileConstructor::Arrow { - damage: 40.0 * self.base_power(), - knockback: 10.0, - energy_regen: 0, - }, - projectile_body: Body::Object(object::Body::Arrow), - projectile_light: None, - projectile_gravity: Some(Gravity(0.2)), - projectile_speed: 100.0, - reps_remaining: 5, - }, - ], - Dagger => vec![BasicMelee { - energy_cost: 0, - buildup_duration: self.adjusted_duration(100), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(300), - base_damage: (50.0 * self.base_power()) as u32, - knockback: 0.0, - range: 3.5, - max_angle: 20.0, - }], - Sceptre => vec![ - BasicBeam { - buildup_duration: self.adjusted_duration(250), - recover_duration: self.adjusted_duration(250), - beam_duration: Duration::from_secs(1), - base_hps: (60.0 * self.base_power()) as u32, - base_dps: (60.0 * self.base_power()) as u32, - tick_rate: 2.0 * self.base_speed(), - range: 25.0, - max_angle: 1.0, - lifesteal_eff: 0.20, - energy_regen: 50, - energy_cost: 100, - energy_drain: 0, - }, - BasicRanged { - energy_cost: 800, - buildup_duration: self.adjusted_duration(800), - recover_duration: self.adjusted_duration(50), - projectile: ProjectileConstructor::Heal { - heal: 140.0 * self.base_power(), - damage: 50.0 * self.base_power(), - radius: 3.0 + 2.5 * self.base_power(), - }, - projectile_body: Body::Object(object::Body::BoltNature), - projectile_light: Some(LightEmitter { - col: (0.0, 1.0, 0.0).into(), - ..Default::default() - }), - projectile_gravity: Some(Gravity(0.5)), - projectile_speed: 40.0, - can_continue: false, - }, - ], - Staff => vec![ - BasicRanged { - energy_cost: 0, - buildup_duration: self.adjusted_duration(500), - recover_duration: self.adjusted_duration(350), - projectile: ProjectileConstructor::Fireball { - damage: 100.0 * self.base_power(), - radius: 5.0, - energy_regen: 50, - }, - projectile_body: Body::Object(object::Body::BoltFire), - projectile_light: Some(LightEmitter { - col: (1.0, 0.75, 0.11).into(), - ..Default::default() - }), - projectile_gravity: Some(Gravity(0.3)), - projectile_speed: 60.0, - can_continue: true, - }, - BasicBeam { - buildup_duration: self.adjusted_duration(250), - recover_duration: self.adjusted_duration(250), - beam_duration: self.adjusted_duration(500), - base_hps: 0, - base_dps: (150.0 * self.base_power()) as u32, - tick_rate: 3.0 * self.base_speed(), - range: 15.0, - max_angle: 22.5, - lifesteal_eff: 0.0, - energy_regen: 0, - energy_cost: 0, - energy_drain: 350, - }, - Shockwave { - energy_cost: 600, - buildup_duration: self.adjusted_duration(700), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(300), - damage: (200.0 * self.base_power()) as u32, - knockback: Knockback::Away(25.0), - shockwave_angle: 360.0, - shockwave_vertical_angle: 90.0, - shockwave_speed: 20.0, - shockwave_duration: Duration::from_millis(500), - requires_ground: false, - move_efficiency: 0.1, - }, - ], - Shield => vec![ - BasicMelee { - energy_cost: 0, - buildup_duration: self.adjusted_duration(100), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(300), - base_damage: (40.0 * self.base_power()) as u32, - knockback: 0.0, - range: 3.0, - max_angle: 120.0, - }, - ], - Unique(StoneGolemFist) => vec![ - BasicMelee { - energy_cost: 0, - buildup_duration: self.adjusted_duration(400), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(250), - knockback: 25.0, - base_damage: 200, - range: 5.0, - max_angle: 120.0, - }, - Shockwave { - energy_cost: 0, - buildup_duration: self.adjusted_duration(500), - swing_duration: self.adjusted_duration(200), - recover_duration: self.adjusted_duration(800), - damage: 500, - knockback: Knockback::TowardsUp(40.0), - shockwave_angle: 90.0, - shockwave_vertical_angle: 15.0, - shockwave_speed: 20.0, - shockwave_duration: Duration::from_millis(2000), - requires_ground: true, - move_efficiency: 0.05, - }, - ], - Unique(BeastClaws) => vec![BasicMelee { - energy_cost: 0, - buildup_duration: self.adjusted_duration(250), - swing_duration: self.adjusted_duration(250), - recover_duration: self.adjusted_duration(250), - knockback: 25.0, - base_damage: 200, - range: 5.0, - max_angle: 120.0, - }], - Debug => vec![ - CharacterAbility::Boost { - movement_duration: Duration::from_millis(50), - only_up: false, - }, - CharacterAbility::Boost { - movement_duration: Duration::from_millis(50), - only_up: true, - }, - BasicRanged { - energy_cost: 0, - buildup_duration: Duration::from_millis(0), - recover_duration: self.adjusted_duration(10), - projectile: ProjectileConstructor::Possess, - projectile_body: Body::Object(object::Body::ArrowSnake), - projectile_light: Some(LightEmitter { - col: (0.0, 1.0, 0.33).into(), - ..Default::default() - }), - projectile_gravity: None, - projectile_speed: 100.0, - can_continue: false, - }, - ], - Empty => vec![BasicMelee { - energy_cost: 0, - buildup_duration: Duration::from_millis(0), - swing_duration: self.adjusted_duration(100), - recover_duration: self.adjusted_duration(900), - base_damage: 20, - knockback: 0.0, - range: 3.5, - max_angle: 15.0, - }], - } - }*/ } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -559,6 +105,24 @@ pub struct AbilitySet { pub skills: Vec, } +impl AbilitySet { + pub fn modify_from_tool(self, tool: &Tool) -> Self { + Self { + primary: self + .primary + .adjust_stats(tool.base_power(), tool.base_speed()), + secondary: self + .secondary + .adjust_stats(tool.base_power(), tool.base_speed()), + skills: self + .skills + .into_iter() + .map(|a| a.adjust_stats(tool.base_power(), tool.base_speed())) + .collect(), + } + } +} + impl AbilitySet { pub fn map U>(self, mut f: F) -> AbilitySet { AbilitySet { diff --git a/common/src/comp/inventory/slot.rs b/common/src/comp/inventory/slot.rs index 2298623184..8bc0a3296a 100644 --- a/common/src/comp/inventory/slot.rs +++ b/common/src/comp/inventory/slot.rs @@ -1,6 +1,9 @@ use crate::{ comp, - comp::{item::{self, armor, tool::AbilityMap}, ItemConfig}, + comp::{ + item::{self, armor, tool::AbilityMap}, + ItemConfig, + }, }; use comp::{Inventory, Loadout}; use serde::{Deserialize, Serialize}; @@ -107,12 +110,16 @@ fn loadout_replace( EquipSlot::Armor(ArmorSlot::Tabard) => replace(&mut loadout.tabard, item), EquipSlot::Lantern => replace(&mut loadout.lantern, item), EquipSlot::Glider => replace(&mut loadout.glider, item), - EquipSlot::Mainhand => { - replace(&mut loadout.active_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item) - }, - EquipSlot::Offhand => { - replace(&mut loadout.second_item, item.map(|item| ItemConfig::from((item, map)))).map(|i| i.item) - }, + EquipSlot::Mainhand => replace( + &mut loadout.active_item, + item.map(|item| ItemConfig::from((item, map))), + ) + .map(|i| i.item), + EquipSlot::Offhand => replace( + &mut loadout.second_item, + item.map(|item| ItemConfig::from((item, map))), + ) + .map(|i| i.item), } } @@ -153,7 +160,11 @@ fn loadout_insert( /// loadout_remove(slot, &mut loadout); /// assert_eq!(None, loadout.active_item); /// ``` -pub fn loadout_remove(equip_slot: EquipSlot, loadout: &mut Loadout, map: &AbilityMap) -> Option { +pub fn loadout_remove( + equip_slot: EquipSlot, + loadout: &mut Loadout, + map: &AbilityMap, +) -> Option { loadout_replace(equip_slot, None, loadout, map) } @@ -326,7 +337,12 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: /// unequip(slot, &mut inv, &mut loadout); /// assert_eq!(None, loadout.active_item); /// ``` -pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) { +pub fn unequip( + slot: EquipSlot, + inventory: &mut Inventory, + loadout: &mut Loadout, + map: &AbilityMap, +) { loadout_remove(slot, loadout, map) // Remove item from loadout .and_then(|i| inventory.push(i)) // Insert into inventory .and_then(|i| loadout_insert(slot, i, loadout, map)) // If that fails put back in loadout diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index d0cf49facd..3710c76ddc 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -199,4 +199,26 @@ impl ProjectileConstructor { }, } } + + pub fn modify_projectile(mut self, power: f32) -> Self { + use ProjectileConstructor::*; + match self { + Arrow { ref mut damage, .. } => { + *damage *= power; + }, + Fireball { ref mut damage, .. } => { + *damage *= power; + }, + Heal { + ref mut damage, + ref mut heal, + .. + } => { + *damage *= power; + *heal *= power; + }, + Possess => {}, + } + self + } } diff --git a/common/src/loadout_builder.rs b/common/src/loadout_builder.rs index b224dbb00e..c364acbaf4 100644 --- a/common/src/loadout_builder.rs +++ b/common/src/loadout_builder.rs @@ -4,7 +4,6 @@ use crate::comp::{ Alignment, Body, CharacterAbility, ItemConfig, Loadout, }; use rand::Rng; -use std::time::Duration; /// Builder for character Loadouts, containing weapon and armour items belonging /// to a character, along with some helper methods for loading Items and @@ -362,7 +361,9 @@ impl LoadoutBuilder { /// abilities or their timings is desired, you should create and provide /// the item config directly to the [active_item](#method.active_item) /// method - pub fn default_item_config_from_item(item: Item, map: &AbilityMap) -> ItemConfig { ItemConfig::from((item, map)) } + pub fn default_item_config_from_item(item: Item, map: &AbilityMap) -> ItemConfig { + ItemConfig::from((item, map)) + } /// Get an item's (weapon's) default /// [ItemConfig](../comp/struct.ItemConfig.html) diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index dedd9ca207..702dfa1ba7 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -95,7 +95,6 @@ impl CharacterBehavior for Data { if ability_key_is_pressed(data, self.static_data.ability_key) { // Recovers update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) @@ -106,7 +105,6 @@ impl CharacterBehavior for Data { } else { // Recovers update.character = CharacterState::BasicRanged(Data { - static_data: self.static_data.clone(), timer: self .timer .checked_add(Duration::from_secs_f32(data.dt.0)) diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index b4cfde8b80..bc9e2052b5 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -7,7 +7,7 @@ use crate::{ use serde::{Deserialize, Serialize}; use std::time::Duration; -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct Stage { /// Specifies which stage the combo attack is in pub stage: u32, @@ -50,6 +50,16 @@ impl Stage { forward_movement: self.forward_movement, } } + + pub fn adjust_stats(mut self, power: f32, speed: f32) -> Self { + self.base_damage = (self.base_damage as f32 * power) as u32; + self.max_damage = (self.max_damage as f32 * power) as u32; + self.damage_increase = (self.damage_increase as f32 * power) as u32; + self.base_buildup_duration = (self.base_buildup_duration as f32 / speed) as u64; + self.base_swing_duration = (self.base_swing_duration as f32 / speed) as u64; + self.base_recover_duration = (self.base_recover_duration as f32 / speed) as u64; + self + } } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index 815bc2e852..6fdeadc53a 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -19,7 +19,8 @@ pub fn create_character( let loadout = LoadoutBuilder::new() .defaults() .active_item(Some(LoadoutBuilder::default_item_config_from_str( - character_tool.as_deref().unwrap(), map + character_tool.as_deref().unwrap(), + map, ))) .build(); diff --git a/server/src/lib.rs b/server/src/lib.rs index 822d77d319..1e5d6c4b39 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -161,7 +161,7 @@ impl Server { .insert(CharacterUpdater::new(&persistence_db_dir)?); let character_loader = CharacterLoader::new(&persistence_db_dir, &*state.ability_map()); - state.ecs_mut().insert(character_loader); + state.ecs_mut().insert(character_loader?); state.ecs_mut().insert(Vec::::new()); // System timers for performance monitoring diff --git a/server/src/persistence/character/conversions.rs b/server/src/persistence/character/conversions.rs index 0c4c0935ea..59574ff059 100644 --- a/server/src/persistence/character/conversions.rs +++ b/server/src/persistence/character/conversions.rs @@ -240,7 +240,10 @@ pub fn convert_inventory_from_database_items(database_items: &[Item]) -> Result< Ok(inventory) } -pub fn convert_loadout_from_database_items(database_items: &[Item], map: &AbilityMap) -> Result { +pub fn convert_loadout_from_database_items( + database_items: &[Item], + map: &AbilityMap, +) -> Result { let mut loadout = loadout_builder::LoadoutBuilder::new(); for db_item in database_items.iter() { let item = common::comp::Item::new_from_asset(db_item.item_definition_id.as_str())?; diff --git a/server/src/persistence/character_loader.rs b/server/src/persistence/character_loader.rs index 2dd27f0d5f..8d72e8f80b 100644 --- a/server/src/persistence/character_loader.rs +++ b/server/src/persistence/character_loader.rs @@ -99,14 +99,14 @@ impl CharacterLoader { CharacterLoaderRequestKind::DeleteCharacter { player_uuid, character_id, - } => { - CharacterLoaderResponseType::CharacterList(conn.transaction(|txn| { - delete_character(&player_uuid, character_id, txn, &map) - })) - }, + } => CharacterLoaderResponseType::CharacterList(conn.transaction(|txn| { + delete_character(&player_uuid, character_id, txn, &map) + })), CharacterLoaderRequestKind::LoadCharacterList { player_uuid } => { CharacterLoaderResponseType::CharacterList( - conn.transaction(|txn| load_character_list(&player_uuid, txn, &map)), + conn.transaction(|txn| { + load_character_list(&player_uuid, txn, &map) + }), ) }, CharacterLoaderRequestKind::LoadCharacterData { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index d0f4884dfe..634bca2b81 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -144,9 +144,14 @@ impl<'a> System<'a> for Sys { scale = 2.0 + rand::random::(); } - let loadout = - LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant, &map) - .build(); + let loadout = LoadoutBuilder::build_loadout( + body, + alignment, + main_tool, + entity.is_giant, + &map, + ) + .build(); let health = comp::Health::new(stats.body_type, stats.level.level()); From 479bda3895d03fa2aa93457dc248bddd40a3e4d4 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 12 Nov 2020 21:50:40 -0600 Subject: [PATCH 10/10] Fixed tests. Addressed comments. --- common/src/comp/ability.rs | 14 +++------ common/src/comp/inventory/item/tool.rs | 23 ++++---------- common/src/comp/inventory/slot.rs | 42 +++++++++++++++++++++----- common/src/comp/projectile.rs | 16 +++++----- common/src/loadout_builder.rs | 10 ++++-- common/src/states/combo_melee.rs | 2 +- server/src/events/interaction.rs | 4 +-- voxygen/src/menu/char_selection/mod.rs | 7 +---- voxygen/src/menu/main/mod.rs | 6 +--- 9 files changed, 67 insertions(+), 57 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 9154a23ccb..30689de66c 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -314,7 +314,7 @@ impl CharacterAbility { } } - pub fn adjust_stats(mut self, power: f32, speed: f32) -> Self { + pub fn adjusted_by_stats(mut self, power: f32, speed: f32) -> Self { use CharacterAbility::*; match self { BasicMelee { @@ -337,7 +337,7 @@ impl CharacterAbility { } => { *buildup_duration = (*buildup_duration as f32 / speed) as u64; *recover_duration = (*recover_duration as f32 / speed) as u64; - *projectile = projectile.modify_projectile(power); + *projectile = projectile.modified_projectile(power); }, RepeaterRanged { ref mut movement_duration, @@ -351,7 +351,7 @@ impl CharacterAbility { *buildup_duration = (*buildup_duration as f32 / speed) as u64; *shoot_duration = (*shoot_duration as f32 / speed) as u64; *recover_duration = (*recover_duration as f32 / speed) as u64; - *projectile = projectile.modify_projectile(power); + *projectile = projectile.modified_projectile(power); }, Boost { ref mut movement_duration, @@ -389,7 +389,7 @@ impl CharacterAbility { } => { *stage_data = stage_data .iter_mut() - .map(|s| s.adjust_stats(power, speed)) + .map(|s| s.adjusted_by_stats(power, speed)) .collect(); }, LeapMelee { @@ -701,11 +701,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { } => CharacterState::ComboMelee(combo_melee::Data { static_data: combo_melee::StaticData { num_stages: stage_data.len() as u32, - stage_data: stage_data - .clone() - .into_iter() - .map(|stage| stage.to_duration()) - .collect(), + stage_data: stage_data.iter().map(|stage| stage.to_duration()).collect(), initial_energy_gain: *initial_energy_gain, max_energy_gain: *max_energy_gain, energy_increase: *energy_increase, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index cda5a6637d..5f46baca2e 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -87,7 +87,7 @@ impl Tool { pub fn get_abilities(&self, map: &AbilityMap) -> AbilitySet { if let Some(set) = map.0.get(&self.kind).cloned() { - set.modify_from_tool(&self) + set.modified_by_tool(&self) } else { error!( "ToolKind: {:?} has no AbilitySet in the ability map falling back to default", @@ -106,29 +106,17 @@ pub struct AbilitySet { } impl AbilitySet { - pub fn modify_from_tool(self, tool: &Tool) -> Self { - Self { - primary: self - .primary - .adjust_stats(tool.base_power(), tool.base_speed()), - secondary: self - .secondary - .adjust_stats(tool.base_power(), tool.base_speed()), - skills: self - .skills - .into_iter() - .map(|a| a.adjust_stats(tool.base_power(), tool.base_speed())) - .collect(), - } + pub fn modified_by_tool(self, tool: &Tool) -> Self { + self.map(|a| a.adjusted_by_stats(tool.base_power(), tool.base_speed())) } } -impl AbilitySet { +impl AbilitySet { pub fn map U>(self, mut f: F) -> AbilitySet { AbilitySet { primary: f(self.primary), secondary: f(self.secondary), - skills: self.skills.iter().map(|x| f(x.clone())).collect(), + skills: self.skills.into_iter().map(|x| f(x)).collect(), } } } @@ -145,6 +133,7 @@ impl Default for AbilitySet { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AbilityMap(HashMap>); + impl Asset for AbilityMap { const ENDINGS: &'static [&'static str] = &["ron"]; diff --git a/common/src/comp/inventory/slot.rs b/common/src/comp/inventory/slot.rs index 8bc0a3296a..02f641b41c 100644 --- a/common/src/comp/inventory/slot.rs +++ b/common/src/comp/inventory/slot.rs @@ -139,7 +139,9 @@ fn loadout_insert( /// /// ``` /// use veloren_common::{ +/// assets::Asset, /// comp::{ +/// item::tool::AbilityMap, /// slot::{loadout_remove, EquipSlot}, /// Inventory, /// }, @@ -148,16 +150,19 @@ fn loadout_insert( /// /// let mut inv = Inventory::new_empty(); /// +/// let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); +/// /// let mut loadout = LoadoutBuilder::new() /// .defaults() /// .active_item(Some(LoadoutBuilder::default_item_config_from_str( /// "common.items.weapons.sword.zweihander_sword_0", +/// &map, /// ))) /// .build(); /// /// let slot = EquipSlot::Mainhand; /// -/// loadout_remove(slot, &mut loadout); +/// loadout_remove(slot, &mut loadout, &map); /// assert_eq!(None, loadout.active_item); /// ``` pub fn loadout_remove( @@ -260,6 +265,7 @@ pub fn swap( /// use veloren_common::{ /// assets::Asset, /// comp::{ +/// item::tool::AbilityMap, /// slot::{equip, EquipSlot}, /// Inventory, Item, /// }, @@ -273,7 +279,9 @@ pub fn swap( /// /// let mut loadout = LoadoutBuilder::new().defaults().build(); /// -/// equip(0, &mut inv, &mut loadout); +/// let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); +/// +/// equip(0, &mut inv, &mut loadout, &map); /// assert_eq!(Some(boots), loadout.foot); /// ``` pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: &AbilityMap) { @@ -316,7 +324,9 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: /// /// ``` /// use veloren_common::{ +/// assets::Asset, /// comp::{ +/// item::tool::AbilityMap, /// slot::{unequip, EquipSlot}, /// Inventory, /// }, @@ -325,16 +335,19 @@ pub fn equip(slot: usize, inventory: &mut Inventory, loadout: &mut Loadout, map: /// /// let mut inv = Inventory::new_empty(); /// +/// let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); +/// /// let mut loadout = LoadoutBuilder::new() /// .defaults() /// .active_item(Some(LoadoutBuilder::default_item_config_from_str( /// "common.items.weapons.sword.zweihander_sword_0", +/// &map, /// ))) /// .build(); /// /// let slot = EquipSlot::Mainhand; /// -/// unequip(slot, &mut inv, &mut loadout); +/// unequip(slot, &mut inv, &mut loadout, &map); /// assert_eq!(None, loadout.active_item); /// ``` pub fn unequip( @@ -361,8 +374,12 @@ mod tests { amount: 0, }; + use crate::assets::Asset; + let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); + let sword = LoadoutBuilder::default_item_config_from_str( "common.items.weapons.sword.zweihander_sword_0", + &map, ); let mut loadout = LoadoutBuilder::new() @@ -372,11 +389,11 @@ mod tests { .build(); assert_eq!(Some(sword.clone()), loadout.active_item); - unequip(EquipSlot::Mainhand, &mut inv, &mut loadout); + unequip(EquipSlot::Mainhand, &mut inv, &mut loadout, &map); // We have space in the inventory, so this should have unequipped assert_eq!(None, loadout.active_item); - unequip(EquipSlot::Offhand, &mut inv, &mut loadout); + unequip(EquipSlot::Offhand, &mut inv, &mut loadout, &map); // There is no more space in the inventory, so this should still be equipped assert_eq!(Some(sword.clone()), loadout.second_item); @@ -402,9 +419,12 @@ mod tests { let mut loadout = LoadoutBuilder::new().defaults().build(); + use crate::assets::Asset; + let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); + // We should start with the starting sandles assert_eq!(starting_sandles, loadout.foot); - equip(0, &mut inv, &mut loadout); + equip(0, &mut inv, &mut loadout, &map); // We should now have the testing boots equiped assert_eq!(boots, loadout.foot); @@ -424,6 +444,9 @@ mod tests { "common.items.armor.starter.sandals_0", )); + use crate::assets::Asset; + let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); + let mut loadout = LoadoutBuilder::new().defaults().build(); // We should start with the starting sandles @@ -436,6 +459,7 @@ mod tests { EquipSlot::Armor(ArmorSlot::Feet), boots.clone(), &mut loadout, + &map, ) ); @@ -445,8 +469,12 @@ mod tests { #[test] fn test_loadout_remove() { + use crate::assets::Asset; + let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); + let sword = LoadoutBuilder::default_item_config_from_str( "common.items.weapons.sword.zweihander_sword_0", + &map, ); let mut loadout = LoadoutBuilder::new() @@ -457,7 +485,7 @@ mod tests { // The swap should return the sword assert_eq!( Some(sword.item), - loadout_remove(EquipSlot::Mainhand, &mut loadout,) + loadout_remove(EquipSlot::Mainhand, &mut loadout, &map) ); // We should now have nothing equiped diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 3710c76ddc..f5a2d09891 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -1,6 +1,6 @@ use crate::{ comp::buff::{BuffCategory, BuffData, BuffKind}, - effect::{BuffEffect, Effect as EffectB}, + effect::{self, BuffEffect}, sync::Uid, Damage, DamageSource, Explosion, GroupTarget, Knockback, RadiusEffect, }; @@ -107,7 +107,7 @@ impl ProjectileConstructor { Effect::Explode(Explosion { effects: vec![RadiusEffect::Entity( Some(GroupTarget::OutOfGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Explosion, value: damage, }), @@ -121,7 +121,7 @@ impl ProjectileConstructor { Effect::Explode(Explosion { effects: vec![RadiusEffect::Entity( Some(GroupTarget::OutOfGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Explosion, value: damage, }), @@ -145,14 +145,14 @@ impl ProjectileConstructor { effects: vec![ RadiusEffect::Entity( Some(GroupTarget::OutOfGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Explosion, value: damage, }), ), RadiusEffect::Entity( Some(GroupTarget::InGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Healing, value: heal, }), @@ -168,14 +168,14 @@ impl ProjectileConstructor { effects: vec![ RadiusEffect::Entity( Some(GroupTarget::OutOfGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Explosion, value: damage, }), ), RadiusEffect::Entity( Some(GroupTarget::InGroup), - EffectB::Damage(Damage { + effect::Effect::Damage(Damage { source: DamageSource::Healing, value: heal, }), @@ -200,7 +200,7 @@ impl ProjectileConstructor { } } - pub fn modify_projectile(mut self, power: f32) -> Self { + pub fn modified_projectile(mut self, power: f32) -> Self { use ProjectileConstructor::*; match self { Arrow { ref mut damage, .. } => { diff --git a/common/src/loadout_builder.rs b/common/src/loadout_builder.rs index c364acbaf4..f0be91a52d 100644 --- a/common/src/loadout_builder.rs +++ b/common/src/loadout_builder.rs @@ -10,13 +10,19 @@ use rand::Rng; /// ItemConfig /// /// ``` -/// use veloren_common::LoadoutBuilder; +/// use veloren_common::{ +/// assets::Asset, +/// comp::item::tool::AbilityMap, +/// LoadoutBuilder, +/// }; +/// +/// let map = AbilityMap::load_expect_cloned("common.abilities.weapon_ability_manifest"); /// /// // Build a loadout with character starter defaults and a specific sword with default sword abilities /// let loadout = LoadoutBuilder::new() /// .defaults() /// .active_item(Some(LoadoutBuilder::default_item_config_from_str( -/// "common.items.weapons.sword.zweihander_sword_0" +/// "common.items.weapons.sword.zweihander_sword_0", &map /// ))) /// .build(); /// ``` diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index bc9e2052b5..ec3c25e822 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -51,7 +51,7 @@ impl Stage { } } - pub fn adjust_stats(mut self, power: f32, speed: f32) -> Self { + pub fn adjusted_by_stats(mut self, power: f32, speed: f32) -> Self { self.base_damage = (self.base_damage as f32 * power) as u32; self.max_damage = (self.max_damage as f32 * power) as u32; self.damage_increase = (self.damage_increase as f32 * power) as u32; diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index bfa9294059..4f322654f1 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -108,7 +108,7 @@ pub fn handle_unmount(server: &mut Server, mounter: EcsEntity) { #[allow(clippy::nonminimal_bool)] // TODO: Pending review in #587 pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) { let ecs = &server.state.ecs(); - let map = ecs.fetch::(); + let ability_map = ecs.fetch::(); if let (Some(possessor), Some(possesse)) = ( ecs.entity_from_uid(possessor_uid.into()), ecs.entity_from_uid(possesse_uid.into()), @@ -181,7 +181,7 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) { let item = comp::Item::new_from_asset_expect("common.items.debug.possess"); if let item::ItemKind::Tool(_) = item.kind() { - let debug_item = comp::ItemConfig::from((item, &*map)); + let debug_item = comp::ItemConfig::from((item, &*ability_map)); std::mem::swap(&mut loadout.active_item, &mut loadout.second_item); loadout.active_item = Some(debug_item); } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 03e44d2dc0..7fc03783de 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -10,12 +10,7 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client::{self, Client}; -use common::{ - assets::Asset, - comp::{self}, - span, - state::DeltaTime, -}; +use common::{assets::Asset, comp, span, state::DeltaTime}; use specs::WorldExt; use std::{cell::RefCell, rc::Rc}; use tracing::error; diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index e4696ea4d9..f3b57d1acc 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -12,11 +12,7 @@ use crate::{ Direction, GlobalState, PlayState, PlayStateResult, }; use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; -use common::{ - assets::Asset, - comp::{self}, - span, -}; +use common::{assets::Asset, comp, span}; use tracing::error; use ui::{Event as MainMenuEvent, MainMenuUi};