mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Theropod charge attack
This commit is contained in:
parent
9d7e8957bb
commit
60dd47cdea
19
assets/common/abilities/unique/theropodbasic/dash.ron
Normal file
19
assets/common/abilities/unique/theropodbasic/dash.ron
Normal file
@ -0,0 +1,19 @@
|
||||
DashMelee(
|
||||
energy_cost: 0,
|
||||
base_damage: 150,
|
||||
scaled_damage: 40,
|
||||
base_poise_damage: 0,
|
||||
scaled_poise_damage: 0,
|
||||
base_knockback: 8.0,
|
||||
scaled_knockback: 17.0,
|
||||
range: 4.0,
|
||||
angle: 45.0,
|
||||
energy_drain: 0,
|
||||
forward_speed: 2.0,
|
||||
buildup_duration: 0.5,
|
||||
charge_duration: 1.2,
|
||||
swing_duration: 0.1,
|
||||
recover_duration: 1.1,
|
||||
infinite_charge: true,
|
||||
is_interruptible: false,
|
||||
)
|
@ -184,6 +184,11 @@
|
||||
secondary: "common.abilities.unique.theropodbird.triplestrike",
|
||||
abilities: [],
|
||||
),
|
||||
Unique(TheropodCharge): (
|
||||
primary: "common.abilities.unique.theropodbird.triplestrike",
|
||||
secondary: "common.abilities.unique.theropodbasic.dash",
|
||||
abilities: [],
|
||||
),
|
||||
Unique(ObjectTurret): (
|
||||
primary: "common.abilities.unique.turret.arrows",
|
||||
secondary: "common.abilities.unique.turret.arrows",
|
||||
|
18
assets/common/items/npc_weapons/unique/theropodcharge.ron
Normal file
18
assets/common/items/npc_weapons/unique/theropodcharge.ron
Normal file
@ -0,0 +1,18 @@
|
||||
ItemDef(
|
||||
name: "Theropod Charge",
|
||||
description: "testing123",
|
||||
kind: Tool((
|
||||
kind: Unique(TheropodCharge),
|
||||
hands: Two,
|
||||
stats: Direct((
|
||||
equip_time_secs: 0.01,
|
||||
power: 1.0,
|
||||
poise_strength: 1.0,
|
||||
speed: 1.0,
|
||||
crit_chance: 0.1,
|
||||
crit_mult: 2.0,
|
||||
)),
|
||||
)),
|
||||
quality: Low,
|
||||
tags: [],
|
||||
)
|
BIN
assets/voxygen/voxel/npc/moose/female/ears.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/ears.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/foot_bl.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/foot_bl.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/foot_br.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/foot_br.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/foot_fl.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/foot_fl.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/foot_fr.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/foot_fr.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/head.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/head.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/jaw.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/jaw.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/leg_bl.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/leg_bl.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/leg_br.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/leg_br.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/leg_fl.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/leg_fl.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/leg_fr.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/leg_fr.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/neck.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/neck.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/tail.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/tail.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/torso_back.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/torso_back.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/female/torso_front.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/female/torso_front.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/ears.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/ears.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/foot_br.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/foot_br.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/foot_fr.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/foot_fr.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/head.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/head.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/jaw.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/jaw.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/leg_br.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/leg_br.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/leg_fr.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/leg_fr.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/neck.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/neck.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/tail.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/tail.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/torso_back.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/torso_back.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/moose/male/torso_front.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/moose/male/torso_front.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/ntouka/male/foot_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/ntouka/male/foot_l.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/ntouka/male/hand_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/ntouka/male/hand_l.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/ntouka/male/leg_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/ntouka/male/leg_l.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/yale/male/foot_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/yale/male/foot_l.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/yale/male/hand_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/yale/male/hand_l.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/npc/yale/male/leg_l.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/npc/yale/male/leg_l.vox
(Stored with Git LFS)
Binary file not shown.
@ -197,7 +197,7 @@ impl Body {
|
||||
theropod::Species::Woodraptor => 1.5,
|
||||
theropod::Species::Archaeos => 3.5,
|
||||
theropod::Species::Odonto => 3.5,
|
||||
theropod::Species::Yale => 1.3,
|
||||
theropod::Species::Yale => 0.8,
|
||||
theropod::Species::Ntouka => 3.0,
|
||||
_ => 1.8,
|
||||
},
|
||||
@ -249,6 +249,8 @@ impl Body {
|
||||
quadruped_medium::Species::Saber => 2.0,
|
||||
quadruped_medium::Species::Catoblepas => 2.9,
|
||||
quadruped_medium::Species::Barghest => 2.5,
|
||||
quadruped_medium::Species::Dreadhorn => 2.5,
|
||||
quadruped_medium::Species::Moose => 2.5,
|
||||
_ => 1.6,
|
||||
},
|
||||
Body::QuadrupedLow(body) => match body.species {
|
||||
@ -263,7 +265,7 @@ impl Body {
|
||||
theropod::Species::Sandraptor => 2.6,
|
||||
theropod::Species::Woodraptor => 2.6,
|
||||
theropod::Species::Sunlizard => 2.5,
|
||||
theropod::Species::Yale => 2.8,
|
||||
theropod::Species::Yale => 3.0,
|
||||
_ => 8.0,
|
||||
},
|
||||
Body::BirdMedium(body) => match body.species {
|
||||
|
@ -421,6 +421,7 @@ pub enum UniqueKind {
|
||||
QuadSmallBasic,
|
||||
TheropodBasic,
|
||||
TheropodBird,
|
||||
TheropodCharge,
|
||||
ObjectTurret,
|
||||
WoodenSpear,
|
||||
}
|
||||
|
@ -191,12 +191,16 @@ impl LoadoutBuilder {
|
||||
Body::Theropod(theropod) => match theropod.species {
|
||||
theropod::Species::Sandraptor
|
||||
| theropod::Species::Snowraptor
|
||||
| theropod::Species::Woodraptor
|
||||
| theropod::Species::Yale => {
|
||||
| theropod::Species::Woodraptor => {
|
||||
main_tool = Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.unique.theropodbird",
|
||||
));
|
||||
},
|
||||
theropod::Species::Yale => {
|
||||
main_tool = Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.unique.theropodcharge",
|
||||
));
|
||||
},
|
||||
_ => {
|
||||
main_tool = Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.unique.theropodbasic",
|
||||
|
@ -1008,7 +1008,11 @@ impl<'a> AgentData<'a> {
|
||||
circle_time: 2,
|
||||
},
|
||||
Some(ToolKind::Unique(UniqueKind::QuadMedCharge)) => Tactic::CircleCharge {
|
||||
radius: 15,
|
||||
radius: 12,
|
||||
circle_time: 1,
|
||||
},
|
||||
Some(ToolKind::Unique(UniqueKind::TheropodCharge)) => Tactic::CircleCharge {
|
||||
radius: 6,
|
||||
circle_time: 1,
|
||||
},
|
||||
|
||||
|
@ -519,15 +519,15 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
||||
(Roshwalr, _) => (1.3),
|
||||
(Barghest, _) => (1.5),
|
||||
(Antelope, _) => (1.2),
|
||||
(Kelpie, _) => (1.4),
|
||||
(Kelpie, _) => (1.35),
|
||||
(Donkey, _) => (1.2),
|
||||
(Horse, _) => (1.45),
|
||||
(Horse, _) => (1.42),
|
||||
(Zebra, _) => (1.3),
|
||||
(Cattle, _) => (1.7),
|
||||
(Highland, _) => (1.7),
|
||||
(Bear, _) => (1.7),
|
||||
(Yak, _) => (1.7),
|
||||
(Camel, _) => (1.45),
|
||||
(Camel, _) => (1.42),
|
||||
(Dreadhorn, _) => (2.0),
|
||||
(Moose, _) => (1.1),
|
||||
(Snowleopard, _) => (1.2),
|
||||
|
@ -3,7 +3,6 @@ use super::{
|
||||
SkeletonAttr, TheropodSkeleton,
|
||||
};
|
||||
use common::states::utils::StageSection;
|
||||
//use std::ops::Rem;
|
||||
|
||||
pub struct AlphaAnimation;
|
||||
|
||||
|
96
voxygen/anim/src/theropod/dash.rs
Normal file
96
voxygen/anim/src/theropod/dash.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use super::{
|
||||
super::{vek::*, Animation},
|
||||
SkeletonAttr, TheropodSkeleton,
|
||||
};
|
||||
use common::states::utils::StageSection;
|
||||
|
||||
pub struct DashAnimation;
|
||||
|
||||
impl Animation for DashAnimation {
|
||||
type Dependency = (f32, f32, Option<StageSection>, f32);
|
||||
type Skeleton = TheropodSkeleton;
|
||||
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"theropod_dash\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "theropod_dash")]
|
||||
fn update_skeleton_inner(
|
||||
skeleton: &Self::Skeleton,
|
||||
(_velocity, global_time, stage_section, timer): Self::Dependency,
|
||||
anim_time: f32,
|
||||
_rate: &mut f32,
|
||||
_s_a: &SkeletonAttr,
|
||||
) -> Self::Skeleton {
|
||||
let mut next = (*skeleton).clone();
|
||||
|
||||
let (movement1base, chargemovementbase, movement2base, movement3, legtell) =
|
||||
match stage_section {
|
||||
Some(StageSection::Buildup) => (anim_time.sqrt(), 0.0, 0.0, 0.0, anim_time),
|
||||
Some(StageSection::Charge) => (1.0, 1.0, 0.0, 0.0, 0.0),
|
||||
Some(StageSection::Swing) => (1.0, 1.0, anim_time.powi(4), 0.0, 1.0),
|
||||
Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time, 1.0),
|
||||
_ => (0.0, 0.0, 0.0, 0.0, 0.0),
|
||||
};
|
||||
let pullback = 1.0 - movement3;
|
||||
let subtract = global_time - timer;
|
||||
let check = subtract - subtract.trunc();
|
||||
let mirror = (check - 0.5).signum();
|
||||
let movement1 = mirror * movement1base * pullback;
|
||||
let movement2 = mirror * movement2base * pullback;
|
||||
let movement1abs = movement1base * pullback;
|
||||
let movement2abs = movement2base * pullback;
|
||||
let legtwitch = (legtell * 6.0).sin() * pullback;
|
||||
let legswing = legtell * pullback;
|
||||
let chargeanim = (chargemovementbase * anim_time * 15.0).sin();
|
||||
|
||||
next.head.orientation =
|
||||
Quaternion::rotation_x(movement1abs * -0.3 + chargeanim * 0.02 + movement2abs * 0.9)
|
||||
* Quaternion::rotation_y(movement1 * 0.1 + movement2 * 0.2);
|
||||
next.neck.orientation =
|
||||
Quaternion::rotation_x(movement1abs * -0.8 + chargeanim * 0.05 + movement2abs * 0.9)
|
||||
* Quaternion::rotation_y(movement1 * 0.1 + movement2 * 0.1);
|
||||
|
||||
next.jaw.orientation = Quaternion::rotation_x(movement1abs * -0.3 + movement2abs * 0.5);
|
||||
|
||||
next.chest_front.orientation = Quaternion::rotation_x(movement1abs * -0.2);
|
||||
next.chest_back.orientation =
|
||||
Quaternion::rotation_x(movement1abs * 0.2 + chargeanim * -0.05);
|
||||
|
||||
next.leg_l.orientation = Quaternion::rotation_x(movement1abs * -0.1);
|
||||
|
||||
next.leg_r.orientation = Quaternion::rotation_x(movement1abs * -0.1);
|
||||
next.foot_l.orientation = Quaternion::rotation_x(movement1abs * -0.3);
|
||||
next.foot_r.orientation = Quaternion::rotation_x(movement1abs * -0.3);
|
||||
|
||||
next.tail_front.orientation =
|
||||
Quaternion::rotation_x(
|
||||
0.1 + movement1abs * -0.1 + chargeanim * -0.05 + movement2abs * -0.3,
|
||||
) * Quaternion::rotation_z(movement1 * -0.1 + movement2 * -0.2);
|
||||
|
||||
next.tail_back.orientation =
|
||||
Quaternion::rotation_x(
|
||||
0.1 + movement1abs * -0.1 + chargeanim * -0.05 + movement2abs * -0.3,
|
||||
) * Quaternion::rotation_z(movement1 * -0.1 + movement2 * -0.2);
|
||||
|
||||
if legtell > 0.0 {
|
||||
if mirror.is_sign_positive() {
|
||||
next.leg_l.orientation = Quaternion::rotation_x(legswing * 1.1);
|
||||
|
||||
next.foot_l.orientation = Quaternion::rotation_x(legswing * -1.1 + legtwitch * 0.5);
|
||||
|
||||
next.leg_r.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.foot_r.orientation = Quaternion::rotation_x(0.0);
|
||||
} else {
|
||||
next.leg_l.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.foot_l.orientation = Quaternion::rotation_x(0.0);
|
||||
|
||||
next.leg_r.orientation = Quaternion::rotation_x(legswing * 1.1);
|
||||
|
||||
next.foot_r.orientation = Quaternion::rotation_x(legswing * -1.1 + legtwitch * 0.5);
|
||||
}
|
||||
};
|
||||
next
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
pub mod alpha;
|
||||
pub mod beta;
|
||||
pub mod dash;
|
||||
pub mod idle;
|
||||
pub mod jump;
|
||||
pub mod run;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
alpha::AlphaAnimation, beta::BetaAnimation, idle::IdleAnimation, jump::JumpAnimation,
|
||||
run::RunAnimation,
|
||||
alpha::AlphaAnimation, beta::BetaAnimation, dash::DashAnimation, idle::IdleAnimation,
|
||||
jump::JumpAnimation, run::RunAnimation,
|
||||
};
|
||||
|
||||
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
||||
|
@ -3151,6 +3151,36 @@ impl FigureMgr {
|
||||
),
|
||||
}
|
||||
},
|
||||
CharacterState::DashMelee(s) => {
|
||||
let stage_time = s.timer.as_secs_f32();
|
||||
let stage_progress = match s.stage_section {
|
||||
StageSection::Buildup => {
|
||||
stage_time / s.static_data.buildup_duration.as_secs_f32()
|
||||
},
|
||||
StageSection::Charge => {
|
||||
stage_time / s.static_data.charge_duration.as_secs_f32()
|
||||
},
|
||||
StageSection::Swing => {
|
||||
stage_time / s.static_data.swing_duration.as_secs_f32()
|
||||
},
|
||||
StageSection::Recover => {
|
||||
stage_time / s.static_data.recover_duration.as_secs_f32()
|
||||
},
|
||||
_ => 0.0,
|
||||
};
|
||||
anim::theropod::DashAnimation::update_skeleton(
|
||||
&target_base,
|
||||
(
|
||||
vel.0.magnitude(),
|
||||
time,
|
||||
Some(s.stage_section),
|
||||
state.state_time,
|
||||
),
|
||||
stage_progress,
|
||||
&mut state_animation_rate,
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
// TODO!
|
||||
_ => target_base,
|
||||
};
|
||||
|
@ -1,508 +0,0 @@
|
||||
use super::image_frame::ImageFrame;
|
||||
use conrod_core::{
|
||||
builder_method, builder_methods, image, input::global::Global, position::Dimension, text,
|
||||
widget, widget_ids, Color, Colorable, FontSize, Positionable, Sizeable, Ui, UiCell, Widget,
|
||||
WidgetCommon, WidgetStyle,
|
||||
};
|
||||
use std::time::{Duration, Instant};
|
||||
#[derive(Copy, Clone)]
|
||||
struct Hover(widget::Id, [f64; 2]);
|
||||
#[derive(Copy, Clone)]
|
||||
enum HoverState {
|
||||
Hovering(Hover),
|
||||
Fading(Instant, Hover, Option<(Instant, widget::Id)>),
|
||||
Start(Instant, widget::Id),
|
||||
None,
|
||||
}
|
||||
|
||||
// Spacing between the tooltip and mouse
|
||||
const MOUSE_PAD_Y: f64 = 15.0;
|
||||
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Default text color
|
||||
|
||||
pub struct ItemTooltipManager {
|
||||
tooltip_id: widget::Id,
|
||||
state: HoverState,
|
||||
// How long before a tooltip is displayed when hovering
|
||||
hover_dur: Duration,
|
||||
// How long it takes a tooltip to disappear
|
||||
fade_dur: Duration,
|
||||
// Current scaling of the ui
|
||||
logical_scale_factor: f64,
|
||||
}
|
||||
impl ItemTooltipManager {
|
||||
pub fn new(
|
||||
mut generator: widget::id::Generator,
|
||||
hover_dur: Duration,
|
||||
fade_dur: Duration,
|
||||
logical_scale_factor: f64,
|
||||
) -> Self {
|
||||
Self {
|
||||
tooltip_id: generator.next(),
|
||||
state: HoverState::None,
|
||||
hover_dur,
|
||||
fade_dur,
|
||||
logical_scale_factor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self, input: &Global, logical_scale_factor: f64) {
|
||||
self.logical_scale_factor = logical_scale_factor;
|
||||
|
||||
let current = &input.current;
|
||||
|
||||
if let Some(um_id) = current.widget_under_mouse {
|
||||
match self.state {
|
||||
HoverState::Hovering(hover) if um_id == hover.0 => (),
|
||||
HoverState::Hovering(hover) => {
|
||||
self.state =
|
||||
HoverState::Fading(Instant::now(), hover, Some((Instant::now(), um_id)))
|
||||
},
|
||||
HoverState::Fading(_, _, Some((_, id))) if um_id == id => {},
|
||||
HoverState::Fading(start, hover, _) => {
|
||||
self.state = HoverState::Fading(start, hover, Some((Instant::now(), um_id)))
|
||||
},
|
||||
HoverState::Start(_, id) if um_id == id => (),
|
||||
HoverState::Start(_, _) | HoverState::None => {
|
||||
self.state = HoverState::Start(Instant::now(), um_id)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match self.state {
|
||||
HoverState::Hovering(hover) => {
|
||||
self.state = HoverState::Fading(Instant::now(), hover, None)
|
||||
},
|
||||
HoverState::Fading(start, hover, Some((_, _))) => {
|
||||
self.state = HoverState::Fading(start, hover, None)
|
||||
},
|
||||
HoverState::Start(_, _) => self.state = HoverState::None,
|
||||
HoverState::Fading(_, _, None) | HoverState::None => (),
|
||||
}
|
||||
}
|
||||
|
||||
// Handle fade timing
|
||||
if let HoverState::Fading(start, _, maybe_hover) = self.state {
|
||||
if start.elapsed() > self.fade_dur {
|
||||
self.state = match maybe_hover {
|
||||
Some((start, hover)) => HoverState::Start(start, hover),
|
||||
None => HoverState::None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||
fn set_tooltip(
|
||||
&mut self,
|
||||
tooltip: &ItemTooltip,
|
||||
title_text: &str,
|
||||
desc_text: &str,
|
||||
title_col: Color,
|
||||
img_id: Option<image::Id>,
|
||||
image_dims: Option<(f64, f64)>,
|
||||
src_id: widget::Id,
|
||||
ui: &mut UiCell,
|
||||
) {
|
||||
let tooltip_id = self.tooltip_id;
|
||||
let mp_h = MOUSE_PAD_Y / self.logical_scale_factor;
|
||||
|
||||
let tooltip = |transparency, mouse_pos: [f64; 2], ui: &mut UiCell| {
|
||||
// Fill in text and the potential image beforehand to get an accurate size for
|
||||
// spacing
|
||||
let tooltip = tooltip
|
||||
.clone()
|
||||
.title(title_text)
|
||||
.desc(desc_text)
|
||||
.title_col(title_col)
|
||||
.image(img_id)
|
||||
.image_dims(image_dims);
|
||||
|
||||
let [t_w, t_h] = tooltip.get_wh(ui).unwrap_or([0.0, 0.0]);
|
||||
let [m_x, m_y] = [mouse_pos[0], mouse_pos[1]];
|
||||
let (w_w, w_h) = (ui.win_w, ui.win_h);
|
||||
|
||||
// Determine position based on size and mouse position
|
||||
// Flow to the top left of the mouse when there is space
|
||||
let x = if (m_x + w_w / 2.0) > t_w {
|
||||
m_x - t_w / 2.0
|
||||
} else {
|
||||
m_x + t_w / 2.0
|
||||
};
|
||||
let y = if w_h - (m_y + w_h / 2.0) > t_h + mp_h {
|
||||
m_y + mp_h + t_h / 2.0
|
||||
} else {
|
||||
m_y - mp_h - t_h / 2.0
|
||||
};
|
||||
tooltip
|
||||
.floating(true)
|
||||
.transparency(transparency)
|
||||
.x_y(x, y)
|
||||
.set(tooltip_id, ui);
|
||||
};
|
||||
|
||||
match self.state {
|
||||
HoverState::Hovering(Hover(id, xy)) if id == src_id => tooltip(1.0, xy, ui),
|
||||
HoverState::Fading(start, Hover(id, xy), _) if id == src_id => tooltip(
|
||||
(0.1f32 - start.elapsed().as_millis() as f32 / self.hover_dur.as_millis() as f32)
|
||||
.max(0.0),
|
||||
xy,
|
||||
ui,
|
||||
),
|
||||
HoverState::Start(start, id) if id == src_id && start.elapsed() > self.hover_dur => {
|
||||
let xy = ui.global_input().current.mouse.xy;
|
||||
self.state = HoverState::Hovering(Hover(id, xy));
|
||||
tooltip(1.0, xy, ui);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ItemTooltipped<'a, W> {
|
||||
inner: W,
|
||||
tooltip_manager: &'a mut ItemTooltipManager,
|
||||
title_text: &'a str,
|
||||
desc_text: &'a str,
|
||||
img_id: Option<image::Id>,
|
||||
image_dims: Option<(f64, f64)>,
|
||||
tooltip: &'a ItemTooltip<'a>,
|
||||
title_col: Color,
|
||||
}
|
||||
impl<'a, W: Widget> ItemTooltipped<'a, W> {
|
||||
pub fn tooltip_image(mut self, img_id: image::Id) -> Self {
|
||||
self.img_id = Some(img_id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tooltip_image_dims(mut self, dims: (f64, f64)) -> Self {
|
||||
self.image_dims = Some(dims);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set(self, id: widget::Id, ui: &mut UiCell) -> W::Event {
|
||||
let event = self.inner.set(id, ui);
|
||||
self.tooltip_manager.set_tooltip(
|
||||
self.tooltip,
|
||||
self.title_text,
|
||||
self.desc_text,
|
||||
self.title_col,
|
||||
self.img_id,
|
||||
self.image_dims,
|
||||
id,
|
||||
ui,
|
||||
);
|
||||
event
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ItemTooltipable {
|
||||
// If `Tooltip` is expensive to construct accept a closure here instead.
|
||||
fn with_item_tooltip<'a>(
|
||||
self,
|
||||
tooltip_manager: &'a mut ItemTooltipManager,
|
||||
title_text: &'a str,
|
||||
desc_text: &'a str,
|
||||
tooltip: &'a ItemTooltip<'a>,
|
||||
title_col: Color,
|
||||
) -> ItemTooltipped<'a, Self>
|
||||
where
|
||||
Self: std::marker::Sized;
|
||||
}
|
||||
impl<W: Widget> ItemTooltipable for W {
|
||||
fn with_item_tooltip<'a>(
|
||||
self,
|
||||
tooltip_manager: &'a mut ItemTooltipManager,
|
||||
title_text: &'a str,
|
||||
desc_text: &'a str,
|
||||
tooltip: &'a ItemTooltip<'a>,
|
||||
title_col: Color,
|
||||
) -> ItemTooltipped<'a, W> {
|
||||
ItemTooltipped {
|
||||
inner: self,
|
||||
tooltip_manager,
|
||||
title_text,
|
||||
desc_text,
|
||||
img_id: None,
|
||||
image_dims: None,
|
||||
tooltip,
|
||||
title_col,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Vertical spacing between elements of the tooltip
|
||||
const V_PAD: f64 = 10.0;
|
||||
/// Horizontal spacing between elements of the tooltip
|
||||
const H_PAD: f64 = 10.0;
|
||||
/// Default portion of inner width that goes to an image
|
||||
const IMAGE_W_FRAC: f64 = 0.3;
|
||||
/// Default width multiplied by the description font size
|
||||
const DEFAULT_CHAR_W: f64 = 30.0;
|
||||
/// Text vertical spacing factor to account for overhanging text
|
||||
const TEXT_SPACE_FACTOR: f64 = 0.35;
|
||||
|
||||
/// A widget for displaying tooltips
|
||||
#[derive(Clone, WidgetCommon)]
|
||||
pub struct ItemTooltip<'a> {
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
title_text: &'a str,
|
||||
desc_text: &'a str,
|
||||
title_col: Color,
|
||||
image: Option<image::Id>,
|
||||
image_dims: Option<(f64, f64)>,
|
||||
style: Style,
|
||||
transparency: f32,
|
||||
image_frame: ImageFrame,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, WidgetStyle)]
|
||||
pub struct Style {
|
||||
#[conrod(default = "Color::Rgba(1.0, 1.0, 1.0, 1.0)")]
|
||||
pub color: Option<Color>,
|
||||
title: widget::text::Style,
|
||||
desc: widget::text::Style,
|
||||
// add background imgs here
|
||||
}
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
title,
|
||||
desc,
|
||||
image_frame,
|
||||
image,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
ids: Ids,
|
||||
}
|
||||
|
||||
impl<'a> ItemTooltip<'a> {
|
||||
builder_methods! {
|
||||
pub desc_text_color { style.desc.color = Some(Color) }
|
||||
pub title_font_size { style.title.font_size = Some(FontSize) }
|
||||
pub desc_font_size { style.desc.font_size = Some(FontSize) }
|
||||
pub title_justify { style.title.justify = Some(text::Justify) }
|
||||
pub desc_justify { style.desc.justify = Some(text::Justify) }
|
||||
image { image = Option<image::Id> }
|
||||
title { title_text = &'a str }
|
||||
desc { desc_text = &'a str }
|
||||
image_dims { image_dims = Option<(f64, f64)> }
|
||||
transparency { transparency = f32 }
|
||||
title_col { title_col = Color}
|
||||
}
|
||||
|
||||
pub fn new(image_frame: ImageFrame) -> Self {
|
||||
ItemTooltip {
|
||||
common: widget::CommonBuilder::default(),
|
||||
style: Style::default(),
|
||||
title_text: "",
|
||||
desc_text: "",
|
||||
transparency: 1.0,
|
||||
image_frame,
|
||||
image: None,
|
||||
image_dims: None,
|
||||
title_col: TEXT_COLOR,
|
||||
}
|
||||
}
|
||||
|
||||
/// Align the text to the left of its bounding **Rect**'s *x* axis range.
|
||||
//pub fn left_justify(self) -> Self {
|
||||
// self.justify(text::Justify::Left)
|
||||
//}
|
||||
|
||||
/// Align the text to the middle of its bounding **Rect**'s *x* axis range.
|
||||
//pub fn center_justify(self) -> Self {
|
||||
// self.justify(text::Justify::Center)
|
||||
//}
|
||||
|
||||
/// Align the text to the right of its bounding **Rect**'s *x* axis range.
|
||||
//pub fn right_justify(self) -> Self {
|
||||
// self.justify(text::Justify::Right)
|
||||
//}
|
||||
|
||||
fn text_image_width(&self, total_width: f64) -> (f64, f64) {
|
||||
let inner_width = (total_width - H_PAD * 2.0).max(0.0);
|
||||
// Image defaults to 30% of the width
|
||||
let image_w = if self.image.is_some() {
|
||||
match self.image_dims {
|
||||
Some((w, _)) => w,
|
||||
None => (inner_width - H_PAD).max(0.0) * IMAGE_W_FRAC,
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
// Text gets the remaining width
|
||||
let text_w = (inner_width
|
||||
- if self.image.is_some() {
|
||||
image_w + H_PAD
|
||||
} else {
|
||||
0.0
|
||||
})
|
||||
.max(0.0);
|
||||
|
||||
(text_w, image_w)
|
||||
}
|
||||
|
||||
/// Specify the font used for displaying the text.
|
||||
pub fn font_id(mut self, font_id: text::font::Id) -> Self {
|
||||
self.style.title.font_id = Some(Some(font_id));
|
||||
self.style.desc.font_id = Some(Some(font_id));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for ItemTooltip<'a> {
|
||||
type Event = ();
|
||||
type State = State;
|
||||
type Style = Style;
|
||||
|
||||
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
||||
State {
|
||||
ids: Ids::new(id_gen),
|
||||
}
|
||||
}
|
||||
|
||||
fn style(&self) -> Self::Style { self.style.clone() }
|
||||
|
||||
fn update(self, args: widget::UpdateArgs<Self>) {
|
||||
let widget::UpdateArgs {
|
||||
id,
|
||||
state,
|
||||
rect,
|
||||
style,
|
||||
ui,
|
||||
..
|
||||
} = args;
|
||||
|
||||
// Widths
|
||||
let (text_w, image_w) = self.text_image_width(rect.w());
|
||||
|
||||
// Apply transparency
|
||||
let color = style.color(ui.theme()).alpha(self.transparency);
|
||||
|
||||
// Background image frame
|
||||
self.image_frame
|
||||
.wh(rect.dim())
|
||||
.xy(rect.xy())
|
||||
.graphics_for(id)
|
||||
.parent(id)
|
||||
.color(color)
|
||||
.set(state.ids.image_frame, ui);
|
||||
|
||||
// Image
|
||||
if let Some(img_id) = self.image {
|
||||
widget::Image::new(img_id)
|
||||
.w_h(image_w, self.image_dims.map_or(image_w, |(_, h)| h))
|
||||
.graphics_for(id)
|
||||
.parent(id)
|
||||
.color(Some(color))
|
||||
.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
|
||||
.set(state.ids.image, ui);
|
||||
}
|
||||
|
||||
// Spacing for overhanging text
|
||||
let title_space = self.style.title.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR;
|
||||
|
||||
// Title of tooltip
|
||||
if !self.title_text.is_empty() {
|
||||
let title = widget::Text::new(self.title_text)
|
||||
.w(text_w)
|
||||
.graphics_for(id)
|
||||
.parent(id)
|
||||
.with_style(self.style.title)
|
||||
// Apply transparency
|
||||
.color(self.title_col);
|
||||
|
||||
if self.image.is_some() {
|
||||
title
|
||||
.right_from(state.ids.image, H_PAD)
|
||||
.align_top_of(state.ids.image)
|
||||
} else {
|
||||
title.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
|
||||
}
|
||||
.set(state.ids.title, ui);
|
||||
}
|
||||
|
||||
// Description of tooltip
|
||||
let desc = widget::Text::new(self.desc_text)
|
||||
.w(text_w)
|
||||
.graphics_for(id)
|
||||
.parent(id)
|
||||
// Apply transparency
|
||||
.color(style.desc.color(ui.theme()).alpha(self.transparency))
|
||||
.with_style(self.style.desc);
|
||||
|
||||
if !self.title_text.is_empty() {
|
||||
desc.down_from(state.ids.title, V_PAD * 0.5 + title_space)
|
||||
.align_left_of(state.ids.title)
|
||||
} else if self.image.is_some() {
|
||||
desc.right_from(state.ids.image, H_PAD)
|
||||
.align_top_of(state.ids.image)
|
||||
} else {
|
||||
desc.top_left_with_margins_on(state.ids.image_frame, V_PAD, H_PAD)
|
||||
}
|
||||
.set(state.ids.desc, ui);
|
||||
}
|
||||
|
||||
/// Default width is based on the description font size unless the text is
|
||||
/// small enough to fit on a single line
|
||||
fn default_x_dimension(&self, ui: &Ui) -> Dimension {
|
||||
let single_line_title_w = widget::Text::new(self.title_text)
|
||||
.with_style(self.style.title)
|
||||
.get_w(ui)
|
||||
.unwrap_or(0.0);
|
||||
let single_line_desc_w = widget::Text::new(self.desc_text)
|
||||
.with_style(self.style.desc)
|
||||
.get_w(ui)
|
||||
.unwrap_or(0.0);
|
||||
|
||||
let text_w = single_line_title_w.max(single_line_desc_w);
|
||||
let inner_w = if self.image.is_some() {
|
||||
match self.image_dims {
|
||||
Some((w, _)) => w + text_w + H_PAD,
|
||||
None => text_w / (1.0 - IMAGE_W_FRAC) + H_PAD,
|
||||
}
|
||||
} else {
|
||||
text_w
|
||||
};
|
||||
|
||||
let width =
|
||||
inner_w.min(self.style.desc.font_size(&ui.theme) as f64 * DEFAULT_CHAR_W) + 2.0 * H_PAD;
|
||||
Dimension::Absolute(width)
|
||||
}
|
||||
|
||||
fn default_y_dimension(&self, ui: &Ui) -> Dimension {
|
||||
let (text_w, image_w) = self.text_image_width(self.get_w(ui).unwrap_or(0.0));
|
||||
let title_h = if self.title_text.is_empty() {
|
||||
0.0
|
||||
} else {
|
||||
widget::Text::new(self.title_text)
|
||||
.with_style(self.style.title)
|
||||
.w(text_w)
|
||||
.get_h(ui)
|
||||
.unwrap_or(0.0)
|
||||
+ self.style.title.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR
|
||||
+ 0.5 * V_PAD
|
||||
};
|
||||
let desc_h = if self.desc_text.is_empty() {
|
||||
0.0
|
||||
} else {
|
||||
widget::Text::new(self.desc_text)
|
||||
.with_style(self.style.desc)
|
||||
.w(text_w)
|
||||
.get_h(ui)
|
||||
.unwrap_or(0.0)
|
||||
+ self.style.desc.font_size(&ui.theme) as f64 * TEXT_SPACE_FACTOR
|
||||
};
|
||||
// Image defaults to square shape
|
||||
let image_h = self.image_dims.map_or(image_w, |(_, h)| h);
|
||||
// Title height + desc height + padding/spacing
|
||||
let height = (title_h + desc_h).max(image_h) + 2.0 * V_PAD;
|
||||
Dimension::Absolute(height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Colorable for ItemTooltip<'a> {
|
||||
builder_method!(color { style.color = Some(Color) });
|
||||
}
|
@ -289,7 +289,7 @@ pub fn apply_caves_supplement<'a>(
|
||||
3 => match dynamic_rng.gen_range(0..2) {
|
||||
0 => comp::biped_large::Species::Blueoni,
|
||||
_ => comp::biped_large::Species::Redoni,
|
||||
}
|
||||
},
|
||||
_ => comp::biped_large::Species::Troll,
|
||||
};
|
||||
comp::biped_large::Body::random_with(dynamic_rng, &species).into()
|
||||
|
@ -119,6 +119,43 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.1,
|
||||
},
|
||||
// Tundra rock solitary ennemies
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(
|
||||
quadruped_low::Body::random_with(rng, &quadruped_low::Species::Rocksnapper)
|
||||
.into(),
|
||||
)
|
||||
.with_alignment(Alignment::Enemy)
|
||||
},
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * col.rock * 1.0
|
||||
},
|
||||
},
|
||||
// Taiga rare solitary ennemies
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..3) {
|
||||
0 => biped_large::Body::random_with(rng, &biped_large::Species::Wendigo)
|
||||
.into(),
|
||||
_ => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Dreadhorn,
|
||||
)
|
||||
.into(),
|
||||
})
|
||||
.with_alignment(Alignment::Enemy)
|
||||
},
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.2
|
||||
},
|
||||
},
|
||||
// Taiga pack ennemies
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
@ -166,7 +203,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..6) {
|
||||
.with_body(match rng.gen_range(0..5) {
|
||||
0 => {
|
||||
bird_medium::Body::random_with(rng, &bird_medium::Species::Eagle).into()
|
||||
},
|
||||
@ -181,11 +218,6 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
&quadruped_medium::Species::Moose,
|
||||
)
|
||||
.into(),
|
||||
4 => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Dreadhorn,
|
||||
)
|
||||
.into(),
|
||||
_ => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Tuskram,
|
||||
@ -198,22 +230,6 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| close(c.temp, CONFIG.snow_temp + 0.2, 0.6) * BASE_DENSITY * 5.0,
|
||||
},
|
||||
// Tundra rock solitary ennemies
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(
|
||||
quadruped_low::Body::random_with(rng, &quadruped_low::Species::Rocksnapper)
|
||||
.into(),
|
||||
)
|
||||
.with_alignment(Alignment::Enemy)
|
||||
},
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * col.rock * 1.0
|
||||
},
|
||||
},
|
||||
// Temperate solitary ennemies
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
@ -247,7 +263,10 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, col| {
|
||||
close(c.temp, CONFIG.temperate_temp, 0.35) * col.tree_density * BASE_DENSITY * 1.0
|
||||
close(c.temp, CONFIG.temperate_temp + 0.1, 0.5)
|
||||
* col.tree_density
|
||||
* BASE_DENSITY
|
||||
* 1.0
|
||||
},
|
||||
},
|
||||
// Temperate pack wild
|
||||
@ -318,8 +337,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..8,
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| {
|
||||
close(c.temp, CONFIG.temperate_temp, 0.5)
|
||||
* close(c.humidity, CONFIG.forest_hum, 0.4)
|
||||
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
|
||||
* close(c.humidity, CONFIG.forest_hum, 0.6)
|
||||
//* col.tree_density
|
||||
* BASE_DENSITY
|
||||
* 4.0
|
||||
@ -329,7 +348,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..12) {
|
||||
.with_body(match rng.gen_range(0..11) {
|
||||
0 => quadruped_small::Body {
|
||||
species: quadruped_small::Species::Fox,
|
||||
body_type: quadruped_small::BodyType::Male,
|
||||
@ -370,12 +389,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
&quadruped_medium::Species::Hirdrasil,
|
||||
)
|
||||
.into(),
|
||||
9 => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Kelpie,
|
||||
)
|
||||
.into(),
|
||||
10 => quadruped_small::Body::random_with(
|
||||
9 => quadruped_small::Body::random_with(
|
||||
rng,
|
||||
&quadruped_small::Species::Truffler,
|
||||
)
|
||||
@ -391,9 +405,9 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| {
|
||||
close(c.temp, CONFIG.temperate_temp, 0.5)
|
||||
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
|
||||
* BASE_DENSITY
|
||||
* close(c.humidity, CONFIG.forest_hum, 0.4)
|
||||
* close(c.humidity, CONFIG.forest_hum, 0.6)
|
||||
* 8.0
|
||||
},
|
||||
},
|
||||
@ -421,7 +435,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
Entry {
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(match rng.gen_range(0..3) {
|
||||
.with_body(match rng.gen_range(0..4) {
|
||||
0 => quadruped_small::Body::random_with(
|
||||
rng,
|
||||
&quadruped_small::Species::Beaver,
|
||||
@ -432,6 +446,11 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
body_type: quadruped_low::BodyType::Female,
|
||||
}
|
||||
.into(),
|
||||
2 => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Kelpie,
|
||||
)
|
||||
.into(),
|
||||
_ => {
|
||||
bird_medium::Body::random_with(rng, &bird_medium::Species::Duck).into()
|
||||
},
|
||||
@ -499,7 +518,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
.into()
|
||||
},
|
||||
1 => quadruped_low::Body::random_with(rng, &quadruped_low::Species::Asp)
|
||||
.into(),
|
||||
.into(),
|
||||
_ => quadruped_medium::Body::random_with(
|
||||
rng,
|
||||
&quadruped_medium::Species::Tiger,
|
||||
@ -511,8 +530,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| {
|
||||
close(c.temp, CONFIG.tropical_temp + 0.1, 0.3)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.3)
|
||||
close(c.temp, CONFIG.tropical_temp + 0.2, 0.2)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.2)
|
||||
* BASE_DENSITY
|
||||
* 3.0
|
||||
},
|
||||
@ -539,8 +558,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| {
|
||||
close(c.temp, CONFIG.tropical_temp + 0.1, 0.3)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.3)
|
||||
close(c.temp, CONFIG.tropical_temp + 0.2, 0.2)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.2)
|
||||
* BASE_DENSITY
|
||||
* 0.8
|
||||
},
|
||||
@ -573,8 +592,8 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
group_size: 1..2,
|
||||
is_underwater: false,
|
||||
get_density: |c, _col| {
|
||||
close(c.temp, CONFIG.tropical_temp, 0.4)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.3)
|
||||
close(c.temp, CONFIG.tropical_temp + 0.2, 0.3)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.2)
|
||||
* BASE_DENSITY
|
||||
* 8.0
|
||||
},
|
||||
@ -853,13 +872,12 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
make_entity: |pos, rng| {
|
||||
EntityInfo::at(pos)
|
||||
.with_body(
|
||||
quadruped_low::Body::random_with(rng, &quadruped_low::Species::Crocodile)
|
||||
.into(),
|
||||
fish_medium::Body::random_with(rng, &fish_medium::Species::Icepike).into(),
|
||||
)
|
||||
.with_alignment(Alignment::Enemy)
|
||||
},
|
||||
group_size: 1..3,
|
||||
is_underwater: false,
|
||||
is_underwater: true,
|
||||
get_density: |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.15) * col.tree_density * BASE_DENSITY * 5.0
|
||||
},
|
||||
|
@ -902,12 +902,11 @@ impl Settlement {
|
||||
object::Body::TrainingDummy.into()
|
||||
},
|
||||
0 => {
|
||||
let species = match dynamic_rng.gen_range(0..6) {
|
||||
let species = match dynamic_rng.gen_range(0..5) {
|
||||
0 => quadruped_small::Species::Pig,
|
||||
1 => quadruped_small::Species::Sheep,
|
||||
2 => quadruped_small::Species::Goat,
|
||||
3 => quadruped_small::Species::Dog,
|
||||
4 => quadruped_small::Species::Goat,
|
||||
_ => quadruped_small::Species::Cat,
|
||||
};
|
||||
is_human = false;
|
||||
|
Loading…
Reference in New Issue
Block a user