Added bosses, improved secret object spawn rates

This commit is contained in:
Joshua Barretto 2019-08-02 19:56:37 +01:00
parent 6ff75dcf0b
commit 677c5781ba
13 changed files with 73 additions and 16 deletions

View File

@ -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>;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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>();

View File

@ -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
}
};

View File

@ -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(),

View File

@ -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();
}
}

View File

@ -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?
);

View File

@ -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();

View File

@ -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 {

View File

@ -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 {