mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added bosses, improved secret object spawn rates
This commit is contained in:
parent
6ff75dcf0b
commit
677c5781ba
@ -10,10 +10,20 @@ pub enum Agent {
|
||||
offset: Vec2<f32>,
|
||||
},
|
||||
Enemy {
|
||||
bearing: Vec2<f32>,
|
||||
target: Option<EcsEntity>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Agent {
|
||||
pub fn enemy() -> Self {
|
||||
Agent::Enemy {
|
||||
bearing: Vec2::zero(),
|
||||
target: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Agent {
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ pub use inputs::{
|
||||
};
|
||||
pub use inventory::{item, Inventory, InventoryUpdate, Item};
|
||||
pub use last::Last;
|
||||
pub use phys::{ForceUpdate, Ori, Pos, Vel};
|
||||
pub use phys::{ForceUpdate, Ori, Pos, Scale, Vel};
|
||||
pub use player::Player;
|
||||
pub use stats::{Dying, Exp, HealthSource, Level, Stats};
|
||||
pub use visual::LightEmitter;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use specs::{Component, NullStorage};
|
||||
use specs::{Component, FlaggedStorage, NullStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
use vek::*;
|
||||
|
||||
@ -26,6 +26,14 @@ impl Component for Ori {
|
||||
type Storage = IDVStorage<Self>;
|
||||
}
|
||||
|
||||
// Scale
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Scale(pub f32);
|
||||
|
||||
impl Component for Scale {
|
||||
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
|
||||
}
|
||||
|
||||
// ForceUpdate
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ForceUpdate;
|
||||
|
@ -34,18 +34,26 @@ impl Health {
|
||||
pub fn current(&self) -> u32 {
|
||||
self.current
|
||||
}
|
||||
|
||||
pub fn maximum(&self) -> u32 {
|
||||
self.maximum
|
||||
}
|
||||
|
||||
pub fn set_to(&mut self, amount: u32, cause: HealthSource) {
|
||||
let amount = amount.min(self.maximum);
|
||||
self.last_change = Some((amount as i32 - self.current as i32, 0.0, cause));
|
||||
self.current = amount;
|
||||
}
|
||||
|
||||
pub fn change_by(&mut self, amount: i32, cause: HealthSource) {
|
||||
self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum);
|
||||
self.last_change = Some((amount, 0.0, cause));
|
||||
}
|
||||
|
||||
pub fn set_current(&mut self, amount: u32) {
|
||||
self.current = amount.min(self.maximum);
|
||||
}
|
||||
|
||||
pub fn set_maximum(&mut self, amount: u32) {
|
||||
self.maximum = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
|
@ -26,6 +26,7 @@ sphynx::sum_type! {
|
||||
Stats(comp::Stats),
|
||||
LightEmitter(comp::LightEmitter),
|
||||
Item(comp::Item),
|
||||
Scale(comp::Scale),
|
||||
}
|
||||
}
|
||||
// Automatically derive From<T> for EcsCompPhantom
|
||||
@ -42,6 +43,7 @@ sphynx::sum_type! {
|
||||
Stats(PhantomData<comp::Stats>),
|
||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||
Item(PhantomData<comp::Item>),
|
||||
Scale(PhantomData<comp::Scale>),
|
||||
}
|
||||
}
|
||||
impl sphynx::CompPacket for EcsCompPacket {
|
||||
|
@ -132,6 +132,7 @@ impl State {
|
||||
ecs.register_synced::<comp::CanBuild>();
|
||||
ecs.register_synced::<comp::LightEmitter>();
|
||||
ecs.register_synced::<comp::Item>();
|
||||
ecs.register_synced::<comp::Scale>();
|
||||
|
||||
// Register components send from clients -> server
|
||||
ecs.register::<comp::Controller>();
|
||||
|
@ -58,7 +58,7 @@ impl<'a> System<'a> for Sys {
|
||||
* 10.0;
|
||||
}
|
||||
}
|
||||
Agent::Enemy { target } => {
|
||||
Agent::Enemy { bearing, target } => {
|
||||
let choose_new = match target.map(|tgt| positions.get(tgt)).flatten() {
|
||||
Some(tgt_pos) => {
|
||||
let dist = Vec2::<f32>::from(tgt_pos.0 - pos.0).magnitude();
|
||||
@ -80,7 +80,16 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
None => {
|
||||
controller.move_dir = Vec2::one();
|
||||
*bearing +=
|
||||
Vec2::new(rand::random::<f32>() - 0.5, rand::random::<f32>() - 0.5)
|
||||
* 0.1
|
||||
- *bearing * 0.01;
|
||||
|
||||
controller.move_dir = if bearing.magnitude_squared() > 0.5 {
|
||||
bearing.normalized()
|
||||
} else {
|
||||
Vec2::zero()
|
||||
};
|
||||
true
|
||||
}
|
||||
};
|
||||
|
@ -438,7 +438,7 @@ fn handle_help(server: &mut Server, entity: EcsEntity, _args: String, _action: &
|
||||
|
||||
fn alignment_to_agent(alignment: &str, target: EcsEntity) -> Option<comp::Agent> {
|
||||
match alignment {
|
||||
"hostile" => Some(comp::Agent::Enemy { target: None }),
|
||||
"hostile" => Some(comp::Agent::enemy()),
|
||||
"friendly" => Some(comp::Agent::Pet {
|
||||
target,
|
||||
offset: Vec2::zero(),
|
||||
|
@ -270,6 +270,17 @@ impl Server {
|
||||
|
||||
// Handle chunk supplement
|
||||
for npc in supplement.npcs {
|
||||
let mut stats = comp::Stats::new("Test".to_string());
|
||||
let mut body = comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random());
|
||||
let mut scale = 1.0;
|
||||
|
||||
if npc.boss {
|
||||
stats.health.set_maximum(400);
|
||||
stats.health.set_current(400);
|
||||
scale = 2.5;
|
||||
body = comp::Body::Humanoid(comp::humanoid::Body::random());
|
||||
}
|
||||
|
||||
self.state
|
||||
.ecs_mut()
|
||||
.create_entity_synced()
|
||||
@ -277,11 +288,11 @@ impl Server {
|
||||
.with(comp::Vel(Vec3::zero()))
|
||||
.with(comp::Ori(Vec3::unit_y()))
|
||||
.with(comp::Controller::default())
|
||||
.with(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
||||
.with(comp::Stats::new("Test".to_string()))
|
||||
.with(body)
|
||||
.with(stats)
|
||||
.with(comp::ActionState::default())
|
||||
.with(comp::Agent::Enemy { target: None })
|
||||
.with(comp::ForceUpdate)
|
||||
.with(comp::Agent::enemy())
|
||||
.with(comp::Scale(scale))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ impl Scene {
|
||||
renderer,
|
||||
Vec3::zero(),
|
||||
-Vec3::unit_y(),
|
||||
1.0,
|
||||
Rgba::broadcast(1.0),
|
||||
1.0 / 60.0, // TODO: Use actual deltatime here?
|
||||
);
|
||||
|
@ -624,11 +624,12 @@ impl FigureMgr {
|
||||
.get(client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
|
||||
for (entity, pos, vel, ori, body, animation_info, stats) in (
|
||||
for (entity, pos, vel, ori, scale, body, animation_info, stats) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<comp::Pos>(),
|
||||
&ecs.read_storage::<comp::Vel>(),
|
||||
&ecs.read_storage::<comp::Ori>(),
|
||||
ecs.read_storage::<comp::Scale>().maybe(),
|
||||
&ecs.read_storage::<comp::Body>(),
|
||||
ecs.read_storage::<comp::AnimationInfo>().maybe(),
|
||||
ecs.read_storage::<comp::Stats>().maybe(),
|
||||
@ -671,6 +672,8 @@ impl FigureMgr {
|
||||
})
|
||||
.unwrap_or(Rgba::broadcast(1.0));
|
||||
|
||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||
|
||||
let skeleton_attr = &self
|
||||
.model_cache
|
||||
.get_or_create_model(renderer, *body, tick)
|
||||
@ -750,7 +753,7 @@ impl FigureMgr {
|
||||
};
|
||||
|
||||
state.skeleton.interpolate(&target_skeleton, dt);
|
||||
state.update(renderer, pos.0, ori.0, col, dt);
|
||||
state.update(renderer, pos.0, ori.0, scale, col, dt);
|
||||
}
|
||||
Body::Quadruped(_) => {
|
||||
let state = self
|
||||
@ -788,7 +791,7 @@ impl FigureMgr {
|
||||
};
|
||||
|
||||
state.skeleton.interpolate(&target_skeleton, dt);
|
||||
state.update(renderer, pos.0, ori.0, col, dt);
|
||||
state.update(renderer, pos.0, ori.0, scale, col, dt);
|
||||
}
|
||||
Body::QuadrupedMedium(_) => {
|
||||
let state = self
|
||||
@ -834,7 +837,7 @@ impl FigureMgr {
|
||||
};
|
||||
|
||||
state.skeleton.interpolate(&target_skeleton, dt);
|
||||
state.update(renderer, pos.0, ori.0, col, dt);
|
||||
state.update(renderer, pos.0, ori.0, scale, col, dt);
|
||||
}
|
||||
Body::Object(_) => {
|
||||
let state = self
|
||||
@ -843,7 +846,7 @@ impl FigureMgr {
|
||||
.or_insert_with(|| FigureState::new(renderer, ObjectSkeleton::new()));
|
||||
|
||||
state.skeleton = state.skeleton_mut().clone();
|
||||
state.update(renderer, pos.0, ori.0, col, dt);
|
||||
state.update(renderer, pos.0, ori.0, scale, col, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -967,6 +970,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
renderer: &mut Renderer,
|
||||
pos: Vec3<f32>,
|
||||
ori: Vec3<f32>,
|
||||
scale: f32,
|
||||
col: Rgba<f32>,
|
||||
dt: f32,
|
||||
) {
|
||||
@ -982,7 +986,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
let mat = Mat4::<f32>::identity()
|
||||
* Mat4::translation_3d(self.pos)
|
||||
* Mat4::rotation_z(-ori.x.atan2(ori.y))
|
||||
* Mat4::scaling_3d(Vec3::from(0.8));
|
||||
* Mat4::scaling_3d(Vec3::from(0.8 * scale));
|
||||
|
||||
let locals = FigureLocals::new(mat, col);
|
||||
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
||||
|
@ -43,7 +43,7 @@ pub fn structure_gen<'a>(
|
||||
let wheight = st_sample.alt.max(cliff_height);
|
||||
let st_pos3d = Vec3::new(st_pos.x, st_pos.y, wheight as i32);
|
||||
|
||||
let volumes: &'static [_] = if QUIRKY_RAND.get(st_seed) % 64 == 17 {
|
||||
let volumes: &'static [_] = if QUIRKY_RAND.get(st_seed) % 512 == 17 {
|
||||
if st_sample.temp > CONFIG.desert_temp {
|
||||
&QUIRKY_DRY
|
||||
} else {
|
||||
|
@ -131,10 +131,12 @@ impl World {
|
||||
};
|
||||
|
||||
const SPAWN_RATE: f32 = 0.1;
|
||||
const BOSS_RATE: f32 = 0.1;
|
||||
let supplement = ChunkSupplement {
|
||||
npcs: if rand::thread_rng().gen::<f32>() < SPAWN_RATE && sim_chunk.chaos < 0.5 {
|
||||
vec![NpcInfo {
|
||||
pos: gen_entity_pos(),
|
||||
boss: rand::thread_rng().gen::<f32>() < BOSS_RATE,
|
||||
}]
|
||||
} else {
|
||||
Vec::new()
|
||||
@ -147,6 +149,7 @@ impl World {
|
||||
|
||||
pub struct NpcInfo {
|
||||
pub pos: Vec3<f32>,
|
||||
pub boss: bool,
|
||||
}
|
||||
|
||||
pub struct ChunkSupplement {
|
||||
|
Loading…
Reference in New Issue
Block a user