diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index ec7fd52fd4..292f407df7 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -1040,6 +1040,7 @@ Simple(None, "common.abilities.custom.cursekeeper.summonshamanicspirit"), Simple(None, "common.abilities.custom.cursekeeper.summonjiangshi"), Simple(None, "common.abilities.custom.cursekeeper.teleport"), + Simple(None, "common.abilities.custom.cursekeeper.poisonbomb"), ], ), Custom("CursekeeperFake"): ( diff --git a/assets/common/abilities/custom/arthropods/blackwidow/poisonball.ron b/assets/common/abilities/custom/arthropods/blackwidow/poisonball.ron index 79d4043581..b4fd4a68c1 100644 --- a/assets/common/abilities/custom/arthropods/blackwidow/poisonball.ron +++ b/assets/common/abilities/custom/arthropods/blackwidow/poisonball.ron @@ -5,6 +5,7 @@ BasicRanged( projectile: Poisonball( damage: 58.0, radius: 3.5, + knockback: 1.0, energy_regen: 0, min_falloff: 0.2, ), diff --git a/assets/common/abilities/custom/cursekeeper/poisonbomb.ron b/assets/common/abilities/custom/cursekeeper/poisonbomb.ron new file mode 100644 index 0000000000..80e4db0c28 --- /dev/null +++ b/assets/common/abilities/custom/cursekeeper/poisonbomb.ron @@ -0,0 +1,18 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 0.3, + recover_duration: 0.3, + projectile: Poisonball( + damage: 32.0, + knockback: 10.0, + radius: 6.0, + energy_regen: 5.0, + min_falloff: 0.1, + ), + projectile_body: Object(SpitPoison), + projectile_light: None, + projectile_speed: 25.0, + num_projectiles: 2, + projectile_spread: 0.1, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/sea_bishop/longbeam.ron b/assets/common/abilities/custom/sea_bishop/longbeam.ron index 2e4cda981d..2eabc7c9dd 100644 --- a/assets/common/abilities/custom/sea_bishop/longbeam.ron +++ b/assets/common/abilities/custom/sea_bishop/longbeam.ron @@ -7,7 +7,7 @@ BasicBeam( range: 30.0, max_angle: 15.0, damage_effect: Some(Buff(( - kind: Burning, + kind: Wet, dur_secs: 3.0, strength: Value(0.2), chance: 0.1, diff --git a/assets/common/abilities/custom/wealdwyvern/poisonbomb.ron b/assets/common/abilities/custom/wealdwyvern/poisonbomb.ron index 40161e2bde..e2f74ea2fd 100644 --- a/assets/common/abilities/custom/wealdwyvern/poisonbomb.ron +++ b/assets/common/abilities/custom/wealdwyvern/poisonbomb.ron @@ -5,6 +5,7 @@ BasicRanged( projectile: Poisonball( damage: 32.0, radius: 5.0, + knockback: 10.0, energy_regen: 5.0, min_falloff: 0.1, ), diff --git a/assets/voxygen/voxel/object_manifest.ron b/assets/voxygen/voxel/object_manifest.ron index 51c01667fd..cb592c2cd2 100644 --- a/assets/voxygen/voxel/object_manifest.ron +++ b/assets/voxygen/voxel/object_manifest.ron @@ -1053,7 +1053,7 @@ ), TerracottaStatue: ( bone0: ( - offset: (-28.0, -28.0, -0.0), + offset: (-21.0, -19.0, -0.0), central: ("sprite.furniture.terracotta_statue_4"), ), bone1: ( diff --git a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox index e9fcf716b7..c30ff1d016 100644 --- a/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox +++ b/assets/voxygen/voxel/sprite/furniture/terracotta_statue_4.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f744f68a189601591021384cc3aca8096d2ddbcf3772fafc724d2ccec1c13d3 -size 166120 +oid sha256:78c8ed9ca42eea868969fdf16e09ba13e7574196f8639366f4dc3963eb375cd4 +size 129672 diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 71f449d380..c03f0c6c63 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -80,6 +80,7 @@ pub enum ProjectileConstructor { Poisonball { damage: f32, radius: f32, + knockback: f32, min_falloff: f32, }, NecroticSphere { @@ -400,8 +401,18 @@ impl ProjectileConstructor { Poisonball { damage, radius, + knockback, min_falloff, } => { + let knockback = AttackEffect::new( + Some(GroupTarget::OutOfGroup), + CombatEffect::Knockback(Knockback { + strength: knockback, + direction: KnockbackDir::Away, + }) + .adjusted_by_stats(tool_stats), + ) + .with_requirement(CombatRequirement::AnyDamage); let buff = AttackEffect::new( Some(GroupTarget::OutOfGroup), CombatEffect::Buff(CombatBuff { @@ -425,6 +436,7 @@ impl ProjectileConstructor { let attack = Attack::default() .with_damage(damage) .with_precision(precision_mult) + .with_effect(knockback) .with_effect(buff); let explosion = Explosion { effects: vec![ diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index 9eafd13111..be883bc0b6 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -432,7 +432,7 @@ impl SpriteKind { SpriteKind::HaniwaUrn => 1.09, SpriteKind::TerracottaChest => 1.09, SpriteKind::TerracottaStatue => 5.29, - SpriteKind::TerracottaBlock => 1.09, + SpriteKind::TerracottaBlock => 1.00, SpriteKind::SeaDecorChain => 1.09, SpriteKind::SeaDecorBlock => 1.00, SpriteKind::SeaDecorWindowHor => 0.55, diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 79201e785b..8f1fc8d17d 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -1587,9 +1587,14 @@ impl<'a> AgentData<'a> { read_data, rng, ), - Tactic::Cursekeeper => { - self.handle_cursekeeper_attack(agent, controller, tgt_data, read_data, rng) - }, + Tactic::Cursekeeper => self.handle_cursekeeper_attack( + agent, + controller, + &attack_data, + tgt_data, + read_data, + rng, + ), Tactic::CursekeeperFake => { self.handle_cursekeeper_fake_attack(agent, controller, &attack_data) }, diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 1644b1c096..7a68113491 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -4813,6 +4813,7 @@ impl<'a> AgentData<'a> { &self, agent: &mut Agent, controller: &mut Controller, + attack_data: &AttackData, tgt_data: &TargetData, read_data: &ReadData, rng: &mut impl Rng, @@ -4844,7 +4845,7 @@ impl<'a> AgentData<'a> { .copied(), select_pos: None, }); - } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] > 10.0 { + } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] > 12.0 { agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] = 0.0; } else { agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] += read_data.dt.0; @@ -4860,7 +4861,7 @@ impl<'a> AgentData<'a> { } if line_of_sight_with_target() { - if agent.combat_state.timers[ActionStateTimers::TimerSummon as usize] > 45.0 { + if agent.combat_state.timers[ActionStateTimers::TimerSummon as usize] > 32.0 { match agent.combat_state.timers[ActionStateTimers::SelectSummon as usize] as i32 { 0 => controller.push_basic_input(InputKind::Ability(0)), 1 => controller.push_basic_input(InputKind::Ability(1)), @@ -4869,19 +4870,23 @@ impl<'a> AgentData<'a> { _ => controller.push_basic_input(InputKind::Ability(4)), } } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] < 6.0 { + controller.push_basic_input(InputKind::Ability(6)); + } else if agent.combat_state.timers[ActionStateTimers::TimerBeam as usize] < 9.0 { controller.push_basic_input(InputKind::Primary); } else { controller.push_basic_input(InputKind::Secondary); } } - self.path_toward_target( - agent, - controller, - tgt_data.pos.0, - read_data, - Path::Partial, - None, - ); + if attack_data.dist_sqrd > 10_f32.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Full, + None, + ); + } } pub fn handle_shamanic_spirit_attack( @@ -4926,7 +4931,7 @@ impl<'a> AgentData<'a> { enum Conditions { AttackToggle = 0, } - if attack_data.dist_sqrd < 15_f32.powi(2) { + if attack_data.dist_sqrd < 25_f32.powi(2) { if !agent.combat_state.conditions[Conditions::AttackToggle as usize] { controller.push_basic_input(InputKind::Primary); if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover)) diff --git a/world/src/site2/plot/terracotta_palace.rs b/world/src/site2/plot/terracotta_palace.rs index 3277eaa7dc..f014e26d97 100644 --- a/world/src/site2/plot/terracotta_palace.rs +++ b/world/src/site2/plot/terracotta_palace.rs @@ -617,14 +617,13 @@ impl Structure for TerracottaPalace { // chamber rooms for dir in CARDINALS { let room_center = center + dir * ((room_size / 2) + 8); - // floor decor in chamber rooms painter .cylinder(Aabb { - min: (room_center - 3).with_z(base - 24 - (room_size / 2) - (room_size / 16)), + min: (room_center - 3).with_z(base - 30 - (room_size / 2) - (room_size / 16)), max: (room_center + 3).with_z(base - 6 - (room_size / 2) - (room_size / 16)), }) .clear(); - // npcs in chamber rooms + // cursekeeper in chamber rooms let npc_pos = room_center.with_z(base - 24 - (room_size / 2) - (room_size / 16)); let npc = chamber_npcs .swap_remove(RandomField::new(0).get(npc_pos) as usize % chamber_npcs.len()); @@ -634,7 +633,7 @@ impl Structure for TerracottaPalace { // chamber_1 painter .aabb(Aabb { - min: Vec2::new(center.x - (room_size / 2), center.y - 5) + min: Vec2::new(center.x - (room_size / 2), center.y - 4) .with_z(base - 10 - (room_size / 2)), max: Vec2::new(center.x - (room_size / 2) + 1, center.y + 5) .with_z(base - 10 - (room_size / 2) + 5), @@ -651,7 +650,7 @@ impl Structure for TerracottaPalace { // chamber_2 painter .aabb(Aabb { - min: Vec2::new(center.x + (room_size / 2) - 1, center.y - 5) + min: Vec2::new(center.x + (room_size / 2) - 1, center.y - 4) .with_z(base - 10 - (room_size / 2)), max: Vec2::new(center.x + (room_size / 2), center.y + 5) .with_z(base - 10 - (room_size / 2) + 5), @@ -668,7 +667,7 @@ impl Structure for TerracottaPalace { // chamber_3 painter .aabb(Aabb { - min: Vec2::new(center.x - 5, center.y - (room_size / 2)) + min: Vec2::new(center.x - 4, center.y - (room_size / 2)) .with_z(base - 10 - (room_size / 2)), max: Vec2::new(center.x + 5, center.y - (room_size / 2) + 1) .with_z(base - 10 - (room_size / 2) + 5), @@ -685,7 +684,7 @@ impl Structure for TerracottaPalace { // chamber_4 painter .aabb(Aabb { - min: Vec2::new(center.x - 5, center.y + (room_size / 2) - 1) + min: Vec2::new(center.x - 4, center.y + (room_size / 2) - 1) .with_z(base - 10 - (room_size / 2)), max: Vec2::new(center.x + 5, center.y + (room_size / 2)) .with_z(base - 10 - (room_size / 2) + 5), @@ -880,7 +879,6 @@ impl Structure for TerracottaPalace { spawn_random_entity(pillar_npc_pos, painter, 1..=1); - // npcs in upper chamber rooms let statue = statue_npcs .swap_remove(RandomField::new(0).get(statue_pos) as usize % statue_npcs.len()); painter.spawn( @@ -1031,7 +1029,7 @@ impl Structure for TerracottaPalace { } } // npcs on top floor - let npcs = 3.0_f32; + let npcs = 5.0_f32; let radius_npcs = (room_size / 4) + 6; let phi_npcs = TAU / npcs; for n in 1..=npcs as i32 { @@ -1050,7 +1048,7 @@ impl Structure for TerracottaPalace { // main room npcs let radius_npcs_main = (room_size / 4) + 10; - let npcs_main = 10.0_f32; + let npcs_main = 15.0_f32; let phi_npcs_main = TAU / npcs_main; for n in 1..=npcs_main as i32 { let pos = Vec2::new(