diff --git a/CHANGELOG.md b/CHANGELOG.md index c76b124f27..cec261f3bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added reworked Cultist Dungeon - Petting animals tamed by you or someone else! - Updated furniture sprites. - Added Abyssal rings diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 14eb72198b..f6c8edf177 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -477,6 +477,13 @@ secondary: Simple(None, "common.abilities.custom.quadmedbasic.triplestrike"), abilities: [], ), + Custom("Darkhound"): ( + primary: Simple(None, "common.abilities.custom.darkhound.leap"), + secondary: Simple(None, "common.abilities.custom.darkhound.doublestrike"), + abilities: [ + Simple(None, "common.abilities.custom.darkhound.quickleap"), + ], + ), Custom("Frostfang"): ( primary: Simple(None, "common.abilities.custom.frostfang.singlestrike"), secondary: Simple(None, "common.abilities.custom.frostfang.triplestrike"), @@ -1124,4 +1131,24 @@ secondary: Simple(None, "common.abilities.custom.jiangshi.teleport"), abilities: [], ), + Custom("BipedLargeCultistStaff"): ( + primary: Simple(None, "common.abilities.custom.biped_large_cultist.staff.firebomb"), + secondary: Simple(None, "common.abilities.custom.biped_large_cultist.staff.flamethrower"), + abilities: [], + ), + Custom("BipedLargeCultistSword"): ( + primary: Simple(None, "common.abilities.custom.biped_large_cultist.sword.doublestrike"), + secondary: Simple(None, "common.abilities.custom.biped_large_cultist.sword.dash"), + abilities: [], + ), + Custom("BipedLargeCultistHammer"): ( + primary: Simple(None, "common.abilities.custom.biped_large_cultist.hammer.doublestrike"), + secondary: Simple(None, "common.abilities.custom.biped_large_cultist.hammer.doublestrike"), + abilities: [], + ), + Custom("BipedLargeCultistBow"): ( + primary: Simple(None, "common.abilities.custom.biped_large_cultist.bow.basic"), + secondary: Simple(None, "common.abilities.custom.biped_large_cultist.bow.basic"), + abilities: [], + ), }) diff --git a/assets/common/abilities/custom/biped_large_cultist/bow/basic.ron b/assets/common/abilities/custom/biped_large_cultist/bow/basic.ron new file mode 100644 index 0000000000..19b16b56e7 --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/bow/basic.ron @@ -0,0 +1,16 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 0.9, + recover_duration: 0.3, + projectile: Arrow( + damage: 12.0, + knockback: 5.0, + energy_regen: 4.0, + ), + projectile_body: Object(Arrow), + projectile_light: None, + projectile_speed: 100.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/biped_large_cultist/hammer/doublestrike.ron b/assets/common/abilities/custom/biped_large_cultist/hammer/doublestrike.ron new file mode 100644 index 0000000000..fd5cdaa956 --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/hammer/doublestrike.ron @@ -0,0 +1,45 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 16, + poise: 40, + knockback: 4, + energy_regen: 0, + ), + range: 4.5, + angle: 50.0, + ), + buildup_duration: 1.0, + swing_duration: 0.28, + hit_timing: 0.5, + recover_duration: 1.0, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 0.65, + ), + ( + melee_constructor: ( + kind: Bash( + damage: 32, + poise: 40, + knockback: 16, + energy_regen: 0, + ), + range: 2.5, + angle: 30.0, + ), + buildup_duration: 0.6, + swing_duration: 0.25, + hit_timing: 0.5, + recover_duration: 1.2, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 0.65, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/biped_large_cultist/staff/firebomb.ron b/assets/common/abilities/custom/biped_large_cultist/staff/firebomb.ron new file mode 100644 index 0000000000..3e42c85c8e --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/staff/firebomb.ron @@ -0,0 +1,20 @@ +BasicRanged( + energy_cost: 0, + buildup_duration: 1.0, + recover_duration: 1.35, + projectile: Fireball( + damage: 15.0, + radius: 5.0, + energy_regen: 5.0, + min_falloff: 0.5, + ), + projectile_body: Object(BoltFire), + /*projectile_light: Some(LightEmitter { + col: (1.0, 0.75, 0.11).into(), + ..Default::default() + }),*/ + projectile_speed: 60.0, + num_projectiles: 1, + projectile_spread: 0.0, + move_efficiency: 0.3, +) diff --git a/assets/common/abilities/custom/biped_large_cultist/staff/flamethrower.ron b/assets/common/abilities/custom/biped_large_cultist/staff/flamethrower.ron new file mode 100644 index 0000000000..3762d8c722 --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/staff/flamethrower.ron @@ -0,0 +1,19 @@ +BasicBeam( + buildup_duration: 0.5, + recover_duration: 0.5, + beam_duration: 1.0, + damage: 3.5, + tick_rate: 3.0, + range: 20.0, + max_angle: 15.0, + damage_effect: Some(Buff(( + kind: Burning, + dur_secs: 10.0, + strength: DamageFraction(0.5), + chance: 0.25, + ))), + energy_regen: 0, + energy_drain: 35.0, + ori_rate: 0.3, + specifier: Flamethrower, +) diff --git a/assets/common/abilities/custom/biped_large_cultist/sword/dash.ron b/assets/common/abilities/custom/biped_large_cultist/sword/dash.ron new file mode 100644 index 0000000000..b8ef89c258 --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/sword/dash.ron @@ -0,0 +1,28 @@ +DashMelee( + energy_cost: 10.0, + melee_constructor: ( + kind: Stab( + damage: 9.0, + poise: 40.0, + knockback: 8.0, + energy_regen: 0.0, + ), + scaled: Some(( + kind: Stab( + damage: 16.0, + poise: 0.0, + knockback: 7.0, + energy_regen: 0.0, + ))), + range: 5.0, + angle: 45.0, + ), + energy_drain: 0, + forward_speed: 4.0, + buildup_duration: 0.6, + charge_duration: 1.2, + swing_duration: 0.1, + recover_duration: 0.9, + ori_modifier: 0.3, + auto_charge: false, +) diff --git a/assets/common/abilities/custom/biped_large_cultist/sword/doublestrike.ron b/assets/common/abilities/custom/biped_large_cultist/sword/doublestrike.ron new file mode 100644 index 0000000000..b7dbc3bb98 --- /dev/null +++ b/assets/common/abilities/custom/biped_large_cultist/sword/doublestrike.ron @@ -0,0 +1,57 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Slash( + damage: 16, + poise: 15, + knockback: 8, + energy_regen: 0, + ), + range: 3.5, + angle: 50.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 0.8, + swing_duration: 0.18, + hit_timing: 0.5, + recover_duration: 0.9, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 0.7, + ), + ( + melee_constructor: ( + kind: Slash( + damage: 32, + poise: 20, + knockback: 12, + energy_regen: 0, + ), + range: 3.5, + angle: 30.0, + damage_effect: Some(Buff(( + kind: Bleeding, + dur_secs: 10.0, + strength: DamageFraction(0.1), + chance: 0.1, + ))), + ), + buildup_duration: 0.7, + swing_duration: 0.1, + hit_timing: 0.5, + recover_duration: 0.7, + movement: ( + swing: Some(Forward(0.5)), + ), + ori_modifier: 0.7, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/darkhound/doublestrike.ron b/assets/common/abilities/custom/darkhound/doublestrike.ron new file mode 100644 index 0000000000..ecd0aeea02 --- /dev/null +++ b/assets/common/abilities/custom/darkhound/doublestrike.ron @@ -0,0 +1,45 @@ +ComboMelee2( + strikes: [ + ( + melee_constructor: ( + kind: Bash( + damage: 16, + poise: 15, + knockback: 4, + energy_regen: 0, + ), + range: 2.2, + angle: 30.0, + ), + buildup_duration: 0.7, + swing_duration: 0.5, + hit_timing: 0.5, + recover_duration: 0.6, + movement: ( + swing: Some(Forward(0.2)), + ), + ori_modifier: 0.8, + ), + ( + melee_constructor: ( + kind: Bash( + damage: 16, + poise: 15, + knockback: 4, + energy_regen: 0, + ), + range: 2.2, + angle: 30.0, + ), + buildup_duration: 0.85, + swing_duration: 0.45, + hit_timing: 0.5, + recover_duration: 0.6, + movement: ( + swing: Some(Forward(0.4)), + ), + ori_modifier: 0.8, + ), + ], + energy_cost_per_strike: 0, +) diff --git a/assets/common/abilities/custom/darkhound/leap.ron b/assets/common/abilities/custom/darkhound/leap.ron new file mode 100644 index 0000000000..39104d791d --- /dev/null +++ b/assets/common/abilities/custom/darkhound/leap.ron @@ -0,0 +1,21 @@ +LeapMelee( + energy_cost: 0, + buildup_duration: 0.95, + movement_duration: 0.8, + swing_duration: 0.55, + recover_duration: 0.4, + melee_constructor: ( + kind: Bash( + damage: 36.0, + poise: 30.0, + knockback: 4.0, + energy_regen: 0.0, + ), + range: 6.75, + angle: 180.0, + multi_target: Some(Normal), + ), + forward_leap_strength: 45.0, + vertical_leap_strength: 10.0, + specifier: None, +) diff --git a/assets/common/abilities/custom/darkhound/quickleap.ron b/assets/common/abilities/custom/darkhound/quickleap.ron new file mode 100644 index 0000000000..049ecba96f --- /dev/null +++ b/assets/common/abilities/custom/darkhound/quickleap.ron @@ -0,0 +1,21 @@ +LeapMelee( + energy_cost: 0, + buildup_duration: 0.5, + movement_duration: 0.6, + swing_duration: 0.3, + recover_duration: 0.25, + melee_constructor: ( + kind: Bash( + damage: 16.0, + poise: 15.0, + knockback: 2.0, + energy_regen: 0.0, + ), + range: 4.5, + angle: 180.0, + multi_target: Some(Normal), + ), + forward_leap_strength: 20.0, + vertical_leap_strength: 5.0, + specifier: None, +) diff --git a/assets/common/abilities/custom/husk/singlestrike.ron b/assets/common/abilities/custom/husk/singlestrike.ron index da3ed62acf..fae57da95a 100644 --- a/assets/common/abilities/custom/husk/singlestrike.ron +++ b/assets/common/abilities/custom/husk/singlestrike.ron @@ -11,8 +11,8 @@ ComboMelee2( range: 2.5, angle: 60.0, ), - buildup_duration: 0.5, - swing_duration: 0.07, + buildup_duration: 1.2, + swing_duration: 0.27, hit_timing: 0.5, recover_duration: 0.5, movement: ( diff --git a/assets/common/abilities/custom/mindflayer/cursedflames.ron b/assets/common/abilities/custom/mindflayer/cursedflames.ron index 3a22d090ef..5bd27d6259 100644 --- a/assets/common/abilities/custom/mindflayer/cursedflames.ron +++ b/assets/common/abilities/custom/mindflayer/cursedflames.ron @@ -1,8 +1,8 @@ BasicBeam( - buildup_duration: 0.3, + buildup_duration: 0.9, recover_duration: 1.0, beam_duration: 1.0, - damage: 20.0, + damage: 12.0, tick_rate: 5.0, range: 22.0, max_angle: 15.0, diff --git a/assets/common/abilities/custom/mindflayer/necroticvortex.ron b/assets/common/abilities/custom/mindflayer/necroticvortex.ron index 40fd009054..1e28df280a 100644 --- a/assets/common/abilities/custom/mindflayer/necroticvortex.ron +++ b/assets/common/abilities/custom/mindflayer/necroticvortex.ron @@ -1,5 +1,5 @@ RapidMelee( - buildup_duration: 1.2, + buildup_duration: 1.8, swing_duration: 0.5, recover_duration: 1.2, melee_constructor: ( diff --git a/assets/common/item_i18n_manifest.ron b/assets/common/item_i18n_manifest.ron index 282dc97b4b..aca402d449 100644 --- a/assets/common/item_i18n_manifest.ron +++ b/assets/common/item_i18n_manifest.ron @@ -2673,6 +2673,9 @@ Simple( "common.items.npc_weapons.unique.quadsmallbasic", ): "common-items-npc_weapons-unique-quadsmallbasic", + Simple( + "common.items.npc_weapons.unique.darkhound", + ): "common-items-npc_weapons-unique-darkhound", Simple( "common.items.npc_weapons.unique.roshwalr", ): "common-items-npc_weapons-unique-roshwalr", diff --git a/assets/common/items/npc_weapons/bow/bipedlarge-velorite.ron b/assets/common/items/npc_weapons/bow/bipedlarge-velorite.ron index 428a2dd7d6..59da457f0f 100644 --- a/assets/common/items/npc_weapons/bow/bipedlarge-velorite.ron +++ b/assets/common/items/npc_weapons/bow/bipedlarge-velorite.ron @@ -16,5 +16,5 @@ ItemDef( )), quality: Epic, tags: [], - ability_spec: Some(Custom("Bow Simple")), + ability_spec: Some(Custom("BipedLargeCultistBow")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/hammer/bipedlarge-cultist.ron b/assets/common/items/npc_weapons/hammer/bipedlarge-cultist.ron index 68145757f8..3a9b1ed3b3 100644 --- a/assets/common/items/npc_weapons/hammer/bipedlarge-cultist.ron +++ b/assets/common/items/npc_weapons/hammer/bipedlarge-cultist.ron @@ -16,5 +16,5 @@ ItemDef( )), quality: Epic, tags: [], - ability_spec: Some(Custom("Hammer Simple")), + ability_spec: Some(Custom("BipedLargeCultistHammer")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/staff/bipedlarge-cultist.ron b/assets/common/items/npc_weapons/staff/bipedlarge-cultist.ron index 1f8d6aefff..a20ab7eaa1 100644 --- a/assets/common/items/npc_weapons/staff/bipedlarge-cultist.ron +++ b/assets/common/items/npc_weapons/staff/bipedlarge-cultist.ron @@ -16,5 +16,5 @@ ItemDef( )), quality: Epic, tags: [], - ability_spec: Some(Custom("Staff Simple")), + ability_spec: Some(Custom("BipedLargeCultistStaff")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/sword/bipedlarge-cultist.ron b/assets/common/items/npc_weapons/sword/bipedlarge-cultist.ron index 87e1183979..cf97bd8ab0 100644 --- a/assets/common/items/npc_weapons/sword/bipedlarge-cultist.ron +++ b/assets/common/items/npc_weapons/sword/bipedlarge-cultist.ron @@ -16,5 +16,5 @@ ItemDef( )), quality: Epic, tags: [], - ability_spec: Some(Custom("Sword Simple")), + ability_spec: Some(Custom("BipedLargeCultistSword")), ) \ No newline at end of file diff --git a/assets/common/items/npc_weapons/unique/darkhound.ron b/assets/common/items/npc_weapons/unique/darkhound.ron new file mode 100644 index 0000000000..e75fdbde30 --- /dev/null +++ b/assets/common/items/npc_weapons/unique/darkhound.ron @@ -0,0 +1,20 @@ +ItemDef( + legacy_name: "Quad Med Jump", + legacy_description: "testing123", + kind: Tool(( + kind: Natural, + hands: Two, + stats: ( + equip_time_secs: 0.01, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Low, + tags: [], + ability_spec: Some(Custom("Darkhound")), +) \ No newline at end of file diff --git a/assets/voxygen/i18n/en/hud/map.ftl b/assets/voxygen/i18n/en/hud/map.ftl index 0cff829f3b..65b548ed48 100644 --- a/assets/voxygen/i18n/en/hud/map.ftl +++ b/assets/voxygen/i18n/en/hud/map.ftl @@ -36,5 +36,6 @@ hud-map-gnarling = Gnarling Fortification hud-map-chapel_site = Sea Chapel hud-map-adlet = Adlet Stronghold hud-map-haniwa = Haniwa Catacomb +hud-map-cultist = Cultist Dungeon hud-map-terracotta = Terracotta Ruins hud-map-placed_by = Placed by { $name } diff --git a/assets/voxygen/i18n/en/item/weapon/npc.ftl b/assets/voxygen/i18n/en/item/weapon/npc.ftl index 51f9379215..e61aa88a3c 100644 --- a/assets/voxygen/i18n/en/item/weapon/npc.ftl +++ b/assets/voxygen/i18n/en/item/weapon/npc.ftl @@ -280,6 +280,9 @@ common-items-npc_weapons-unique-quadmedquick = Quad Med Quick common-items-npc_weapons-unique-quadsmallbasic = Quad Small Basic .desc = testing123 +common-items-npc_weapons-unique-darkhound = Darkhound + .desc = testing123 + common-items-npc_weapons-unique-roshwalr = Roshwalr .desc = testing123 diff --git a/assets/world/dungeon/difficulty_distribution.ron b/assets/world/dungeon/difficulty_distribution.ron index 1969d17d35..d47161d8dd 100644 --- a/assets/world/dungeon/difficulty_distribution.ron +++ b/assets/world/dungeon/difficulty_distribution.ron @@ -18,5 +18,4 @@ ([ (2, 0.20), (4, 0.10), - (5, 0.10), ]) diff --git a/common/net/src/msg/world_msg.rs b/common/net/src/msg/world_msg.rs index 77985ddc76..6338e8723c 100644 --- a/common/net/src/msg/world_msg.rs +++ b/common/net/src/msg/world_msg.rs @@ -154,6 +154,7 @@ pub enum SiteKind { Adlet, Haniwa, DwarvenMine, + Cultist, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 42ca5bc7dd..af759b0994 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -798,6 +798,7 @@ impl Body { match self { Body::BipedLarge(biped_large) => match biped_large.species { biped_large::Species::Dullahan => 400, + biped_large::Species::Cultistwarlord | biped_large::Species::Cultistwarlock => 240, _ => 300, }, Body::BirdLarge(body) => match body.species { @@ -853,6 +854,7 @@ impl Body { // T1 quadruped_medium::Species::Alpaca => 55, quadruped_medium::Species::Antelope => 70, + quadruped_medium::Species::Darkhound => 80, quadruped_medium::Species::Camel => 100, quadruped_medium::Species::Cattle => 90, quadruped_medium::Species::Deer => 55, @@ -889,7 +891,6 @@ impl Body { quadruped_medium::Species::Ngoubou => 590, quadruped_medium::Species::Roshwalr => 640, quadruped_medium::Species::Tarasque => 370, - _ => 100, }, Body::FishMedium(fish_medium) => match fish_medium.species { // T2 @@ -943,7 +944,7 @@ impl Body { biped_large::Species::Mountaintroll => 240, biped_large::Species::Swamptroll => 240, biped_large::Species::Dullahan => 600, - biped_large::Species::Mindflayer => 1250, + biped_large::Species::Mindflayer => 2000, biped_large::Species::Tidalwarrior => 1600, biped_large::Species::Yeti => 1800, biped_large::Species::Minotaur => 3000, @@ -951,8 +952,8 @@ impl Body { biped_large::Species::Blueoni => 240, biped_large::Species::Redoni => 240, biped_large::Species::Huskbrute => 800, - biped_large::Species::Cultistwarlord => 250, - biped_large::Species::Cultistwarlock => 250, + biped_large::Species::Cultistwarlord => 200, + biped_large::Species::Cultistwarlock => 200, biped_large::Species::Gigasfrost => 30000, biped_large::Species::AdletElder => 1500, biped_large::Species::Tursus => 300, diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index caa919ac35..6cfdee57a7 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -599,11 +599,13 @@ fn default_main_tool(body: &Body) -> Item { )), quadruped_medium::Species::Saber | quadruped_medium::Species::Bonerattler - | quadruped_medium::Species::Darkhound | quadruped_medium::Species::Lion | quadruped_medium::Species::Snowleopard => Some(Item::new_from_asset_expect( "common.items.npc_weapons.unique.quadmedjump", )), + quadruped_medium::Species::Darkhound => Some(Item::new_from_asset_expect( + "common.items.npc_weapons.unique.darkhound", + )), // Below uniques still follow quadmedcharge just with stat alterations quadruped_medium::Species::Moose | quadruped_medium::Species::Tuskram => { Some(Item::new_from_asset_expect( diff --git a/common/src/terrain/site.rs b/common/src/terrain/site.rs index dbcbe999d2..bdbb9627da 100644 --- a/common/src/terrain/site.rs +++ b/common/src/terrain/site.rs @@ -18,6 +18,7 @@ pub enum DungeonKindMeta { Haniwa, SeaChapel, Terracotta, + Cultist, } #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] diff --git a/rtsim/src/gen/site.rs b/rtsim/src/gen/site.rs index 1e06d0e82f..d1a5094ed8 100644 --- a/rtsim/src/gen/site.rs +++ b/rtsim/src/gen/site.rs @@ -32,6 +32,7 @@ impl Site { | SiteKind::ChapelSite(_) | SiteKind::Terracotta(_) | SiteKind::Gnarling(_) + | SiteKind::Cultist(_) | SiteKind::PirateHideout(_) | SiteKind::JungleRuin(_) | SiteKind::RockCircle(_) diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 4ea590eb06..c46bd790de 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -1076,17 +1076,20 @@ impl<'a> AgentData<'a> { if let Some(ability_spec) = item.ability_spec() { match &*ability_spec { AbilitySpec::Custom(spec) => match spec.as_str() { - "Oni" | "Sword Simple" => Tactic::SwordSimple, - "Staff Simple" => Tactic::Staff, + "Oni" | "Sword Simple" | "BipedLargeCultistSword" => { + Tactic::SwordSimple + }, + "Staff Simple" | "BipedLargeCultistStaff" => Tactic::Staff, + "BipedLargeCultistHammer" => Tactic::Hammer, "Simple Flying Melee" => Tactic::SimpleFlyingMelee, - "Bow Simple" | "Boreal Bow" => Tactic::Bow, + "Bow Simple" | "Boreal Bow" | "BipedLargeCultistBow" => Tactic::Bow, "Stone Golem" | "Coral Golem" => Tactic::StoneGolem, "Iron Golem" => Tactic::IronGolem, "Quad Med Quick" => Tactic::CircleCharge { radius: 3, circle_time: 2, }, - "Quad Med Jump" => Tactic::QuadMedJump, + "Quad Med Jump" | "Darkhound" => Tactic::QuadMedJump, "Quad Med Charge" => Tactic::CircleCharge { radius: 6, circle_time: 1, diff --git a/voxygen/anim/src/biped_large/combomelee.rs b/voxygen/anim/src/biped_large/combomelee.rs index 32e0907075..ffb4663c15 100644 --- a/voxygen/anim/src/biped_large/combomelee.rs +++ b/voxygen/anim/src/biped_large/combomelee.rs @@ -114,7 +114,8 @@ impl Animation for ComboAnimation { }, Some( "common.abilities.custom.cyclops.doublestrike" - | "common.abilities.hammersimple.doublestrike", + | "common.abilities.hammersimple.doublestrike" + | "common.abilities.custom.biped_large_cultist.hammer.doublestrike", ) => { let speed = Vec2::::from(velocity).magnitude(); match strike { @@ -152,6 +153,7 @@ impl Animation for ComboAnimation { Some( "common.abilities.custom.dullahan.melee" | "common.abilities.swordsimple.doublestrike" + | "common.abilities.custom.biped_large_cultist.sword.doublestrike" | "common.abilities.custom.terracotta_pursuer.doublestrike" | "common.abilities.custom.terracotta_demolisher.triplestrike", ) => { diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 2af3932def..a3ecfb0f5e 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -585,6 +585,9 @@ image_ids! { mmap_site_haniwa: "voxygen.element.ui.map.buttons.haniwa", mmap_site_haniwa_hover: "voxygen.element.ui.map.buttons.haniwa_hover", mmap_site_haniwa_bg: "voxygen.element.ui.map.buttons.haniwa_bg", + mmap_site_cultist: "voxygen.element.ui.map.buttons.mindflayer", + mmap_site_cultist_hover: "voxygen.element.ui.map.buttons.mindflayer_hover", + mmap_site_cultist_bg: "voxygen.element.ui.map.buttons.mindflayer_bg", mmap_site_minotaur: "voxygen.element.ui.map.buttons.minotaur", mmap_site_minotaur_hover: "voxygen.element.ui.map.buttons.minotaur_hover", mmap_site_minotaur_bg: "voxygen.element.ui.map.buttons.minotaur_bg", diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 40699a45ca..6d4a0d4141 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -927,6 +927,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Bridge => i18n.get_msg("hud-map-bridge"), SiteKind::Adlet => i18n.get_msg("hud-map-adlet"), SiteKind::Haniwa => i18n.get_msg("hud-map-haniwa"), + SiteKind::Cultist => i18n.get_msg("hud-map-cultist"), SiteKind::DwarvenMine => i18n.get_msg("hud-map-df_mine"), }); let (difficulty, desc) = match &site.kind { @@ -957,6 +958,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Bridge => (None, i18n.get_msg("hud-map-bridge")), SiteKind::Adlet => (Some(1), i18n.get_msg("hud-map-adlet")), SiteKind::Haniwa => (Some(3), i18n.get_msg("hud-map-haniwa")), + SiteKind::Cultist => (Some(5), i18n.get_msg("hud-map-cultist")), SiteKind::DwarvenMine => (Some(5), i18n.get_msg("hud-map-df_mine")), }; let desc = desc.into_owned() + &get_site_economy(site_rich); @@ -970,6 +972,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Gnarling => self.imgs.mmap_site_gnarling, SiteKind::Adlet => self.imgs.mmap_site_adlet, SiteKind::Haniwa => self.imgs.mmap_site_haniwa, + SiteKind::Cultist => self.imgs.mmap_site_cultist, SiteKind::DwarvenMine => self.imgs.mmap_site_mine, SiteKind::Dungeon { difficulty } => match difficulty { 4 => self.imgs.mmap_site_minotaur, @@ -994,6 +997,7 @@ impl<'a> Widget for Map<'a> { SiteKind::Gnarling => self.imgs.mmap_site_gnarling_hover, SiteKind::Adlet => self.imgs.mmap_site_adlet_hover, SiteKind::Haniwa => self.imgs.mmap_site_haniwa_hover, + SiteKind::Cultist => self.imgs.mmap_site_cultist_hover, SiteKind::DwarvenMine => self.imgs.mmap_site_mine_hover, SiteKind::Dungeon { difficulty } => match difficulty { 4 => self.imgs.mmap_site_minotaur_hover, @@ -1015,6 +1019,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::Terracotta | SiteKind::Adlet | SiteKind::Haniwa + | SiteKind::Cultist | SiteKind::DwarvenMine => match difficulty { Some(0) => QUALITY_LOW, Some(1) => QUALITY_COMMON, @@ -1043,6 +1048,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::ChapelSite | SiteKind::DwarvenMine | SiteKind::Haniwa + | SiteKind::Cultist | SiteKind::Terracotta | SiteKind::Adlet => show_dungeons, SiteKind::Castle => show_castles, @@ -1105,6 +1111,7 @@ impl<'a> Widget for Map<'a> { | SiteKind::Gnarling | SiteKind::ChapelSite | SiteKind::Haniwa + | SiteKind::Cultist | SiteKind::Terracotta | SiteKind::Adlet => { if show_dungeons { diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index 2b300b01c1..d60f4da193 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -708,6 +708,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Bridge => None, SiteKind::Adlet => Some(1), SiteKind::Haniwa => Some(3), + SiteKind::Cultist => Some(5), SiteKind::DwarvenMine => Some(5), }; @@ -723,6 +724,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Bridge => self.imgs.mmap_site_bridge_bg, SiteKind::Adlet => self.imgs.mmap_site_adlet_bg, SiteKind::Haniwa => self.imgs.mmap_site_haniwa_bg, + SiteKind::Cultist => self.imgs.mmap_site_cultist_bg, SiteKind::DwarvenMine => self.imgs.mmap_site_mine_bg, }) .x_y_position_relative_to( @@ -753,6 +755,7 @@ impl<'a> Widget for MiniMap<'a> { SiteKind::Bridge => self.imgs.mmap_site_bridge, SiteKind::Adlet => self.imgs.mmap_site_adlet, SiteKind::Haniwa => self.imgs.mmap_site_haniwa, + SiteKind::Cultist => self.imgs.mmap_site_cultist, SiteKind::DwarvenMine => self.imgs.mmap_site_mine, }) .middle_of(state.ids.mmap_site_icons_bgs[i]) diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 8fe2943f87..d2b9236cc0 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -414,7 +414,17 @@ impl Civs { )?, SiteKind::DwarvenMine, ), - /*86..=97 => ( + 87..=92 => ( + find_site_loc( + &mut ctx, + &ProximityRequirementsBuilder::new() + .avoid_all_of(this.cultist_enemies(), 40) + .finalize(&world_dims), + &SiteKind::Cultist, + )?, + SiteKind::Cultist, + ), + /*97..=102 => ( find_site_loc( &mut ctx, &ProximityRequirementsBuilder::new() @@ -425,7 +435,7 @@ impl Civs { )?, SiteKind::Castle, ), - 98..=103 => (SiteKind::Citadel, (&castle_enemies, 20)), + 103..=108 => (SiteKind::Citadel, (&castle_enemies, 20)), */ _ => ( find_site_loc( @@ -480,6 +490,7 @@ impl Civs { SiteKind::TrollCave => (4i32, 1.5), SiteKind::Camp => (4i32, 1.5), SiteKind::DwarvenMine => (8i32, 3.0), + SiteKind::Cultist => (24i32, 10.0), }; let (raise, raise_dist, make_waypoint): (f32, i32, bool) = match &site.kind { @@ -663,6 +674,11 @@ impl Civs { &mut rng, wpos, )), + SiteKind::Cultist => WorldSite::cultist(site2::Site::generate_cultist( + &Land::from_sim(ctx.sim), + &mut rng, + wpos, + )), } }); sim_site.site_tmp = Some(site); @@ -1550,6 +1566,13 @@ impl Civs { }) } + fn cultist_enemies(&self) -> impl Iterator> + '_ { + self.sites().filter_map(|s| match s.kind { + SiteKind::Tree | SiteKind::GiantTree => None, + _ => Some(s.center), + }) + } + fn dungeon_enemies(&self) -> impl Iterator> + '_ { self.sites().filter_map(|s| match s.kind { SiteKind::Tree | SiteKind::GiantTree => None, @@ -1964,6 +1987,7 @@ pub enum SiteKind { Camp, DwarvenMine, JungleRuin, + Cultist, } impl SiteKind { @@ -2073,6 +2097,7 @@ impl SiteKind { && !chunk.river.near_water() && !chunk.near_cliffs() }, + SiteKind::Cultist => on_land() && chunk.temp < 0.5 && chunk.near_cliffs(), SiteKind::Castle => { if chunk.tree_density > 0.4 || chunk.river.near_water() || chunk.near_cliffs() { return false; diff --git a/world/src/lib.rs b/world/src/lib.rs index 1d0aa5270c..e03160ad67 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -216,6 +216,7 @@ impl World { civ::SiteKind::Terracotta => world_msg::SiteKind::Terracotta, civ::SiteKind::Citadel => world_msg::SiteKind::Castle, civ::SiteKind::Bridge(_, _) => world_msg::SiteKind::Bridge, + civ::SiteKind::Cultist => world_msg::SiteKind::Cultist, civ::SiteKind::Adlet => world_msg::SiteKind::Adlet, civ::SiteKind::Haniwa => world_msg::SiteKind::Haniwa, }, diff --git a/world/src/site/economy/context.rs b/world/src/site/economy/context.rs index 54a00bca45..c1cc5d051c 100644 --- a/world/src/site/economy/context.rs +++ b/world/src/site/economy/context.rs @@ -131,6 +131,7 @@ impl Environment { SiteKind::GiantTree(_) => (), SiteKind::Gnarling(_) => {}, SiteKind::Adlet(_) => {}, + SiteKind::Cultist(_) => {}, SiteKind::Haniwa(_) => {}, SiteKind::JungleRuin(_) => {}, SiteKind::ChapelSite(_) => {}, diff --git a/world/src/site/mod.rs b/world/src/site/mod.rs index 6fa028986b..822ba97902 100644 --- a/world/src/site/mod.rs +++ b/world/src/site/mod.rs @@ -84,6 +84,7 @@ pub enum SiteKind { RockCircle(site2::Site), TrollCave(site2::Site), Camp(site2::Site), + Cultist(site2::Site), } impl Site { @@ -206,6 +207,13 @@ impl Site { } } + pub fn cultist(cl: site2::Site) -> Self { + Self { + kind: SiteKind::Cultist(cl), + economy: Economy::default(), + } + } + pub fn dwarven_mine(dm: site2::Site) -> Self { Self { kind: SiteKind::DwarvenMine(dm), @@ -265,6 +273,7 @@ impl Site { SiteKind::Bridge(b) => b.radius(), SiteKind::Adlet(ad) => ad.radius(), SiteKind::Haniwa(ha) => ha.radius(), + SiteKind::Cultist(cl) => cl.radius(), } } @@ -292,6 +301,7 @@ impl Site { SiteKind::Bridge(b) => b.origin, SiteKind::Adlet(ad) => ad.origin, SiteKind::Haniwa(ha) => ha.origin, + SiteKind::Cultist(cl) => cl.origin, } } @@ -319,6 +329,7 @@ impl Site { SiteKind::Bridge(b) => b.spawn_rules(wpos), SiteKind::Adlet(ad) => ad.spawn_rules(wpos), SiteKind::Haniwa(ha) => ha.spawn_rules(wpos), + SiteKind::Cultist(cl) => cl.spawn_rules(wpos), } } @@ -346,6 +357,7 @@ impl Site { SiteKind::Bridge(b) => b.name(), SiteKind::Adlet(ad) => ad.name(), SiteKind::Haniwa(ha) => ha.name(), + SiteKind::Cultist(cl) => cl.name(), } } @@ -393,6 +405,7 @@ impl Site { SiteKind::Bridge(b) => b.render(canvas, dynamic_rng), SiteKind::Adlet(ad) => ad.render(canvas, dynamic_rng), SiteKind::Haniwa(ha) => ha.render(canvas, dynamic_rng), + SiteKind::Cultist(cl) => cl.render(canvas, dynamic_rng), } } @@ -434,6 +447,7 @@ impl Site { SiteKind::Bridge(b) => b.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::Adlet(ad) => ad.apply_supplement(dynamic_rng, wpos2d, supplement), SiteKind::Haniwa(ha) => ha.apply_supplement(dynamic_rng, wpos2d, supplement), + SiteKind::Cultist(cl) => cl.apply_supplement(dynamic_rng, wpos2d, supplement), } } @@ -475,6 +489,7 @@ impl Site { SiteKind::Bridge(site2) => Some(site2), SiteKind::Adlet(site2) => Some(site2), SiteKind::Haniwa(site2) => Some(site2), + SiteKind::Cultist(site2) => Some(site2), } } } diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 4cabaabc19..08b4998189 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -113,7 +113,8 @@ impl Site { PlotKind::TerracottaPalace(tp) => Some(tp.spawn_rules(wpos)), PlotKind::TerracottaHouse(th) => Some(th.spawn_rules(wpos)), PlotKind::TerracottaYard(ty) => Some(ty.spawn_rules(wpos)), - //PlotKind::DwarvenMine(m) => Some(m.spawn_rules(wpos)), + PlotKind::Cultist(cl) => Some(cl.spawn_rules(wpos)), + PlotKind::DwarvenMine(dm) => Some(dm.spawn_rules(wpos)), _ => None, }) .fold(base_spawn_rules, |a, b| a.combine(b)) @@ -1726,6 +1727,49 @@ impl Site { site } + pub fn generate_cultist(land: &Land, rng: &mut impl Rng, origin: Vec2) -> Self { + let mut rng = reseed(rng); + let mut site = Site { + origin, + + name: { + let name = NameGen::location(&mut rng).generate(); + match rng.gen_range(0..5) { + 0 => format!("{} Dungeon", name), + 1 => format!("{} Lair", name), + 2 => format!("{} Crib", name), + 3 => format!("{} Catacombs", name), + _ => format!("{} Pit", name), + } + }, + + //name: NameGen::location(&mut rng).generate_adlet(), + ..Site::default() + }; + let size = 22.0 as i32; + let aabr = Aabr { + min: Vec2::broadcast(-size), + max: Vec2::broadcast(size), + }; + { + let cultist = plot::Cultist::generate(land, &mut reseed(&mut rng), &site, aabr); + let cultist_alt = cultist.alt; + let plot = site.create_plot(Plot { + kind: PlotKind::Cultist(cultist), + root_tile: aabr.center(), + tiles: aabr_tiles(aabr).collect(), + seed: rng.gen(), + }); + + site.blit_aabr(aabr, Tile { + kind: TileKind::Building, + plot: Some(plot), + hard_alt: Some(cultist_alt), + }); + } + site + } + pub fn generate_bridge( land: &Land, index: IndexRef, @@ -2083,6 +2127,7 @@ impl Site { PlotKind::TerracottaYard(terracotta_yard) => { terracotta_yard.render_collect(self, canvas) }, + PlotKind::Cultist(cultist) => cultist.render_collect(self, canvas), PlotKind::DesertCityMultiPlot(desert_city_multi_plot) => { desert_city_multi_plot.render_collect(self, canvas) }, diff --git a/world/src/site2/plot.rs b/world/src/site2/plot.rs index d6f9cf7142..ed15109d63 100644 --- a/world/src/site2/plot.rs +++ b/world/src/site2/plot.rs @@ -7,6 +7,7 @@ mod citadel; mod cliff_tower; mod coastal_house; mod coastal_workshop; +mod cultist; mod desert_city_arena; mod desert_city_multiplot; mod desert_city_temple; @@ -33,7 +34,7 @@ mod workshop; pub use self::{ adlet::AdletStronghold, airship_dock::AirshipDock, bridge::Bridge, camp::Camp, castle::Castle, citadel::Citadel, cliff_tower::CliffTower, coastal_house::CoastalHouse, - coastal_workshop::CoastalWorkshop, desert_city_arena::DesertCityArena, + coastal_workshop::CoastalWorkshop, cultist::Cultist, desert_city_arena::DesertCityArena, desert_city_multiplot::DesertCityMultiPlot, desert_city_temple::DesertCityTemple, dungeon::Dungeon, dwarven_mine::DwarvenMine, giant_tree::GiantTree, gnarling::GnarlingFortification, haniwa::Haniwa, house::House, jungle_ruin::JungleRuin, @@ -94,6 +95,7 @@ pub enum PlotKind { JungleRuin(JungleRuin), Plaza, Castle(Castle), + Cultist(Cultist), Road(Path>), Dungeon(Dungeon), Gnarling(GnarlingFortification), diff --git a/world/src/site2/plot/cultist.rs b/world/src/site2/plot/cultist.rs new file mode 100644 index 0000000000..7db604fc78 --- /dev/null +++ b/world/src/site2/plot/cultist.rs @@ -0,0 +1,855 @@ +use super::*; +use crate::{ + site2::plot::dungeon::inscribed_polystar, + util::{sampler::Sampler, RandomField, DIAGONALS}, + Land, +}; +use common::{ + comp::misc::PortalData, + generation::{EntityInfo, SpecialEntity}, + resources::Secs, + terrain::SpriteKind, +}; +use rand::prelude::*; +use std::{f32::consts::TAU, sync::Arc}; +use vek::*; + +pub struct Room { + room_base: i32, + room_center: Vec2, + clear_center: Vec2, + mob_room: bool, + boss_room: bool, +} + +pub struct Cultist { + base: i32, + bounds: Aabr, + pub(crate) alt: i32, + pub(crate) center: Vec2, + pub(crate) room_data: Vec, + room_size: i32, + floors: i32, +} +impl Cultist { + pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr) -> Self { + let bounds = Aabr { + min: site.tile_wpos(tile_aabr.min), + max: site.tile_wpos(tile_aabr.max), + }; + let center = bounds.center(); + let base = land.get_alt_approx(center) as i32; + let room_size = 30; + let mut room_data = vec![]; + + let floors = 3; + for f in 0..=floors { + for s in 0..=1 { + // rooms + let rooms = [1, 2]; + if rooms.contains(&f) { + for dir in DIAGONALS { + let room_base = base - (f * (2 * (room_size))) - (s * room_size); + let room_center = center + (dir * ((room_size * 2) - 5 + (10 * s))); + let clear_center = center + (dir * ((room_size * 2) - 6 + (10 * s))); + let mob_room = s < 1; + room_data.push(Room { + room_base, + room_center, + clear_center, + mob_room, + boss_room: false, + }); + } + } + } + } + let boss_room_base = base - (6 * room_size); + room_data.push(Room { + room_base: boss_room_base, + room_center: center, + clear_center: center, + mob_room: false, + boss_room: true, + }); + + Self { + bounds, + alt: land.get_alt_approx(site.tile_center_wpos((tile_aabr.max - tile_aabr.min) / 2)) + as i32 + + 2, + base, + center, + room_size, + room_data, + floors, + } + } + + pub fn spawn_rules(&self, wpos: Vec2) -> SpawnRules { + SpawnRules { + waypoints: false, + trees: wpos.distance_squared(self.bounds.center()) > (75_i32).pow(2), + ..SpawnRules::default() + } + } +} + +impl Structure for Cultist { + #[cfg(feature = "use-dyn-lib")] + const UPDATE_FN: &'static [u8] = b"render_cultist\0"; + + #[cfg_attr(feature = "be-dyn-lib", export_name = "render_cultist")] + fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) { + let center = self.center; + let base = self.base; + let room_size = self.room_size; + let floors = self.floors; + let mut thread_rng = thread_rng(); + let candles_lite = Fill::Sampling(Arc::new(|wpos| { + Some(match (RandomField::new(0).get(wpos)) % 30 { + 0 => Block::air(SpriteKind::Candle), + _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + }) + })); + + let mut tower_positions = vec![]; + let mut clear_positions = vec![]; + let room_data = &self.room_data; + let mut star_positions = vec![]; + let mut sprite_positions = vec![]; + let mut random_npcs = vec![]; + + let rock_broken = Fill::Sampling(Arc::new(|center| { + Some(match (RandomField::new(0).get(center)) % 52 { + 0..=8 => Block::new(BlockKind::Rock, Rgb::new(60, 55, 65)), + 9..=17 => Block::new(BlockKind::Rock, Rgb::new(65, 60, 70)), + 18..=26 => Block::new(BlockKind::Rock, Rgb::new(70, 65, 75)), + 27..=35 => Block::new(BlockKind::Rock, Rgb::new(75, 70, 80)), + 36..=37 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)), + _ => Block::new(BlockKind::Rock, Rgb::new(55, 50, 60)), + }) + })); + let rock = Fill::Brick(BlockKind::Rock, Rgb::new(55, 50, 60), 24); + let water = Fill::Block(Block::new(BlockKind::Water, Rgb::zero())); + let key_door = Fill::Block(Block::air(SpriteKind::KeyDoor)); + let key_hole = Fill::Block(Block::air(SpriteKind::Keyhole)); + let gold_chain = Fill::Block(Block::air(SpriteKind::SeaDecorChain)); + + for room in room_data { + let (room_base, room_center) = (room.room_base, room.room_center); + // rooms + // encapsulation + painter + .aabb(Aabb { + min: (room_center - room_size - 23).with_z(room_base - room_size - 1), + max: (room_center + room_size + 23).with_z(room_base - 2), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: (room_center - room_size - 2).with_z(room_base - room_size - 1), + max: (room_center + room_size + 2).with_z(room_base - 2), + }) + .fill(rock_broken.clone()); + + // solid floor + painter + .aabb(Aabb { + min: (room_center - room_size - 10).with_z(room_base - room_size - 2), + max: (room_center + room_size + 10).with_z(room_base - room_size - 1), + }) + .fill(rock.clone()); + // floor candles + painter + .cylinder(Aabb { + min: (room_center - room_size + 1).with_z(room_base - room_size - 1), + max: (room_center + room_size - 1).with_z(room_base - room_size), + }) + .fill(candles_lite.clone()); + } + + for s in 0..=floors { + let room_base = base - (s * (2 * room_size)); + + // center pit + for p in 3..=5 { + let pos = 3 * p; + let radius = pos * 2; + let amount = pos; + let clear_radius = radius - 8; + let tower_pos = place_circular(center, radius as f32, amount); + let clear_pos = place_circular(center, clear_radius as f32, amount); + tower_positions.extend(tower_pos); + clear_positions.extend(clear_pos); + } + for tower_center in &tower_positions { + let height_var = + (RandomField::new(0).get(tower_center.with_z(room_base)) % 15) as i32; + let height = height_var * 3; + let size = height_var / 3; + + // towers + + // encapsulation if under ground + if room_base < base { + painter + .aabb(Aabb { + min: (tower_center - 9 - size).with_z(room_base - 2), + max: (tower_center + 9 + size).with_z(room_base + 10 + height), + }) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: (tower_center - 9 - (size / 2)).with_z(room_base + 8 + height), + max: (tower_center + 9 + (size / 2)) + .with_z(room_base + 10 + height + 5 + (height / 2)), + }) + .fill(rock.clone()); + } + painter + .aabb(Aabb { + min: (tower_center - 8 - size).with_z(room_base), + max: (tower_center + 8 + size).with_z(room_base + 10 + height), + }) + .fill(rock_broken.clone()); + painter + .aabb(Aabb { + min: (tower_center - 8 - (size / 2)).with_z(room_base + 10 + height), + max: (tower_center + 8 + (size / 2)) + .with_z(room_base + 10 + height + 5 + (height / 2)), + }) + .fill(rock_broken.clone()); + + // vault carves floor 0 + painter + .vault( + Aabb { + min: Vec2::new(tower_center.x - 8 - size, tower_center.y - 4 - size) + .with_z(room_base + size), + max: Vec2::new(tower_center.x + 8 + size, tower_center.y + 4 + size) + .with_z(room_base + height), + }, + Dir::X, + ) + .clear(); + + painter + .vault( + Aabb { + min: Vec2::new(tower_center.x - 4 - size, tower_center.y - 8 - size) + .with_z(room_base + size), + max: Vec2::new(tower_center.x + 4 + size, tower_center.y + 8 + size) + .with_z(room_base + height), + }, + Dir::Y, + ) + .clear(); + // vault carves floor 1 + painter + .vault( + Aabb { + min: Vec2::new( + tower_center.x - 8 - (size / 2), + tower_center.y - 4 - (size / 2), + ) + .with_z(room_base + 10 + height), + max: Vec2::new( + tower_center.x + 8 + (size / 2), + tower_center.y + 4 + (size / 2), + ) + .with_z(room_base + 10 + height + 5 + (height / 4) + (size / 2)), + }, + Dir::X, + ) + .clear(); + + painter + .vault( + Aabb { + min: Vec2::new( + tower_center.x - 4 - (size / 2), + tower_center.y - 8 - (size / 2), + ) + .with_z(room_base + 10 + height), + max: Vec2::new( + tower_center.x + 4 + (size / 2), + tower_center.y + 8 + (size / 2), + ) + .with_z(room_base + 10 + height + 5 + (height / 4) + (size / 2)), + }, + Dir::Y, + ) + .clear(); + } + // tower clears + for (tower_center, clear_center) in tower_positions.iter().zip(&clear_positions) { + let height_var = + (RandomField::new(0).get(tower_center.with_z(room_base)) % 15) as i32; + let height = height_var * 3; + let size = height_var / 3; + // tower clears + painter + .aabb(Aabb { + min: (clear_center - 9 - size).with_z(room_base + size), + max: (clear_center + 9 + size).with_z(room_base + 8 + height), + }) + .clear(); + painter + .aabb(Aabb { + min: (clear_center - 8 - (size / 2)).with_z(room_base + 10 + height), + max: (clear_center + 8 + (size / 2)) + .with_z(room_base + 8 + height + 5 + (height / 2)), + }) + .clear(); + + // decay + let decay_size = 8 + size; + painter + .cylinder(Aabb { + min: (clear_center - decay_size).with_z(room_base + 8 + height), + max: (clear_center + decay_size).with_z(room_base + 10 + height), + }) + .clear(); + + painter + .cylinder(Aabb { + min: (clear_center - decay_size + 5) + .with_z(room_base + 8 + height + 5 + (height / 2)), + max: (clear_center + decay_size - 5) + .with_z(room_base + 10 + height + 5 + (height / 2)), + }) + .clear(); + } + + // center clear + painter + .cylinder(Aabb { + min: (center - room_size + 10).with_z(room_base), + max: (center + room_size - 10).with_z(room_base + (4 * (room_size))), + }) + .clear(); + } + // room clears + for room in room_data { + let (room_base, room_center, clear_center, mob_room, boss_room) = ( + room.room_base, + room.room_center, + room.clear_center, + room.mob_room, + room.boss_room, + ); + painter + .cylinder(Aabb { + min: (clear_center - room_size - 1).with_z(room_base - room_size), + max: (clear_center + room_size + 1).with_z(room_base - 4), + }) + .clear(); + + // room decor + let decor_var = RandomField::new(0).get(room_center.with_z(room_base)) % 4; + if mob_room { + // room_center platform or water basin + if decor_var < 3 { + painter + .aabb(Aabb { + min: (room_center - room_size + 10).with_z(room_base - room_size - 1), + max: (room_center + room_size - 10).with_z(room_base - 2), + }) + .fill(rock_broken.clone()); + } + } + + // carves + let spacing = 12; + let carve_length = room_size + 8; + let carve_width = 3; + for f in 0..3 { + for c in 0..5 { + // candles & chest & npcs + let sprite_pos_1 = Vec2::new( + room_center.x - room_size + (spacing / 2) + (spacing * c) - carve_width + 2, + room_center.y - carve_length + 2, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)); + sprite_positions.push(sprite_pos_1); + + let sprite_pos_2 = Vec2::new( + room_center.x - room_size + (spacing / 2) + (spacing * c) + carve_width - 2, + room_center.y + carve_length - 2, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)); + sprite_positions.push(sprite_pos_2); + + let sprite_pos_3 = Vec2::new( + room_center.x - carve_length + 2, + room_center.y - room_size + (spacing / 2) + (spacing * c) - carve_width + 2, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)); + sprite_positions.push(sprite_pos_3); + + let sprite_pos_4 = Vec2::new( + room_center.x + carve_length - 2, + room_center.y - room_size + (spacing / 2) + (spacing * c) + carve_width - 2, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)); + sprite_positions.push(sprite_pos_4); + + let candle_limiter = painter.aabb(Aabb { + min: (room_center - room_size + 10) + .with_z(room_base - room_size - 2 + ((room_size / 3) * f)), + max: (room_center + room_size - 10) + .with_z(room_base - room_size + ((room_size / 3) * f)), + }); + painter + .vault( + Aabb { + min: Vec2::new( + room_center.x - room_size + (spacing / 2) + (spacing * c) + - carve_width, + room_center.y - carve_length, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + room_center.y + carve_length, + ) + .with_z( + room_base - room_size - 3 + + (room_size / 3) + + ((room_size / 3) * f), + ), + }, + Dir::Y, + ) + .clear(); + + if mob_room { + painter + .aabb(Aabb { + min: Vec2::new( + room_center.x - room_size + (spacing / 2) + (spacing * c) + - carve_width, + room_center.y - carve_length, + ) + .with_z(room_base - room_size - 2 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + room_center.y + carve_length, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + }) + .intersect(candle_limiter) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: Vec2::new( + room_center.x - room_size + (spacing / 2) + (spacing * c) + - carve_width, + room_center.y - carve_length, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + room_center.y + carve_length, + ) + .with_z(room_base - room_size + ((room_size / 3) * f)), + }) + .intersect(candle_limiter) + .fill(candles_lite.clone()); + } + + painter + .vault( + Aabb { + min: Vec2::new( + room_center.x - carve_length, + room_center.y - room_size + (spacing / 2) + (spacing * c) + - carve_width, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x + carve_length, + room_center.y - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + ) + .with_z( + room_base - room_size - 3 + + (room_size / 3) + + ((room_size / 3) * f), + ), + }, + Dir::X, + ) + .clear(); + if mob_room { + painter + .aabb(Aabb { + min: Vec2::new( + room_center.x - carve_length, + room_center.y - room_size + (spacing / 2) + (spacing * c) + - carve_width, + ) + .with_z(room_base - room_size - 2 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x + carve_length, + room_center.y - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + }) + .intersect(candle_limiter) + .fill(rock.clone()); + painter + .aabb(Aabb { + min: Vec2::new( + room_center.x - carve_length, + room_center.y - room_size + (spacing / 2) + (spacing * c) + - carve_width, + ) + .with_z(room_base - room_size - 1 + ((room_size / 3) * f)), + max: Vec2::new( + room_center.x + carve_length, + room_center.y - room_size + + (spacing / 2) + + (spacing * c) + + carve_width, + ) + .with_z(room_base - room_size + ((room_size / 3) * f)), + }) + .intersect(candle_limiter) + .fill(candles_lite.clone()); + } + } + if mob_room { + // mob room npcs + for dir in CARDINALS { + for d in 1..=4 { + let npc_pos = (room_center + dir * ((spacing / 2) * d)) + .with_z(room_base - room_size + ((room_size / 3) * f)); + let pos_var = RandomField::new(0).get(npc_pos) % 10; + if pos_var < 1 { + painter.spawn(EntityInfo::at(npc_pos.as_()).with_asset_expect( + "common.entity.dungeon.cultist.cultist", + &mut thread_rng, + None, + )) + } else if pos_var > 2 && f > 0 { + painter.sphere_with_radius(npc_pos, 5_f32).clear(); + } + } + } + let decor_var = RandomField::new(0).get(room_center.with_z(room_base)) % 4; + if decor_var < 3 { + // portal platform + painter + .cylinder(Aabb { + min: (room_center - 3).with_z(room_base - (room_size / 4) - 5), + max: (room_center + 3).with_z(room_base - (room_size / 4) - 4), + }) + .fill(rock.clone()); + } else { + painter + .cylinder(Aabb { + min: (room_center - room_size + 10) + .with_z(room_base - room_size - 3), + max: (room_center + room_size - 10) + .with_z(room_base - room_size - 2), + }) + .fill(rock.clone()); + painter + .cylinder(Aabb { + min: (room_center - room_size + 10) + .with_z(room_base - room_size - 2), + max: (room_center + room_size - 10) + .with_z(room_base - room_size - 1), + }) + .fill(water.clone()); + painter + .aabb(Aabb { + min: (room_center - room_size + 10) + .with_z(room_base - room_size - 1), + max: (room_center + room_size - 10) + .with_z(room_base - (room_size / 4) - 3), + }) + .clear(); + } + } + } + // room portals + let mob_portal = room_center.with_z(room_base - (room_size / 4)); + let mob_portal_target = (room_center + 10).with_z(room_base - (room_size * 2)); + let mini_boss_portal = room_center.with_z(room_base - (room_size * 2)); + let exit_position = (center - 10).with_z(base - (6 * room_size)); + let boss_position = (center - 10).with_z(base - (7 * room_size)); + let boss_portal = center.with_z(base - (7 * room_size)); + + let mob_portal_pos = Vec3::new( + mob_portal.x as f32, + mob_portal.y as f32, + mob_portal.z as f32, + ); + let mob_portal_target_pos = Vec3::new( + mob_portal_target.x as f32, + mob_portal_target.y as f32, + mob_portal_target.z as f32, + ); + let mini_boss_portal_pos = Vec3::new( + mini_boss_portal.x as f32, + mini_boss_portal.y as f32, + mini_boss_portal.z as f32, + ); + let exit_pos = Vec3::new( + exit_position.x as f32, + exit_position.y as f32, + exit_position.z as f32, + ); + let boss_pos = Vec3::new( + boss_position.x as f32, + boss_position.y as f32, + boss_position.z as f32, + ); + let boss_portal_pos = Vec3::new( + boss_portal.x as f32, + boss_portal.y as f32, + boss_portal.z as f32, + ); + + let mini_boss_portal_target = [ + exit_pos, exit_pos, exit_pos, exit_pos, exit_pos, boss_pos, boss_pos, boss_pos, + ]; + + if mob_room { + painter.spawn(EntityInfo::at(mob_portal_pos).into_special( + SpecialEntity::Teleporter(PortalData { + target: mob_portal_target_pos, + requires_no_aggro: true, + buildup_time: Secs(5.), + }), + )); + let mini_boss_portal_target_index = RandomField::new(0).get(mini_boss_portal) + as usize + % mini_boss_portal_target.len(); + let mini_boss_portal_target_pos = + mini_boss_portal_target[mini_boss_portal_target_index]; + painter.spawn(EntityInfo::at(mini_boss_portal_pos).into_special( + SpecialEntity::Teleporter(PortalData { + target: mini_boss_portal_target_pos, + requires_no_aggro: true, + buildup_time: Secs(5.), + }), + )); + } else if boss_room { + painter.spawn(EntityInfo::at(boss_portal_pos).into_special( + SpecialEntity::Teleporter(PortalData { + target: exit_pos, + requires_no_aggro: true, + buildup_time: Secs(5.), + }), + )); + } + + if !mob_room { + if boss_room { + let npc_pos = room_center.with_z(room_base - room_size); + + painter.spawn(EntityInfo::at(npc_pos.as_()).with_asset_expect( + "common.entity.dungeon.cultist.mindflayer", + &mut thread_rng, + None, + )); + } else { + let npc_pos = (room_center - 2).with_z(room_base - room_size); + painter.spawn(EntityInfo::at(npc_pos.as_()).with_asset_expect( + "common.entity.dungeon.cultist.warlock", + &mut thread_rng, + None, + )); + + painter.spawn(EntityInfo::at(npc_pos.as_()).with_asset_expect( + "common.entity.dungeon.cultist.warlord", + &mut thread_rng, + None, + )); + painter.spawn( + EntityInfo::at(((room_center + 5).with_z(room_base - room_size)).as_()) + .with_asset_expect( + "common.entity.dungeon.cultist.beastmaster", + &mut thread_rng, + None, + ), + ); + } + // gold chains + let chain_positions = place_circular(room_center, 15.0, 10); + for pos in chain_positions { + painter + .aabb(Aabb { + min: pos.with_z(room_base - 12), + max: (pos + 1).with_z(room_base - 4), + }) + .fill(gold_chain.clone()); + } + } + let down = if mob_room && decor_var < 3 { + 0 + } else if mob_room && decor_var > 2 { + room_size + } else { + 10 + }; + let magic_circle_bb = painter.cylinder(Aabb { + min: (room_center - 15).with_z(room_base - 3 - down), + max: (room_center + 16).with_z(room_base - 2 - down), + }); + star_positions.push((magic_circle_bb, room_center)); + } + // candles & chests & npcs + for sprite_pos in sprite_positions { + // keep center pit clear + if sprite_pos.xy().distance_squared(center) > 40_i32.pow(2) + || sprite_pos.z < (base - (6 * room_size)) + { + match (RandomField::new(0).get(sprite_pos + 1)) % 16 { + 0 => { + if sprite_pos.z > (base - (6 * room_size)) { + random_npcs.push(sprite_pos) + } + }, + 1 => { + // prisoners + painter + .aabb(Aabb { + min: (sprite_pos - 1).with_z(sprite_pos.z), + max: (sprite_pos + 2).with_z(sprite_pos.z + 3), + }) + .fill(key_door.clone()); + painter + .aabb(Aabb { + min: sprite_pos.with_z(sprite_pos.z + 3), + max: (sprite_pos + 1).with_z(sprite_pos.z + 4), + }) + .fill(key_hole.clone()); + painter + .aabb(Aabb { + min: (sprite_pos).with_z(sprite_pos.z), + max: (sprite_pos + 1).with_z(sprite_pos.z + 2), + }) + .clear(); + painter.spawn(EntityInfo::at(sprite_pos.as_()).with_asset_expect( + match (RandomField::new(0).get(sprite_pos)) % 10 { + 0 => "common.entity.village.farmer", + 1 => "common.entity.village.guard", + 2 => "common.entity.village.hunter", + 3 => "common.entity.village.skinner", + _ => "common.entity.village.villager", + }, + &mut thread_rng, + None, + )); + }, + _ => { + painter.sprite( + sprite_pos, + match (RandomField::new(0).get(sprite_pos)) % 20 { + 0 => SpriteKind::DungeonChest5, + _ => SpriteKind::Candle, + }, + ); + }, + } + } + } + // random_npcs around upper entrance and bottom portal + for s in 0..=1 { + let radius = 62.0 - (s * 50) as f32; + let npcs = place_circular(center, radius, 8 - (s * 4)); + for npc_pos in npcs { + random_npcs.push(npc_pos.with_z(base + 8 - ((6 * room_size) * s) - (s * 8))); + } + } + for pos in random_npcs { + let entities = [ + "common.entity.dungeon.cultist.cultist", + "common.entity.dungeon.cultist.turret", + "common.entity.dungeon.cultist.husk", + "common.entity.dungeon.cultist.husk_brute", + "common.entity.dungeon.cultist.hound", + ]; + let npc = entities[(RandomField::new(0).get(pos) % entities.len() as u32) as usize]; + painter.spawn(EntityInfo::at(pos.as_()).with_asset_expect(npc, &mut thread_rng, None)); + } + + // outside portal + let top_position = (center - 20).with_z(base + 125); + let bottom_position = center.with_z(base - (6 * room_size)); + let top_pos = Vec3::new( + top_position.x as f32, + top_position.y as f32, + top_position.z as f32, + ); + let bottom_pos = Vec3::new( + bottom_position.x as f32, + bottom_position.y as f32, + bottom_position.z as f32, + ); + painter.spawn( + EntityInfo::at(bottom_pos).into_special(SpecialEntity::Teleporter(PortalData { + target: top_pos, + requires_no_aggro: true, + buildup_time: Secs(5.), + })), + ); + let stone_purple = Block::new(BlockKind::GlowingRock, Rgb::new(96, 0, 128)); + let magic_circle_bb = painter.cylinder(Aabb { + min: (center - 15).with_z(base - (floors * (2 * room_size)) - 1), + max: (center + 16).with_z(base - (floors * (2 * room_size))), + }); + let magic_circle_bb_boss = painter.cylinder(Aabb { + min: (center - 15).with_z(base - (7 * room_size) - 2), + max: (center + 16).with_z(base - (7 * room_size) - 1), + }); + star_positions.push((magic_circle_bb, center)); + star_positions.push((magic_circle_bb_boss, center)); + for (magic_circle_bb, position) in star_positions { + let magic_circle = painter.prim(Primitive::sampling( + magic_circle_bb, + inscribed_polystar(position, 15.0, 7), + )); + painter.fill(magic_circle, Fill::Block(stone_purple)); + } + // base floor + painter + .cylinder(Aabb { + min: (center - room_size - 15).with_z(base - (floors * (2 * room_size)) - 3), + max: (center + room_size + 15).with_z(base - (floors * (2 * room_size)) - 2), + }) + .fill(rock.clone()); + } +} + +fn place_circular(center: Vec2, radius: f32, amount: i32) -> Vec> { + let phi = TAU / amount as f32; + let mut positions = vec![]; + for n in 1..=amount { + let pos = Vec2::new( + center.x + (radius * ((n as f32 * phi).cos())) as i32, + center.y + (radius * ((n as f32 * phi).sin())) as i32, + ); + positions.push(pos); + } + positions +} diff --git a/world/src/site2/plot/dungeon.rs b/world/src/site2/plot/dungeon.rs index 910431a3de..af0aec26a6 100644 --- a/world/src/site2/plot/dungeon.rs +++ b/world/src/site2/plot/dungeon.rs @@ -231,31 +231,12 @@ impl Room { let entities = match self.difficulty { 2 => enemy_2(dynamic_rng, tile_wcenter), 4 => enemy_4(dynamic_rng, tile_wcenter), - 5 => enemy_5(dynamic_rng, tile_wcenter), _ => enemy_fallback(dynamic_rng, tile_wcenter), }; for entity in entities { supplement.add_entity(entity); } - } else { - // Turrets - // Turret has 1/5000 chance to spawn per voxel in fight room - if dynamic_rng.gen_range(0..5000) == 0 { - let pos = tile_wcenter.map(|e| e as f32) - + Vec3::::iota() - .map(|e| { - (RandomField::new(self.seed.wrapping_add(10 + e)) - .get(Vec3::from(tile_pos)) - % 32) as i32 - - 16 - }) - .map(|e| e as f32 / 16.0); - if self.difficulty == 5 { - let turret = turret_5(dynamic_rng, pos); - supplement.add_entity(turret); - }; - } } } @@ -280,7 +261,6 @@ impl Room { let entities = match self.difficulty { 2 => mini_boss_2(dynamic_rng, tile_wcenter), 4 => mini_boss_4(dynamic_rng, tile_wcenter), - 5 => mini_boss_5(dynamic_rng, tile_wcenter), _ => mini_boss_fallback(dynamic_rng, tile_wcenter), }; @@ -311,7 +291,6 @@ impl Room { let entities = match self.difficulty { 2 => boss_2(dynamic_rng, tile_wcenter), 4 => boss_4(dynamic_rng, tile_wcenter), - 5 => boss_5(dynamic_rng, tile_wcenter), _ => boss_fallback(dynamic_rng, tile_wcenter), }; @@ -744,28 +723,6 @@ fn enemy_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let number = dynamic_rng.gen_range(1..=3); - let mut entities = Vec::new(); - entities.resize_with(number, || { - // TODO: give enemies health skills? - let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32)); - match dynamic_rng.gen_range(0..=4) { - 0 => { - entity.with_asset_expect("common.entity.dungeon.cultist.warlock", dynamic_rng, None) - }, - 1 => { - entity.with_asset_expect("common.entity.dungeon.cultist.warlord", dynamic_rng, None) - }, - _ => { - entity.with_asset_expect("common.entity.dungeon.cultist.cultist", dynamic_rng, None) - }, - } - }); - - entities -} - fn enemy_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { let number = dynamic_rng.gen_range(2..=4); let mut entities = Vec::new(); @@ -777,10 +734,6 @@ fn enemy_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> EntityInfo { - EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.cultist.turret", dynamic_rng, None) -} - fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( @@ -801,16 +754,6 @@ fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - vec![ - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.cultist.mindflayer", - dynamic_rng, - None, - ), - ] -} - fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( @@ -843,40 +786,6 @@ fn mini_boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec) -> Vec { - let mut entities = Vec::new(); - match dynamic_rng.gen_range(0..=2) { - 0 => { - entities.push( - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.cultist.beastmaster", - dynamic_rng, - None, - ), - ); - }, - 1 => { - entities.resize_with(2, || { - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.cultist.husk_brute", - dynamic_rng, - None, - ) - }); - }, - _ => { - entities.resize_with(10, || { - EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( - "common.entity.dungeon.cultist.husk", - dynamic_rng, - None, - ) - }); - }, - } - entities -} - fn mini_boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3) -> Vec { vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect( @@ -1469,7 +1378,6 @@ mod tests { let tile_wcenter = Vec3::new(0, 0, 0); boss_2(&mut dynamic_rng, tile_wcenter); boss_4(&mut dynamic_rng, tile_wcenter); - boss_5(&mut dynamic_rng, tile_wcenter); boss_fallback(&mut dynamic_rng, tile_wcenter); } @@ -1480,7 +1388,6 @@ mod tests { let random_position = Vec3::new(0, 0, 0); enemy_2(&mut dynamic_rng, random_position); enemy_4(&mut dynamic_rng, random_position); - enemy_5(&mut dynamic_rng, random_position); enemy_fallback(&mut dynamic_rng, random_position); } @@ -1491,14 +1398,6 @@ mod tests { let tile_wcenter = Vec3::new(0, 0, 0); mini_boss_2(&mut dynamic_rng, tile_wcenter); mini_boss_4(&mut dynamic_rng, tile_wcenter); - mini_boss_5(&mut dynamic_rng, tile_wcenter); mini_boss_fallback(&mut dynamic_rng, tile_wcenter); } - - #[test] - fn test_creating_turrets() { - let mut dynamic_rng = thread_rng(); - let pos = Vec3::new(0.0, 0.0, 0.0); - turret_5(&mut dynamic_rng, pos); - } }