From 0031aa6f5fe44f159d45122746955a35eec996c4 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 8 Feb 2022 20:23:23 -0500 Subject: [PATCH] Chieftain AI and attacks --- .../common/abilities/ability_set_manifest.ron | 25 +++++++ .../gnarling/chieftain/firebarrage.ron | 15 ++++ .../gnarling/chieftain/fireshockwave.ron | 17 +++++ .../gnarling/chieftain/flamestrike.ron | 23 ++++++ .../gnarling/chieftain/greentotem.ron | 15 ++++ .../abilities/gnarling/chieftain/redtotem.ron | 15 ++++ .../gnarling/chieftain/whitetotem.ron | 15 ++++ .../common/abilities/gnarling/totem/green.ron | 24 +++++++ .../common/abilities/gnarling/totem/red.ron | 18 +++++ .../common/abilities/gnarling/totem/white.ron | 18 +++++ .../common/abilities/sceptre/healingaura.ron | 16 +++-- .../common/abilities/sceptre/wardingaura.ron | 16 +++-- .../entity/dungeon/gnarling/chieftain.ron | 5 +- .../biped_small/gnarling/chest/chieftain.ron | 4 +- .../biped_small/gnarling/chieftain.ron | 10 +-- .../biped_small/gnarling/greentotem.ron | 21 ++++++ .../biped_small/gnarling/redtotem.ron | 21 ++++++ .../biped_small/gnarling/whitetotem.ron | 21 ++++++ assets/voxygen/i18n/en/buff.ron | 2 + .../voxel/object/gnarling_totem_green.vox | 3 + .../voxel/object/gnarling_totem_red.vox | 3 + .../voxel/object/gnarling_totem_white.vox | 3 + assets/voxygen/voxel/object_manifest.ron | 30 ++++++++ common/src/cmd.rs | 1 + common/src/comp/ability.rs | 71 +++++++++--------- common/src/comp/aura.rs | 2 +- common/src/comp/body.rs | 3 + common/src/comp/body/object.rs | 15 +++- common/src/comp/buff.rs | 14 +++- common/src/comp/inventory/loadout_builder.rs | 9 +++ common/src/states/basic_aura.rs | 65 +++++++++-------- server/src/sys/agent.rs | 15 +++- server/src/sys/agent/attack.rs | 72 ++++++++++++++++--- server/src/sys/agent/data.rs | 1 + voxygen/src/hud/chat.rs | 3 +- voxygen/src/hud/mod.rs | 4 ++ voxygen/src/hud/util.rs | 6 +- world/src/site2/mod.rs | 2 +- world/src/site2/plot/gnarling.rs | 32 ++++----- 39 files changed, 534 insertions(+), 121 deletions(-) create mode 100644 assets/common/abilities/gnarling/chieftain/firebarrage.ron create mode 100644 assets/common/abilities/gnarling/chieftain/fireshockwave.ron create mode 100644 assets/common/abilities/gnarling/chieftain/flamestrike.ron create mode 100644 assets/common/abilities/gnarling/chieftain/greentotem.ron create mode 100644 assets/common/abilities/gnarling/chieftain/redtotem.ron create mode 100644 assets/common/abilities/gnarling/chieftain/whitetotem.ron create mode 100644 assets/common/abilities/gnarling/totem/green.ron create mode 100644 assets/common/abilities/gnarling/totem/red.ron create mode 100644 assets/common/abilities/gnarling/totem/white.ron create mode 100644 assets/common/items/npc_weapons/biped_small/gnarling/greentotem.ron create mode 100644 assets/common/items/npc_weapons/biped_small/gnarling/redtotem.ron create mode 100644 assets/common/items/npc_weapons/biped_small/gnarling/whitetotem.ron create mode 100644 assets/voxygen/voxel/object/gnarling_totem_green.vox create mode 100644 assets/voxygen/voxel/object/gnarling_totem_red.vox create mode 100644 assets/voxygen/voxel/object/gnarling_totem_white.vox diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 7cd5af3ee0..a4a49ba3ba 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -79,6 +79,31 @@ secondary: "common.abilities.gnarling.blowgun.dart", abilities: [], ), + Custom("Gnarling Chieftain"): ( + primary: "common.abilities.gnarling.chieftain.flamestrike", + secondary: "common.abilities.gnarling.chieftain.firebarrage", + abilities: [ + (None, "common.abilities.gnarling.chieftain.fireshockwave"), + (None, "common.abilities.gnarling.chieftain.redtotem"), + (None, "common.abilities.gnarling.chieftain.greentotem"), + (None, "common.abilities.gnarling.chieftain.whitetotem"), + ], + ), + Custom("Gnarling Totem Red"): ( + primary: "common.abilities.gnarling.totem.red", + secondary: "common.abilities.gnarling.totem.red", + abilities: [], + ), + Custom("Gnarling Totem Green"): ( + primary: "common.abilities.gnarling.totem.green", + secondary: "common.abilities.gnarling.totem.green", + abilities: [], + ), + Custom("Gnarling Totem White"): ( + primary: "common.abilities.gnarling.totem.white", + secondary: "common.abilities.gnarling.totem.white", + abilities: [], + ), Custom("Deadwood"): ( primary: "common.abilities.custom.deadwood.lifestealbeam", secondary: "common.abilities.custom.deadwood.dash", diff --git a/assets/common/abilities/gnarling/chieftain/firebarrage.ron b/assets/common/abilities/gnarling/chieftain/firebarrage.ron new file mode 100644 index 0000000000..13927fef2d --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/firebarrage.ron @@ -0,0 +1,15 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 0.5, + recover_duration: 0.4, + projectile: Fireball( + damage: 9.0, + radius: 4.0, + energy_regen: 10.0, + min_falloff: 0.5, + ), + projectile_body: Object(BoltFire), + projectile_speed: 40, + num_projectiles: 8, + projectile_spread: 0.05, +) diff --git a/assets/common/abilities/gnarling/chieftain/fireshockwave.ron b/assets/common/abilities/gnarling/chieftain/fireshockwave.ron new file mode 100644 index 0000000000..4c1a7e294f --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/fireshockwave.ron @@ -0,0 +1,17 @@ +Shockwave( + energy_cost: 0, + buildup_duration: 0.5, + swing_duration: 0.1, + recover_duration: 0.4, + damage: 15, + poise_damage: 0, + knockback: ( strength: 25, direction: Away), + shockwave_angle: 360, + shockwave_vertical_angle: 90, + shockwave_speed: 10, + shockwave_duration: 1, + requires_ground: false, + move_efficiency: 0, + damage_kind: Energy, + specifier: Fire, +) diff --git a/assets/common/abilities/gnarling/chieftain/flamestrike.ron b/assets/common/abilities/gnarling/chieftain/flamestrike.ron new file mode 100644 index 0000000000..a30300af9d --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/flamestrike.ron @@ -0,0 +1,23 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0.4, + swing_duration: 0.1, + recover_duration: 0.3, + melee_constructor: ( + kind: Bash( + damage: 5, + poise: 10, + knockback: 0, + energy_regen: 0, + ), + range: 7.5, + angle: 60.0, + damage_effect: Some(Buff(( + kind: Burning, + dur_secs: 10.0, + strength: DamageFraction(0.5), + chance: 0.5, + ))), + ), + ori_modifier: 0.7, +) diff --git a/assets/common/abilities/gnarling/chieftain/greentotem.ron b/assets/common/abilities/gnarling/chieftain/greentotem.ron new file mode 100644 index 0000000000..7a6284e92a --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/greentotem.ron @@ -0,0 +1,15 @@ +BasicSummon( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + summon_amount: 1, + summon_distance: (1, 1), + summon_info: ( + body: Object(GnarlingTotemGreen), + scale: None, + has_health: true, + loadout_config: None, + skillset_config: None, + ), + duration: None, +) diff --git a/assets/common/abilities/gnarling/chieftain/redtotem.ron b/assets/common/abilities/gnarling/chieftain/redtotem.ron new file mode 100644 index 0000000000..379b94e0c1 --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/redtotem.ron @@ -0,0 +1,15 @@ +BasicSummon( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + summon_amount: 1, + summon_distance: (1, 1), + summon_info: ( + body: Object(GnarlingTotemRed), + scale: None, + has_health: true, + loadout_config: None, + skillset_config: None, + ), + duration: None, +) diff --git a/assets/common/abilities/gnarling/chieftain/whitetotem.ron b/assets/common/abilities/gnarling/chieftain/whitetotem.ron new file mode 100644 index 0000000000..12003a475b --- /dev/null +++ b/assets/common/abilities/gnarling/chieftain/whitetotem.ron @@ -0,0 +1,15 @@ +BasicSummon( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + summon_amount: 1, + summon_distance: (1, 1), + summon_info: ( + body: Object(GnarlingTotemWhite), + scale: None, + has_health: true, + loadout_config: None, + skillset_config: None, + ), + duration: None, +) diff --git a/assets/common/abilities/gnarling/totem/green.ron b/assets/common/abilities/gnarling/totem/green.ron new file mode 100644 index 0000000000..3319d35e72 --- /dev/null +++ b/assets/common/abilities/gnarling/totem/green.ron @@ -0,0 +1,24 @@ +BasicAura( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + targets: InGroup, + auras: [ + ( + kind: Regeneration, + strength: 5, + duration: Some(5), + category: Magical, + ), + ( + kind: ProtectingWard, + strength: 0.50, + duration: Some(5), + category: Magical, + ), + ], + aura_duration: 60, + range: 50, + energy_cost: 0, + scales_with_combo: false, +) diff --git a/assets/common/abilities/gnarling/totem/red.ron b/assets/common/abilities/gnarling/totem/red.ron new file mode 100644 index 0000000000..0f5ac85488 --- /dev/null +++ b/assets/common/abilities/gnarling/totem/red.ron @@ -0,0 +1,18 @@ +BasicAura( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + targets: OutOfGroup, + auras: [ + ( + kind: Burning, + strength: 0.5, + duration: Some(5), + category: Magical, + ), + ], + aura_duration: 60, + range: 50, + energy_cost: 0, + scales_with_combo: false, +) diff --git a/assets/common/abilities/gnarling/totem/white.ron b/assets/common/abilities/gnarling/totem/white.ron new file mode 100644 index 0000000000..0f1a9a402d --- /dev/null +++ b/assets/common/abilities/gnarling/totem/white.ron @@ -0,0 +1,18 @@ +BasicAura( + buildup_duration: 0.25, + cast_duration: 0.5, + recover_duration: 0.25, + targets: InGroup, + auras: [ + ( + kind: Hastened, + strength: 0.5, + duration: Some(5), + category: Magical, + ), + ], + aura_duration: 60, + range: 50, + energy_cost: 0, + scales_with_combo: false, +) diff --git a/assets/common/abilities/sceptre/healingaura.ron b/assets/common/abilities/sceptre/healingaura.ron index 08c7afcad2..a9b387c4d5 100644 --- a/assets/common/abilities/sceptre/healingaura.ron +++ b/assets/common/abilities/sceptre/healingaura.ron @@ -3,15 +3,17 @@ BasicAura( cast_duration: 0.5, recover_duration: 0.25, targets: InGroup, - aura: ( - kind: Regeneration, - strength: 0.2, - duration: Some(10.0), - category: Magical, - ), + auras: [ + ( + kind: Regeneration, + strength: 0.2, + duration: Some(10.0), + category: Magical, + ), + ], aura_duration: 1.0, range: 25.0, energy_cost: 20.0, scales_with_combo: true, - specifier: HealingAura, + specifier: Some(HealingAura), ) diff --git a/assets/common/abilities/sceptre/wardingaura.ron b/assets/common/abilities/sceptre/wardingaura.ron index a39ae2eb52..76e01610fc 100644 --- a/assets/common/abilities/sceptre/wardingaura.ron +++ b/assets/common/abilities/sceptre/wardingaura.ron @@ -3,15 +3,17 @@ BasicAura( cast_duration: 0.5, recover_duration: 0.25, targets: InGroup, - aura: ( - kind: ProtectingWard, - strength: 0.20, - duration: Some(10.0), - category: Magical, - ), + auras: [ + ( + kind: ProtectingWard, + strength: 0.20, + duration: Some(10.0), + category: Magical, + ), + ], aura_duration: 1.0, range: 25.0, energy_cost: 40.0, scales_with_combo: false, - specifier: WardingAura, + specifier: Some(WardingAura), ) diff --git a/assets/common/entity/dungeon/gnarling/chieftain.ron b/assets/common/entity/dungeon/gnarling/chieftain.ron index 3460358b9b..88f5e42f7e 100644 --- a/assets/common/entity/dungeon/gnarling/chieftain.ron +++ b/assets/common/entity/dungeon/gnarling/chieftain.ron @@ -8,5 +8,8 @@ inventory: [], ), loot: LootTable("common.loot_tables.dungeon.tier-0.enemy"), - meta: [], + meta: [ + // Done for health reasons + SkillSetAsset("common.skillset.preset.rank5.fullskill"), + ], ) diff --git a/assets/common/items/npc_armor/biped_small/gnarling/chest/chieftain.ron b/assets/common/items/npc_armor/biped_small/gnarling/chest/chieftain.ron index 87f243f870..7d514e1b0c 100644 --- a/assets/common/items/npc_armor/biped_small/gnarling/chest/chieftain.ron +++ b/assets/common/items/npc_armor/biped_small/gnarling/chest/chieftain.ron @@ -4,8 +4,8 @@ ItemDef( kind: Armor(( kind: Chest("GnarlingChieftain"), stats: ( - protection: Some(Normal(2.0)), - poise_resilience: Some(Normal(1.0)), + protection: Some(Normal(60.0)), + poise_resilience: Some(Normal(60.0)), energy_max: Some(2.7), energy_reward: Some(0.027), crit_power: Some(0.025), diff --git a/assets/common/items/npc_weapons/biped_small/gnarling/chieftain.ron b/assets/common/items/npc_weapons/biped_small/gnarling/chieftain.ron index 11fd044bac..7c5e2c6868 100644 --- a/assets/common/items/npc_weapons/biped_small/gnarling/chieftain.ron +++ b/assets/common/items/npc_weapons/biped_small/gnarling/chieftain.ron @@ -6,10 +6,10 @@ ItemDef( hands: Two, stats: Direct(( equip_time_secs: 0.0, - power: 0.3, - effect_power: 0.8, - speed: 0.6, - crit_chance: 0.26764706, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, range: 1.0, energy_efficiency: 1.0, buff_strength: 1.0, @@ -17,5 +17,5 @@ ItemDef( )), quality: Low, tags: [], - ability_spec: Some(Custom("Staff Simple")), + ability_spec: Some(Custom("Gnarling Chieftain")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/gnarling/greentotem.ron b/assets/common/items/npc_weapons/biped_small/gnarling/greentotem.ron new file mode 100644 index 0000000000..87b27d2767 --- /dev/null +++ b/assets/common/items/npc_weapons/biped_small/gnarling/greentotem.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Gnarling Green Totem", + description: "Yeet", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Gnarling Totem Green")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/gnarling/redtotem.ron b/assets/common/items/npc_weapons/biped_small/gnarling/redtotem.ron new file mode 100644 index 0000000000..d7a5353fc0 --- /dev/null +++ b/assets/common/items/npc_weapons/biped_small/gnarling/redtotem.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Gnarling Red Totem", + description: "Yeet", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Gnarling Totem Red")), +) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/biped_small/gnarling/whitetotem.ron b/assets/common/items/npc_weapons/biped_small/gnarling/whitetotem.ron new file mode 100644 index 0000000000..fddc61cab7 --- /dev/null +++ b/assets/common/items/npc_weapons/biped_small/gnarling/whitetotem.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Gnarling White Totem", + description: "Yeet", + kind: Tool(( + kind: Natural, + hands: Two, + stats: Direct(( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.1, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Gnarling Totem White")), +) \ No newline at end of file diff --git a/assets/voxygen/i18n/en/buff.ron b/assets/voxygen/i18n/en/buff.ron index 8b63f58575..793abe289f 100644 --- a/assets/voxygen/i18n/en/buff.ron +++ b/assets/voxygen/i18n/en/buff.ron @@ -21,6 +21,8 @@ "buff.desc.protectingward": "You are protected, somewhat, from attacks.", "buff.title.frenzied": "Frenzied", "buff.desc.frenzied": "You are imbued with unnatural speed and can ignore minor injuries.", + "buff.title.hastened": "Hastened", + "buff.desc.hastened": "Your movements and attacks are faster.", // Debuffs "buff.title.bleed": "Bleeding", "buff.desc.bleed": "Inflicts regular damage.", diff --git a/assets/voxygen/voxel/object/gnarling_totem_green.vox b/assets/voxygen/voxel/object/gnarling_totem_green.vox new file mode 100644 index 0000000000..27e04568ff --- /dev/null +++ b/assets/voxygen/voxel/object/gnarling_totem_green.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d522e7c29184f1ba8a56f05f2c3665db88c5383fb965bea535aa11da55cd910 +size 5344 diff --git a/assets/voxygen/voxel/object/gnarling_totem_red.vox b/assets/voxygen/voxel/object/gnarling_totem_red.vox new file mode 100644 index 0000000000..4ee0ff7d9a --- /dev/null +++ b/assets/voxygen/voxel/object/gnarling_totem_red.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf893aaa310c3abfbf4d5ab2c31986263e1ed813a45b7d3157ee4f1d71e06913 +size 5160 diff --git a/assets/voxygen/voxel/object/gnarling_totem_white.vox b/assets/voxygen/voxel/object/gnarling_totem_white.vox new file mode 100644 index 0000000000..82e5bc8fc3 --- /dev/null +++ b/assets/voxygen/voxel/object/gnarling_totem_white.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88250e9cfdd71d8b1beedae51bdbcb24b8a85985afa4228352e6b9feeff55ad6 +size 5408 diff --git a/assets/voxygen/voxel/object_manifest.ron b/assets/voxygen/voxel/object_manifest.ron index cd3a011aa3..bc56ce1b90 100644 --- a/assets/voxygen/voxel/object_manifest.ron +++ b/assets/voxygen/voxel/object_manifest.ron @@ -829,4 +829,34 @@ central: ("armor.empty"), ) ), + GnarlingTotemRed: ( + bone0: ( + offset: (-6.0, -5.0, 0.0), + central: ("object.gnarling_totem_red"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + GnarlingTotemGreen: ( + bone0: ( + offset: (-9.0, -5.0, 0.0), + central: ("object.gnarling_totem_green"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), + GnarlingTotemWhite: ( + bone0: ( + offset: (-8.0, -5.0, 0.0), + central: ("object.gnarling_totem_white"), + ), + bone1: ( + offset: (0.0, 0.0, 0.0), + central: ("armor.empty"), + ) + ), }) diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 4eb7621a9d..bcc878172b 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -207,6 +207,7 @@ lazy_static! { BuffKind::Wet => "wet", BuffKind::Ensnared => "ensnared", BuffKind::Poisoned => "poisoned", + BuffKind::Hastened => "hastened", }; let mut buff_parser = HashMap::new(); BuffKind::iter().for_each(|kind| {buff_parser.insert(string_from_buff(kind).to_string(), kind);}); diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 8ad672aba0..fde2e1d6b9 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -552,12 +552,12 @@ pub enum CharacterAbility { cast_duration: f32, recover_duration: f32, targets: combat::GroupTarget, - aura: aura::AuraBuffConstructor, + auras: Vec, aura_duration: f32, range: f32, energy_cost: f32, scales_with_combo: bool, - specifier: aura::Specifier, + specifier: Option, }, Blink { buildup_duration: f32, @@ -964,13 +964,7 @@ impl CharacterAbility { ref mut cast_duration, ref mut recover_duration, targets: _, - aura: - aura::AuraBuffConstructor { - kind: _, - ref mut strength, - duration: _, - category: _, - }, + ref mut auras, aura_duration: _, ref mut range, ref mut energy_cost, @@ -980,9 +974,18 @@ impl CharacterAbility { *buildup_duration /= stats.speed; *cast_duration /= stats.speed; *recover_duration /= stats.speed; - // Do we want to make buff_strength affect this instead of power? - // Look into during modular weapon transition - *strength *= stats.power; + auras.iter_mut().for_each( + |aura::AuraBuffConstructor { + kind: _, + ref mut strength, + duration: _, + category: _, + }| { + // Do we want to make buff_strength affect this instead of power? + // Look into during modular weapon transition + *strength *= stats.power; + }, + ); *range *= stats.range; *energy_cost /= stats.energy_efficiency; }, @@ -1079,7 +1082,6 @@ impl CharacterAbility { } #[must_use = "method returns new ability and doesn't mutate the original value"] - #[warn(clippy::pedantic)] pub fn adjusted_by_skills(mut self, skillset: &SkillSet, tool: Option) -> Self { match tool { Some(ToolKind::Sword) => self.adjusted_by_sword_skills(skillset), @@ -1095,7 +1097,6 @@ impl CharacterAbility { self } - #[warn(clippy::pedantic)] fn adjusted_by_mining_skills(&mut self, skillset: &SkillSet) { use skills::MiningSkill::Speed; @@ -1117,7 +1118,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_general_skills(&mut self, skillset: &SkillSet) { if let CharacterAbility::Roll { ref mut energy_cost, @@ -1239,7 +1239,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_axe_skills(&mut self, skillset: &SkillSet) { #![allow(clippy::enum_glob_use)] use skills::{AxeSkill::*, Skill::Axe}; @@ -1333,7 +1332,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_hammer_skills(&mut self, skillset: &SkillSet) { #![allow(clippy::enum_glob_use)] use skills::{HammerSkill::*, Skill::Hammer}; @@ -1436,7 +1434,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_bow_skills(&mut self, skillset: &SkillSet) { #![allow(clippy::enum_glob_use)] use skills::{BowSkill::*, Skill::Bow}; @@ -1537,7 +1534,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_staff_skills(&mut self, skillset: &SkillSet) { #![allow(clippy::enum_glob_use)] use skills::{Skill::Staff, StaffSkill::*}; @@ -1607,7 +1603,6 @@ impl CharacterAbility { } } - #[warn(clippy::pedantic)] fn adjusted_by_sceptre_skills(&mut self, skillset: &SkillSet) { #![allow(clippy::enum_glob_use)] use skills::{SceptreSkill::*, Skill::Sceptre}; @@ -1641,20 +1636,24 @@ impl CharacterAbility { } }, CharacterAbility::BasicAura { - ref mut aura, + ref mut auras, ref mut range, ref mut energy_cost, - specifier: aura::Specifier::HealingAura, + specifier: Some(aura::Specifier::HealingAura), .. } => { let modifiers = SKILL_MODIFIERS.sceptre_tree.healing_aura; if let Ok(level) = skillset.skill_level(Sceptre(HHeal)) { - aura.strength *= modifiers.strength.powi(level.into()); + auras.iter_mut().for_each(|ref mut aura| { + aura.strength *= modifiers.strength.powi(level.into()); + }); } if let Ok(level) = skillset.skill_level(Sceptre(HDuration)) { - if let Some(ref mut duration) = aura.duration { - *duration *= modifiers.duration.powi(level.into()); - } + auras.iter_mut().for_each(|ref mut aura| { + if let Some(ref mut duration) = aura.duration { + *duration *= modifiers.duration.powi(level.into()); + } + }); } if let Ok(level) = skillset.skill_level(Sceptre(HRange)) { *range *= modifiers.range.powi(level.into()); @@ -1664,20 +1663,24 @@ impl CharacterAbility { } }, CharacterAbility::BasicAura { - ref mut aura, + ref mut auras, ref mut range, ref mut energy_cost, - specifier: aura::Specifier::WardingAura, + specifier: Some(aura::Specifier::WardingAura), .. } => { let modifiers = SKILL_MODIFIERS.sceptre_tree.warding_aura; if let Ok(level) = skillset.skill_level(Sceptre(AStrength)) { - aura.strength *= modifiers.strength.powi(level.into()); + auras.iter_mut().for_each(|ref mut aura| { + aura.strength *= modifiers.strength.powi(level.into()); + }); } if let Ok(level) = skillset.skill_level(Sceptre(ADuration)) { - if let Some(ref mut duration) = aura.duration { - *duration *= modifiers.duration.powi(level.into()); - } + auras.iter_mut().for_each(|ref mut aura| { + if let Some(ref mut duration) = aura.duration { + *duration *= modifiers.duration.powi(level.into()); + } + }); } if let Ok(level) = skillset.skill_level(Sceptre(ARange)) { *range *= modifiers.range.powi(level.into()); @@ -2085,7 +2088,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { cast_duration, recover_duration, targets, - aura, + auras, aura_duration, range, energy_cost: _, @@ -2097,7 +2100,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { cast_duration: Duration::from_secs_f32(*cast_duration), recover_duration: Duration::from_secs_f32(*recover_duration), targets: *targets, - aura: *aura, + auras: auras.clone(), aura_duration: Duration::from_secs_f32(*aura_duration), range: *range, ability_info, diff --git a/common/src/comp/aura.rs b/common/src/comp/aura.rs index 821a9c3989..447cda6090 100644 --- a/common/src/comp/aura.rs +++ b/common/src/comp/aura.rs @@ -58,7 +58,7 @@ pub enum AuraChange { } /// Used by the aura system to filter entities when applying an effect. -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub enum AuraTarget { /// Targets the group of the entity specified by the `Uid`. This is useful /// for auras which should only affect a player's party. diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index f6b21b9bef..06e4058b3e 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -694,6 +694,9 @@ impl Body { object::Body::Crossbow => 80, object::Body::HaniwaSentry => 60, object::Body::SeaLantern => 100, + object::Body::GnarlingTotemRed + | object::Body::GnarlingTotemGreen + | object::Body::GnarlingTotemWhite => 25, _ => 1000, }, Body::Golem(golem) => match golem.species { diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 37db11e7cb..638c12b6d4 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -95,6 +95,9 @@ make_case_elim!( SpitPoison = 80, BoltIcicle = 81, Dart = 82, + GnarlingTotemRed = 83, + GnarlingTotemGreen = 84, + GnarlingTotemWhite = 85, } ); @@ -105,7 +108,7 @@ impl Body { } } -pub const ALL_OBJECTS: [Body; 83] = [ +pub const ALL_OBJECTS: [Body; 86] = [ Body::Arrow, Body::Bomb, Body::Scarecrow, @@ -189,6 +192,9 @@ pub const ALL_OBJECTS: [Body; 83] = [ Body::SpitPoison, Body::BoltIcicle, Body::Dart, + Body::GnarlingTotemRed, + Body::GnarlingTotemWhite, + Body::GnarlingTotemGreen, ]; impl From for super::Body { @@ -281,6 +287,9 @@ impl Body { Body::SpitPoison => "spit_poison", Body::BoltIcicle => "bolt_icicle", Body::Dart => "dart", + Body::GnarlingTotemRed => "gnarling_totem_red", + Body::GnarlingTotemGreen => "gnarling_totem_green", + Body::GnarlingTotemWhite => "gnarling_totem_white", } } @@ -390,6 +399,7 @@ impl Body { Body::Apple => 2.0, Body::Hive => 2.0, Body::Coconut => 2.0, + Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => 100.0, }; Mass(m) @@ -407,6 +417,9 @@ impl Body { Body::Snowball => Vec3::broadcast(2.5), Body::Tornado => Vec3::new(2.0, 2.0, 3.4), Body::TrainingDummy => Vec3::new(1.5, 1.5, 3.0), + Body::GnarlingTotemRed | Body::GnarlingTotemGreen | Body::GnarlingTotemWhite => { + Vec3::new(0.8, 0.8, 1.4) + }, // FIXME: this *must* be exhaustive match _ => Vec3::broadcast(0.5), } diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index 69d4f06d36..89989c1fef 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -46,6 +46,10 @@ pub enum BuffKind { /// Strength scales the movement speed linearly. 0.5 is 150% speed, 1.0 is /// 200% speed. Provides regeneration at 10x the value of the strength Frenzied, + /// Increases movement and attack speed. + /// Strength scales strength of both effects linearly. 0.5 is a 50% + /// increase, 1.0 is a 100% increase. + Hastened, // Debuffs /// Does damage to a creature over time /// Strength should be the DPS of the debuff @@ -92,7 +96,8 @@ impl BuffKind { | BuffKind::IncreaseMaxEnergy | BuffKind::IncreaseMaxHealth | BuffKind::Invulnerability - | BuffKind::ProtectingWard => true, + | BuffKind::ProtectingWard + | BuffKind::Hastened => true, BuffKind::Bleeding | BuffKind::Cursed | BuffKind::Burning @@ -347,6 +352,13 @@ impl Buff { vec![BuffEffect::MovementSpeed(1.0 - nn_scaling(data.strength))], data.duration, ), + BuffKind::Hastened => ( + vec![ + BuffEffect::MovementSpeed(1.0 + data.strength), + BuffEffect::AttackSpeed(1.0 + data.strength), + ], + data.duration, + ), }; Buff { kind, diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 84c8c9873b..1ce54524e6 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -365,6 +365,15 @@ fn default_main_tool(body: &Body) -> Item { object::Body::Tornado => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.tornado", )), + object::Body::GnarlingTotemRed => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.biped_small.gnarling.redtotem", + )), + object::Body::GnarlingTotemGreen => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.biped_small.gnarling.greentotem", + )), + object::Body::GnarlingTotemWhite => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.biped_small.gnarling.whitetotem", + )), _ => None, }, Body::BipedSmall(biped_small) => match (biped_small.species, biped_small.body_type) { diff --git a/common/src/states/basic_aura.rs b/common/src/states/basic_aura.rs index d15733c684..bc0aeb82ae 100644 --- a/common/src/states/basic_aura.rs +++ b/common/src/states/basic_aura.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; /// Separated out to condense update portions of character state -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct StaticData { /// How long until state should create the aura pub buildup_duration: Duration, @@ -26,8 +26,8 @@ pub struct StaticData { pub recover_duration: Duration, /// Determines how the aura selects its targets pub targets: GroupTarget, - /// Has information used to construct the aura - pub aura: AuraBuffConstructor, + /// Has information used to construct the auras + pub auras: Vec, /// How long aura lasts pub aura_duration: Duration, /// Radius of aura @@ -39,10 +39,10 @@ pub struct StaticData { /// Combo at the time the aura is first cast pub combo_at_cast: u32, /// Used to specify aura to the frontend - pub specifier: Specifier, + pub specifier: Option, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Data { /// Struct containing data that does not change over the course of the /// character state @@ -66,6 +66,7 @@ impl CharacterBehavior for Data { if self.timer < self.static_data.buildup_duration { // Build up update.character = CharacterState::BasicAura(Data { + static_data: self.static_data.clone(), timer: tick_attack_or_default(data, self.timer, None), ..*self }); @@ -73,38 +74,40 @@ impl CharacterBehavior for Data { // Creates aura let targets = AuraTarget::from((Some(self.static_data.targets), Some(data.uid))); - let mut aura = self.static_data.aura.to_aura( - data.uid, - self.static_data.range, - Some(self.static_data.aura_duration), - targets, - ); - if self.static_data.scales_with_combo { - match aura.aura_kind { - AuraKind::Buff { - kind: _, - ref mut data, - category: _, - source: _, - } => { - data.strength *= - 1.0 + (self.static_data.combo_at_cast.max(1) as f32).log(2.0); - }, + for aura_data in &self.static_data.auras { + let mut aura = aura_data.to_aura( + data.uid, + self.static_data.range, + Some(self.static_data.aura_duration), + targets, + ); + if self.static_data.scales_with_combo { + match aura.aura_kind { + AuraKind::Buff { + kind: _, + ref mut data, + category: _, + source: _, + } => { + data.strength *= 1.0 + + (self.static_data.combo_at_cast.max(1) as f32).log(2.0); + }, + } + output_events.emit_server(ServerEvent::ComboChange { + entity: data.entity, + change: -(self.static_data.combo_at_cast as i32), + }); } - output_events.emit_server(ServerEvent::ComboChange { + output_events.emit_server(ServerEvent::Aura { entity: data.entity, - change: -(self.static_data.combo_at_cast as i32), + aura_change: AuraChange::Add(aura), }); } - output_events.emit_server(ServerEvent::Aura { - entity: data.entity, - aura_change: AuraChange::Add(aura), - }); // Build up update.character = CharacterState::BasicAura(Data { + static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Action, - ..*self }); } }, @@ -112,20 +115,22 @@ impl CharacterBehavior for Data { if self.timer < self.static_data.cast_duration { // Cast update.character = CharacterState::BasicAura(Data { + static_data: self.static_data.clone(), timer: tick_attack_or_default(data, self.timer, None), ..*self }); } else { update.character = CharacterState::BasicAura(Data { + static_data: self.static_data.clone(), timer: Duration::default(), stage_section: StageSection::Recover, - ..*self }); } }, StageSection::Recover => { if self.timer < self.static_data.recover_duration { update.character = CharacterState::BasicAura(Data { + static_data: self.static_data.clone(), timer: tick_attack_or_default(data, self.timer, None), ..*self }); diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index dccf1799b6..ba3b3431d7 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1742,7 +1742,11 @@ impl<'a> AgentData<'a> { "Minotaur" => Tactic::Minotaur, "Clay Golem" => Tactic::ClayGolem, "Tidal Warrior" => Tactic::TidalWarrior, - "Tidal Totem" | "Tornado" => Tactic::RadialTurret, + "Tidal Totem" + | "Tornado" + | "Gnarling Totem Red" + | "Gnarling Totem Green" + | "Gnarling Totem White" => Tactic::RadialTurret, "Yeti" => Tactic::Yeti, "Harvester" => Tactic::Harvester, "Gnarling Dagger" => Tactic::SimpleBackstab, @@ -1750,6 +1754,7 @@ impl<'a> AgentData<'a> { "Deadwood" => Tactic::Deadwood, "Mandragora" => Tactic::Mandragora, "Wood Golem" => Tactic::WoodGolem, + "Gnarling Chieftain" => Tactic::GnarlingChieftain, _ => Tactic::SimpleMelee, }, AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind), @@ -2136,6 +2141,14 @@ impl<'a> AgentData<'a> { Tactic::WoodGolem => { self.handle_wood_golem(agent, controller, &attack_data, tgt_data, read_data) }, + Tactic::GnarlingChieftain => self.handle_gnarling_chieftain( + agent, + controller, + &attack_data, + tgt_data, + read_data, + rng, + ), } } diff --git a/server/src/sys/agent/attack.rs b/server/src/sys/agent/attack.rs index a2ac4f7c81..295be930f7 100644 --- a/server/src/sys/agent/attack.rs +++ b/server/src/sys/agent/attack.rs @@ -1237,18 +1237,11 @@ impl<'a> AgentData<'a> { &self, _agent: &mut Agent, controller: &mut Controller, - attack_data: &AttackData, - tgt_data: &TargetData, - read_data: &ReadData, + _attack_data: &AttackData, + _tgt_data: &TargetData, + _read_data: &ReadData, ) { - if can_see_tgt( - &*read_data.terrain, - self.pos, - tgt_data.pos, - attack_data.dist_sqrd, - ) { - controller.push_basic_input(InputKind::Primary); - } + controller.push_basic_input(InputKind::Primary); } pub fn handle_mindflayer_attack( @@ -2246,4 +2239,61 @@ impl<'a> AgentData<'a> { self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); } } + + pub fn handle_gnarling_chieftain( + &self, + agent: &mut Agent, + controller: &mut Controller, + attack_data: &AttackData, + tgt_data: &TargetData, + read_data: &ReadData, + rng: &mut impl Rng, + ) { + const TOTEM_TIMER: f32 = 15.0; + const HEAVY_ATTACK_WAIT_TIME: f32 = 20.0; + + // Handle timers + agent.action_state.timer += read_data.dt.0; + match self.char_state { + CharacterState::BasicSummon(_) => agent.action_state.timer = 0.0, + CharacterState::Shockwave(_) | CharacterState::BasicRanged(_) => { + agent.action_state.counter = 0.0 + }, + _ => {}, + } + + // If time to summon a totem, do it + if agent.action_state.timer > TOTEM_TIMER { + let input = rng.gen_range(1..=3); + controller.push_basic_input(InputKind::Ability(input)); + } else if agent.action_state.counter > HEAVY_ATTACK_WAIT_TIME { + // Else if time for a heavy attack + if attack_data.in_min_range() { + // If in range, shockwave + controller.push_basic_input(InputKind::Ability(0)); + } else if can_see_tgt( + &read_data.terrain, + self.pos, + tgt_data.pos, + attack_data.dist_sqrd, + ) { + // Else if in sight, barrage + controller.push_basic_input(InputKind::Secondary); + } + } else if attack_data.in_min_range() { + // Else if not time to use anything fancy, if in range and angle, strike them + if attack_data.angle < 20.0 { + controller.push_basic_input(InputKind::Primary); + agent.action_state.counter += read_data.dt.0; + } else { + // If not in angle, charge heavy attack faster + agent.action_state.counter += read_data.dt.0 * 5.0; + } + } else { + // If not in range, charge heavy attack faster + agent.action_state.counter += read_data.dt.0 * 3.3; + } + + self.path_toward_target(agent, controller, tgt_data, read_data, false, true, None); + } } diff --git a/server/src/sys/agent/data.rs b/server/src/sys/agent/data.rs index d294067ff7..8e016a5f0d 100644 --- a/server/src/sys/agent/data.rs +++ b/server/src/sys/agent/data.rs @@ -117,6 +117,7 @@ pub enum Tactic { Deadwood, Mandragora, WoodGolem, + GnarlingChieftain, } #[derive(SystemData)] diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 450bcc3ece..5142d3b8c6 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -777,7 +777,8 @@ fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, templat | BuffKind::IncreaseMaxHealth | BuffKind::Invulnerability | BuffKind::ProtectingWard - | BuffKind::Frenzied => { + | BuffKind::Frenzied + | BuffKind::Hastened => { tracing::error!("Player was killed by a positive buff!"); localized_strings.get("hud.outcome.mysterious") }, diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 484c6ca090..1f3c255540 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -4295,6 +4295,8 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id { BuffKind::Invulnerability => imgs.buff_invincibility_0, BuffKind::ProtectingWard => imgs.buff_dmg_red_0, BuffKind::Frenzied { .. } => imgs.buff_frenzy_0, + // TODO: Get unique icon + BuffKind::Hastened { .. } => imgs.buff_frenzy_0, // Debuffs BuffKind::Bleeding { .. } => imgs.debuff_bleed_0, BuffKind::Cursed { .. } => imgs.debuff_skull_0, @@ -4319,6 +4321,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> &str BuffKind::Invulnerability => localized_strings.get("buff.title.invulnerability"), BuffKind::ProtectingWard => localized_strings.get("buff.title.protectingward"), BuffKind::Frenzied => localized_strings.get("buff.title.frenzied"), + BuffKind::Hastened => localized_strings.get("buff.title.hastened"), // Debuffs BuffKind::Bleeding { .. } => localized_strings.get("buff.title.bleed"), BuffKind::Cursed { .. } => localized_strings.get("buff.title.cursed"), @@ -4355,6 +4358,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz Cow::Borrowed(localized_strings.get("buff.desc.protectingward")) }, BuffKind::Frenzied => Cow::Borrowed(localized_strings.get("buff.desc.frenzied")), + BuffKind::Hastened => Cow::Borrowed(localized_strings.get("buff.desc.hastened")), // Debuffs BuffKind::Bleeding { .. } => Cow::Borrowed(localized_strings.get("buff.desc.bleed")), BuffKind::Cursed { .. } => Cow::Borrowed(localized_strings.get("buff.desc.cursed")), diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index a2d2bef185..44c0737ce4 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -173,7 +173,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Frozen | BuffKind::Wet | BuffKind::Ensnared - | BuffKind::Poisoned => "".to_owned(), + | BuffKind::Poisoned + | BuffKind::Hastened => "".to_owned(), }; write!(&mut description, "{}", buff_desc).unwrap(); @@ -199,7 +200,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { | BuffKind::Frozen | BuffKind::Wet | BuffKind::Ensnared - | BuffKind::Poisoned => "".to_owned(), + | BuffKind::Poisoned + | BuffKind::Hastened => "".to_owned(), } } else if let BuffKind::Saturation | BuffKind::Regeneration = buff.kind { i18n.get("buff.text.every_second").to_string() diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 773d6ac814..9b01c6da9e 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -967,7 +967,7 @@ impl Site { PlotKind::Workshop(workshop) => workshop.render_collect(self, canvas), PlotKind::Castle(castle) => castle.render_collect(self, canvas), PlotKind::Dungeon(dungeon) => dungeon.render_collect(self, canvas), - PlotKind::Gnarling(gnarling) => gnarling.render_collect(self, &canvas), + PlotKind::Gnarling(gnarling) => gnarling.render_collect(self, canvas), PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas), _ => continue, }; diff --git a/world/src/site2/plot/gnarling.rs b/world/src/site2/plot/gnarling.rs index 80df7afd59..b9cd53283d 100644 --- a/world/src/site2/plot/gnarling.rs +++ b/world/src/site2/plot/gnarling.rs @@ -529,7 +529,7 @@ impl Structure for GnarlingFortification { wall_par_thickness, wall_par_height + parapet_z_offset as f32, ) - .fill(darkwood.clone()); + .fill(darkwood); }) } @@ -584,14 +584,14 @@ impl Structure for GnarlingFortification { tower_radius - 3.0, tower_height, )) - .fill(darkwood.clone()); + .fill(darkwood); painter .prim(Primitive::cylinder( wpos.with_z(land.get_alt_approx(wpos) as i32), tower_radius - 4.0, tower_height, )) - .fill(midwood.clone()); + .fill(midwood); //top layer, green above the tower painter .prim(Primitive::cylinder( @@ -599,7 +599,7 @@ impl Structure for GnarlingFortification { tower_radius, 2.0, )) - .fill(moss.clone()); + .fill(moss); //standing area one block deeper painter .prim(Primitive::cylinder( @@ -705,7 +705,7 @@ impl Structure for GnarlingFortification { .with_z(land.get_alt_approx(wpos) as i32 + tower_height as i32 - 16), }) .intersect(outside) - .fill(red.clone()); + .fill(red); }); self.structure_locations @@ -763,14 +763,14 @@ impl Structure for GnarlingFortification { hut_radius - 2.0, hut_wall_height + 3.0, )) - .fill(midwood.clone()); + .fill(midwood); painter .prim(Primitive::cylinder( floor_pos, hut_radius - 3.0, hut_wall_height + 3.0, )) - .fill(darkwood.clone()); + .fill(darkwood); painter .prim(Primitive::cylinder( floor_pos, @@ -832,7 +832,7 @@ impl Structure for GnarlingFortification { let tendril4 = tendril1.translate(Vec3::new(7, 4, 0)); let tendrils = tendril1.union(tendril2).union(tendril3).union(tendril4); - tendrils.fill(moss.clone()); + tendrils.fill(moss); //sphere to delete some hut painter @@ -917,7 +917,7 @@ impl Structure for GnarlingFortification { let floor2_pos = wpos.with_z(alt + 1 + raise + height_1 as i32); painter .prim(Primitive::cylinder(floor2_pos, rad_2, height_2)) - .fill(midwood.clone()); + .fill(midwood); // Roof let roof_radius = rad_1 + 5.0; @@ -934,7 +934,7 @@ impl Structure for GnarlingFortification { roof_radius, roof_height, )) - .fill(moss.clone()); + .fill(moss); let centerspot = painter.line( (wpos + 1).with_z(alt + raise + height_1 as i32 + 2), (wpos + 1).with_z(alt + raise + height_1 as i32 + 2), @@ -1094,7 +1094,7 @@ impl Structure for GnarlingFortification { }) .intersect(roof1) .translate(Vec3::new(0, 0, -1)) - .fill(darkwood.clone()); + .fill(darkwood); painter .aabb(Aabb { min: Vec2::new(wpos.x - 2, wpos.y - 23) @@ -1103,7 +1103,7 @@ impl Structure for GnarlingFortification { .with_z(alt + raise + height_1 as i32 + 7), }) .intersect(roof1) - .fill(red.clone()); + .fill(red); painter .prim(Primitive::cylinder(floor2_pos, rad_2 - 1.0, height_2)) .fill(Fill::Block(Block::empty())); @@ -1167,8 +1167,8 @@ impl Structure for GnarlingFortification { let roof = low1.union(low2).union(top1).union(top2); let roofmoss = roof.translate(Vec3::new(0, 0, 1)).without(top).without(low); top.fill(darkwood.clone()); - low.fill(midwood.clone()); - roofmoss.fill(moss.clone()); + low.fill(midwood); + roofmoss.fill(moss); painter .prim(Primitive::sphere( Vec2::new(wpos.x + randy - 5, wpos.y + randz - 5) @@ -1331,7 +1331,7 @@ impl Structure for GnarlingFortification { min: Vec2::new(wpos.x + 1, wpos.y - 1).with_z(alt + 8), max: Vec2::new(wpos.x + 8, wpos.y).with_z(alt + 38), }); - flag.fill(red.clone()); + flag.fill(red); //add green streaks let streak1 = painter .line( @@ -1404,7 +1404,7 @@ impl Structure for GnarlingFortification { 0.9, ); let flagpole = column.union(arm); - flagpole.fill(darkwood.clone()); + flagpole.fill(darkwood); }, GnarlingStructure::WatchTower => { let platform_1_height = 14;