diff --git a/assets/common/abilities/custom/harvester/firebreath.ron b/assets/common/abilities/custom/harvester/firebreath.ron index e63e8b0dbb..8ad0d9c9a9 100644 --- a/assets/common/abilities/custom/harvester/firebreath.ron +++ b/assets/common/abilities/custom/harvester/firebreath.ron @@ -14,6 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - ori_rate: 0.3, + ori_rate: 0.4, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/mandragora/basic.ron b/assets/common/abilities/custom/mandragora/basic.ron index c1b067bfe1..6f32af9706 100644 --- a/assets/common/abilities/custom/mandragora/basic.ron +++ b/assets/common/abilities/custom/mandragora/basic.ron @@ -7,7 +7,7 @@ BasicMelee( melee_constructor: ( kind: Bash( damage: 8, - poise: 5, + poise: 10, knockback: 0, energy_regen: 0, ), diff --git a/assets/common/abilities/custom/mandragora/scream.ron b/assets/common/abilities/custom/mandragora/scream.ron index 94a1059f6e..4429282e43 100644 --- a/assets/common/abilities/custom/mandragora/scream.ron +++ b/assets/common/abilities/custom/mandragora/scream.ron @@ -7,7 +7,7 @@ BasicMelee( melee_constructor: ( kind: SonicWave( damage: 10, - poise: 35, + poise: 75, knockback: 20, energy_regen: 0, ), diff --git a/assets/common/items/armor/misc/head/gnarling_mask.ron b/assets/common/items/armor/misc/head/gnarling_mask.ron index f6d1318b46..00b89d2d18 100644 --- a/assets/common/items/armor/misc/head/gnarling_mask.ron +++ b/assets/common/items/armor/misc/head/gnarling_mask.ron @@ -6,10 +6,10 @@ ItemDef( stats: Direct(( protection: Some(Normal(3.0)), poise_resilience: Some(Normal(1.0)), - energy_max: Some(14.0), + energy_max: Some(6.0), )), )), - quality: High, + quality: Moderate, tags: [ Gnarling, SalvageInto(Lifecloth, 1), diff --git a/assets/common/items/glider/moth.ron b/assets/common/items/glider/moth.ron index 01f245e441..38c76875ce 100644 --- a/assets/common/items/glider/moth.ron +++ b/assets/common/items/glider/moth.ron @@ -2,6 +2,6 @@ ItemDef( legacy_name: "Green Luna", legacy_description: "The delicate wings flutter faintly.", kind: Glider, - quality: High, + quality: Moderate, tags: [], ) diff --git a/assets/common/loot_tables/dungeon/gnarling/chieftain.ron b/assets/common/loot_tables/dungeon/gnarling/chieftain.ron index 188672b2f0..1aece61ebc 100644 --- a/assets/common/loot_tables/dungeon/gnarling/chieftain.ron +++ b/assets/common/loot_tables/dungeon/gnarling/chieftain.ron @@ -1,18 +1,19 @@ [ (1, All([ - MultiDrop(Item("common.items.mineral.ore.veloritefrag"), 4, 6), Lottery([ - (1.0, LootTable("common.loot_tables.armor.tier-1")), - (1.0, LootTable("common.loot_tables.weapons.tier-1")), - ]), - Lottery([ - (1.0, LootTable("common.loot_tables.armor.tier-0")), - (1.0, LootTable("common.loot_tables.weapons.tier-0")), + (1.0, All([ + LootTable("common.loot_tables.armor.tier-0"), + LootTable("common.loot_tables.weapons.tier-1"), + ])), + (1.0, All([ + LootTable("common.loot_tables.weapons.tier-0"), + LootTable("common.loot_tables.armor.tier-1"), + ])), ]), Lottery([ (3.0, Item("common.items.armor.misc.neck.scratched")), - (1.0, Item("common.items.armor.misc.head.wanderers_hat")), (1.0, Item("common.items.armor.misc.head.gnarling_mask")), + (1.0, Item("common.items.glider.moth")), ]), ])), ] \ No newline at end of file diff --git a/assets/common/loot_tables/dungeon/gnarling/harvester.ron b/assets/common/loot_tables/dungeon/gnarling/harvester.ron index 4bc487abe4..5e2eba3efa 100644 --- a/assets/common/loot_tables/dungeon/gnarling/harvester.ron +++ b/assets/common/loot_tables/dungeon/gnarling/harvester.ron @@ -1,18 +1,19 @@ [ (1, All([ - MultiDrop(Item("common.items.mineral.ore.velorite"), 2, 3), Lottery([ - (1.0, LootTable("common.loot_tables.armor.tier-2")), - (1.0, LootTable("common.loot_tables.weapons.tier-2")), - ]), - Lottery([ - (1.0, LootTable("common.loot_tables.armor.tier-1")), - (1.0, LootTable("common.loot_tables.weapons.tier-1")), + (1.0, All([ + LootTable("common.loot_tables.armor.tier-1"), + LootTable("common.loot_tables.weapons.tier-2"), + ])), + (1.0, All([ + LootTable("common.loot_tables.weapons.tier-1"), + LootTable("common.loot_tables.armor.tier-2"), + ])), ]), Lottery([ (3.0, Nothing), (1.0, Item("common.items.lantern.pumpkin")), - (1.0, Item("common.items.glider.moth")), + (1.0, Item("common.items.armor.misc.head.wanderers_hat")), ]), ])), ] \ No newline at end of file diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 649f424f01..d9b0ddb3cc 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -367,6 +367,7 @@ impl<'a> From<&'a Body> for Psyche { }, Body::BipedSmall(biped_small) => match biped_small.species { biped_small::Species::Gnarling => 0.2, + biped_small::Species::Mandragora => 0.1, biped_small::Species::Adlet => 0.2, biped_small::Species::Haniwa => 0.1, biped_small::Species::Sahagin => 0.1, diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 05d17cc887..6d193e31f5 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -971,6 +971,7 @@ impl Body { Body::BipedSmall(biped_small) => match biped_small.species { biped_small::Species::Gnarling => 50, biped_small::Species::GnarlingChieftain => 150, + biped_small::Species::Mandragora => 65, biped_small::Species::Adlet => 65, biped_small::Species::Sahagin => 85, biped_small::Species::Haniwa => 100, @@ -1223,7 +1224,6 @@ impl Body { biped_large::Species::Minotaur => 4.05, biped_large::Species::Tidalwarrior => 2.75, biped_large::Species::Yeti => 2.25, - biped_large::Species::Harvester => 2.1, _ => 1.0, }, Body::BipedSmall(b) => match b.species { diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index 95305fa07e..f945ed4299 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -213,7 +213,7 @@ impl<'a> System<'a> for Sys { entity, buff_change: BuffChange::Add(Buff::new( BuffKind::Ensnared, - BuffData::new(0.5, Some(Secs(1.0))), + BuffData::new(0.5, Some(Secs(0.1))), Vec::new(), BuffSource::World, *read_data.time, diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 318931d739..b5f56e2ee0 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -4769,7 +4769,7 @@ impl<'a> AgentData<'a> { const FIREBREATH_TIME: f32 = 4.0; const FIREBREATH_SHORT_TIME: f32 = 2.5; // cutoff sooner at close range const FIREBREATH_COOLDOWN: f32 = 3.0; - const CLOSE_MIXUP_COOLDOWN: f32 = 5.0; // variation in attacks at close range + const CLOSE_MIXUP_COOLDOWN: f32 = 2.5; // variation in attacks at close range const FAR_PUMPKIN_COOLDOWN: f32 = 1.0; // allows for pathing to player between throws // conditions @@ -4893,36 +4893,35 @@ impl<'a> AgentData<'a> { // vine summoning let health_fraction = self.health.map_or(0.5, |h| h.fraction()); - if (health_fraction < FIRST_VINE_CREATION_THRESHOLD && !conditions!(HasSummonedFirstVines)) - || (health_fraction < SECOND_VINE_CREATION_THRESHOLD - && !conditions!(HasSummonedSecondVines)) + if health_fraction < SECOND_VINE_CREATION_THRESHOLD && !conditions!(HasSummonedSecondVines) { - if health_fraction < SECOND_VINE_CREATION_THRESHOLD { - use_second_vines!(); - if is_in_vines_recovery!() { - conditions!(HasSummonedSecondVines) = true; - } - } else { - use_first_vines!(); - if is_in_vines_recovery!() { - conditions!(HasSummonedFirstVines) = true; - } + use_second_vines!(); + if is_in_vines_recovery!() { + conditions!(HasSummonedSecondVines) = true; + } + } else if health_fraction < FIRST_VINE_CREATION_THRESHOLD + && !conditions!(HasSummonedFirstVines) + { + use_first_vines!(); + if is_in_vines_recovery!() { + conditions!(HasSummonedFirstVines) = true; } } // close range else if attack_data.dist_sqrd < (attack_data.body_dist + 0.75 * MELEE_RANGE).powi(2) { if is_using_firebreath!(FIREBREATH_SHORT_TIME) { - use_fire_breath!() + use_fire_breath!(); } else if timers!(SinceCloseMixup) > CLOSE_MIXUP_COOLDOWN // for now, no line of sight check for consitency in attacks { if timers!(SinceFirebreath) < FIREBREATH_COOLDOWN { use_pumpkin!(); } else { - let randomise = rng.gen_range(1..=2); + let randomise = rng.gen_range(1..=3); match randomise { 1 => use_fire_breath!(), - _ => use_pumpkin!(), + 2 => use_pumpkin!(), + _ => use_scythe!(), } } } else if attack_data.angle < 60.0 { @@ -4932,9 +4931,9 @@ impl<'a> AgentData<'a> { // mid range (with line of sight) else if attack_data.dist_sqrd < FIREBREATH_RANGE.powi(2) && line_of_sight_with_target() { if is_using_firebreath!(FIREBREATH_TIME) { - use_fire_breath!() + use_fire_breath!(); } else if attack_data.angle < 30.0 && timers!(SinceFirebreath) > FIREBREATH_COOLDOWN { - use_fire_breath!() + use_fire_breath!(); } else if timers!(SinceCloseMixup) > CLOSE_MIXUP_COOLDOWN { use_pumpkin!(); } @@ -5800,7 +5799,7 @@ impl<'a> AgentData<'a> { tgt_data: &TargetData, read_data: &ReadData, ) { - const SCREAM_RANGE: f32 = 10.0; + const SCREAM_RANGE: f32 = 10.0; // hard-coded from scream.ron enum ActionStateFCounters { FCounterHealthThreshold = 0, diff --git a/world/src/site2/plot/gnarling.rs b/world/src/site2/plot/gnarling.rs index f321c219c1..7137df1d86 100644 --- a/world/src/site2/plot/gnarling.rs +++ b/world/src/site2/plot/gnarling.rs @@ -376,30 +376,96 @@ impl GnarlingFortification { if area.contains_point(pos.xy()) { match loc { GnarlingStructure::Hut => { - let num = dynamic_rng.gen_range(1..=3); + let num = dynamic_rng.gen_range(1..=2); for _ in 0..num { supplement.add_entity(random_gnarling(wpos, dynamic_rng)); } }, GnarlingStructure::VeloriteHut => { + const VELO_HEIGHT: i32 = 12; + const GROUND_HEIGHT: i32 = 8; let num = dynamic_rng.gen_range(1..=4); for _ in 0..num { supplement.add_entity(random_gnarling( - wpos.xy().with_z(wpos.z + 12), + wpos.xy().with_z(wpos.z + VELO_HEIGHT), dynamic_rng, )); } + if num < 3 { + // wooden golem (with oriented spawn) + let x_offset; + let y_offset; + match _ori { + Dir::X => { + x_offset = 8; + y_offset = 8; + }, + Dir::NegX => { + x_offset = -8; + y_offset = 8; + }, + Dir::Y => { + x_offset = 8; + y_offset = -8; + }, + Dir::NegY => { + x_offset = -8; + y_offset = -8; + }, + } + let pos = Vec3::new( + wpos.x + x_offset, + wpos.y + y_offset, + wpos.z + GROUND_HEIGHT, + ); + supplement.add_entity(wood_golem(pos, dynamic_rng)); + } }, GnarlingStructure::Banner => {}, GnarlingStructure::ChieftainHut => { - let pos = wpos.xy().with_z(wpos.z + 8); + // inside hut + const FLOOR_HEIGHT: i32 = 8; + let pos = wpos.xy().with_z(wpos.z + FLOOR_HEIGHT); supplement.add_entity(gnarling_chieftain(pos, dynamic_rng)); - for _ in 0..2 { - supplement.add_entity(wood_golem(pos, dynamic_rng)); - } - for _ in 0..6 { + for _ in 0..4 { supplement.add_entity(random_gnarling(pos, dynamic_rng)); } + // hut corner posts + const CORNER_HEIGHT: i32 = 10; + const CORNER_OFFSET: i32 = 18; + let height = wpos.z + CORNER_HEIGHT; + let plus_minus: [i32; 2] = [1, -1]; + for x in plus_minus { + for y in plus_minus { + let pos = Vec3::new( + wpos.x + x * CORNER_OFFSET, + wpos.y + y * CORNER_OFFSET, + height, + ); + supplement.add_entity(gnarling_stalker(pos, dynamic_rng)); + } + } + // hut sides on ground (using orientation) + const GROUND_HEIGHT: i32 = 4; + const GROUND_OFFSET: i32 = 24; + let height = wpos.z + GROUND_HEIGHT; + let x_or_y = match _ori { + Dir::X | Dir::NegX => true, + Dir::Y | Dir::NegY => false, + }; + for pm in plus_minus { + let mut pos_ori = + Vec3::new(wpos.x + pm * GROUND_OFFSET, wpos.y, height); + let mut pos_xori = + Vec3::new(wpos.x, wpos.y + pm * GROUND_OFFSET, height); + if x_or_y { + (pos_ori, pos_xori) = (pos_xori, pos_ori); + } + supplement.add_entity(wood_golem(pos_ori, dynamic_rng)); + for _ in 0..3 { + supplement.add_entity(random_gnarling(pos_xori, dynamic_rng)); + } + } }, GnarlingStructure::WatchTower => { supplement.add_entity(wood_golem(wpos, dynamic_rng));