mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
/airship angle
command and RtSim airships.
This commit is contained in:
parent
64cc97ad59
commit
0b954f8db8
@ -224,7 +224,7 @@ impl ChatCommand {
|
|||||||
"Temporarily gives a player admin permissions or removes them",
|
"Temporarily gives a player admin permissions or removes them",
|
||||||
Admin,
|
Admin,
|
||||||
),
|
),
|
||||||
ChatCommand::Airship => cmd(vec![Boolean("moving", "true".to_string(), Optional)], "Spawns an airship", Admin),
|
ChatCommand::Airship => cmd(vec![Float("destination_degrees_ccw_of_east", 90.0, Optional)], "Spawns an airship", Admin),
|
||||||
ChatCommand::Alias => cmd(vec![Any("name", Required)], "Change your alias", NoAdmin),
|
ChatCommand::Alias => cmd(vec![Any("name", Required)], "Change your alias", NoAdmin),
|
||||||
ChatCommand::Ban => cmd(
|
ChatCommand::Ban => cmd(
|
||||||
vec![Any("username", Required), Message(Optional)],
|
vec![Any("username", Required), Message(Optional)],
|
||||||
|
@ -205,11 +205,11 @@ impl Agent {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_destination() -> Self {
|
pub fn with_destination(pos: Vec3<f32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
can_speak: false,
|
can_speak: true,
|
||||||
psyche: Psyche { aggro: 1.0 },
|
psyche: Psyche { aggro: 1.0 },
|
||||||
rtsim_controller: RtSimController::zero(),
|
rtsim_controller: RtSimController::with_destination(pos),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,6 +509,16 @@ impl Body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn flying_height(&self) -> f32 {
|
||||||
|
match self {
|
||||||
|
Body::BirdSmall(_) => 30.0,
|
||||||
|
Body::BirdMedium(_) => 40.0,
|
||||||
|
Body::Dragon(_) => 60.0,
|
||||||
|
Body::Ship(ship::Body::DefaultAirship) => 60.0,
|
||||||
|
_ => 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn immune_to(&self, buff: BuffKind) -> bool {
|
pub fn immune_to(&self, buff: BuffKind) -> bool {
|
||||||
match buff {
|
match buff {
|
||||||
BuffKind::Bleeding => matches!(self, Body::Object(_) | Body::Golem(_) | Body::Ship(_)),
|
BuffKind::Bleeding => matches!(self, Body::Object(_) | Body::Golem(_) | Body::Ship(_)),
|
||||||
|
@ -46,10 +46,10 @@ impl Default for RtSimController {
|
|||||||
|
|
||||||
impl RtSimController {
|
impl RtSimController {
|
||||||
pub fn reset(&mut self) { *self = Self::default(); }
|
pub fn reset(&mut self) { *self = Self::default(); }
|
||||||
pub fn zero() -> Self {
|
pub fn with_destination(pos: Vec3<f32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
travel_to: Some((Vec3::new(0.0, 0.0, 500.0), "".to_string())),
|
travel_to: Some((pos, format!("{:0.1?}", pos))),
|
||||||
speed_factor: 0.05,
|
speed_factor: 0.25,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -965,13 +965,16 @@ fn handle_spawn_airship(
|
|||||||
args: String,
|
args: String,
|
||||||
action: &ChatCommand,
|
action: &ChatCommand,
|
||||||
) {
|
) {
|
||||||
let moving = scan_fmt_some!(&args, &action.arg_fmt(), String).unwrap_or_else(|| "false".to_string()) == "true";
|
let angle = scan_fmt!(&args, &action.arg_fmt(), f32).ok();
|
||||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||||
Some(mut pos) => {
|
Some(mut pos) => {
|
||||||
pos.0.z += 50.0;
|
pos.0.z += 50.0;
|
||||||
|
const DESTINATION_RADIUS: f32 = 2000.0;
|
||||||
|
let angle = angle.map(|a| a * std::f32::consts::PI / 180.0);
|
||||||
|
let destination = angle.map(|a| pos.0 + Vec3::new(DESTINATION_RADIUS*a.cos(), DESTINATION_RADIUS*a.sin(), 200.0));
|
||||||
server
|
server
|
||||||
.state
|
.state
|
||||||
.create_ship(pos, comp::ship::Body::DefaultAirship, 1, moving)
|
.create_ship(pos, comp::ship::Body::DefaultAirship, 1, destination)
|
||||||
.with(comp::Scale(11.0 / 0.8))
|
.with(comp::Scale(11.0 / 0.8))
|
||||||
.with(LightEmitter {
|
.with(LightEmitter {
|
||||||
col: Rgb::new(1.0, 0.65, 0.2),
|
col: Rgb::new(1.0, 0.65, 0.2),
|
||||||
|
@ -27,7 +27,7 @@ impl Entity {
|
|||||||
|
|
||||||
pub fn get_body(&self) -> comp::Body {
|
pub fn get_body(&self) -> comp::Body {
|
||||||
match self.rng(PERM_GENUS).gen::<f32>() {
|
match self.rng(PERM_GENUS).gen::<f32>() {
|
||||||
//we want 50% birds, 50% humans for now
|
//we want 5% airships, 45% birds, 50% humans
|
||||||
x if x < 0.05 => {
|
x if x < 0.05 => {
|
||||||
comp::Body::Ship(comp::ship::Body::DefaultAirship)
|
comp::Body::Ship(comp::ship::Body::DefaultAirship)
|
||||||
},
|
},
|
||||||
@ -135,7 +135,7 @@ impl Entity {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|s| match self.get_body() {
|
.filter(|s| match self.get_body() {
|
||||||
comp::Body::Humanoid(_) => s.1.is_settlement() | s.1.is_castle(),
|
comp::Body::Humanoid(_) => s.1.is_settlement() | s.1.is_castle(),
|
||||||
comp::Body::Ship(_) => s.1.is_castle(),
|
comp::Body::Ship(_) => s.1.is_settlement(),
|
||||||
_ => s.1.is_dungeon(),
|
_ => s.1.is_dungeon(),
|
||||||
})
|
})
|
||||||
.filter(|_| thread_rng().gen_range(0i32..4) == 0)
|
.filter(|_| thread_rng().gen_range(0i32..4) == 0)
|
||||||
|
@ -121,7 +121,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
comp::Body::Humanoid(_) => comp::Alignment::Npc,
|
comp::Body::Humanoid(_) => comp::Alignment::Npc,
|
||||||
_ => comp::Alignment::Wild,
|
_ => comp::Alignment::Wild,
|
||||||
},
|
},
|
||||||
scale: comp::Scale(1.0),
|
scale: match body {
|
||||||
|
comp::Body::Ship(_) => comp::Scale(11.0 / 0.8),
|
||||||
|
_ => comp::Scale(1.0),
|
||||||
|
},
|
||||||
drop_item: None,
|
drop_item: None,
|
||||||
home_chunk: None,
|
home_chunk: None,
|
||||||
rtsim_entity: Some(RtSimEntity(id)),
|
rtsim_entity: Some(RtSimEntity(id)),
|
||||||
|
@ -41,7 +41,13 @@ pub trait StateExt {
|
|||||||
) -> EcsEntityBuilder;
|
) -> EcsEntityBuilder;
|
||||||
/// Build a static object entity
|
/// Build a static object entity
|
||||||
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder;
|
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder;
|
||||||
fn create_ship(&mut self, pos: comp::Pos, ship: comp::ship::Body, level: u16, moving: bool) -> EcsEntityBuilder;
|
fn create_ship(
|
||||||
|
&mut self,
|
||||||
|
pos: comp::Pos,
|
||||||
|
ship: comp::ship::Body,
|
||||||
|
level: u16,
|
||||||
|
destination: Option<Vec3<f32>>,
|
||||||
|
) -> EcsEntityBuilder;
|
||||||
/// Build a projectile
|
/// Build a projectile
|
||||||
fn create_projectile(
|
fn create_projectile(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -161,10 +167,15 @@ impl StateExt for State {
|
|||||||
))
|
))
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.with(comp::Collider::Box {
|
.with(match body {
|
||||||
radius: body.radius(),
|
comp::Body::Ship(ship) => comp::Collider::Voxel {
|
||||||
z_min: 0.0,
|
id: ship.manifest_entry().to_string(),
|
||||||
z_max: body.height(),
|
},
|
||||||
|
_ => comp::Collider::Box {
|
||||||
|
radius: body.radius(),
|
||||||
|
z_min: 0.0,
|
||||||
|
z_max: body.height(),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.with(comp::Controller::default())
|
.with(comp::Controller::default())
|
||||||
.with(body)
|
.with(body)
|
||||||
@ -203,46 +214,38 @@ impl StateExt for State {
|
|||||||
.with(comp::Gravity(1.0))
|
.with(comp::Gravity(1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_ship(&mut self, pos: comp::Pos, ship: comp::ship::Body, level: u16, moving: bool) -> EcsEntityBuilder {
|
fn create_ship(
|
||||||
if moving {
|
&mut self,
|
||||||
self.ecs_mut()
|
pos: comp::Pos,
|
||||||
.create_entity_synced()
|
ship: comp::ship::Body,
|
||||||
.with(pos)
|
level: u16,
|
||||||
.with(comp::Vel(Vec3::zero()))
|
destination: Option<Vec3<f32>>,
|
||||||
.with(comp::Ori::default())
|
) -> EcsEntityBuilder {
|
||||||
.with(comp::Mass(50.0))
|
let mut builder = self
|
||||||
.with(comp::Collider::Voxel { id: ship.manifest_entry().to_string() })
|
.ecs_mut()
|
||||||
.with(comp::Body::Ship(ship))
|
.create_entity_synced()
|
||||||
.with(comp::Gravity(1.0))
|
.with(pos)
|
||||||
.with(comp::Controller::default())
|
.with(comp::Vel(Vec3::zero()))
|
||||||
.with(comp::inventory::Inventory::new_empty())
|
.with(comp::Ori::default())
|
||||||
.with(comp::CharacterState::default())
|
.with(comp::Mass(50.0))
|
||||||
.with(comp::Energy::new(ship.into(), level))
|
.with(comp::Collider::Voxel {
|
||||||
.with(comp::Health::new(ship.into(), level))
|
id: ship.manifest_entry().to_string(),
|
||||||
.with(comp::Stats::new("Airship".to_string()))
|
})
|
||||||
.with(comp::MountState::Unmounted)
|
.with(comp::Body::Ship(ship))
|
||||||
.with(comp::Buffs::default())
|
.with(comp::Gravity(1.0))
|
||||||
.with(comp::Combo::default())
|
.with(comp::Controller::default())
|
||||||
.with(comp::Agent::with_destination())
|
.with(comp::inventory::Inventory::new_empty())
|
||||||
} else {
|
.with(comp::CharacterState::default())
|
||||||
self.ecs_mut()
|
.with(comp::Energy::new(ship.into(), level))
|
||||||
.create_entity_synced()
|
.with(comp::Health::new(ship.into(), level))
|
||||||
.with(pos)
|
.with(comp::Stats::new("Airship".to_string()))
|
||||||
.with(comp::Vel(Vec3::zero()))
|
.with(comp::Buffs::default())
|
||||||
.with(comp::Ori::default())
|
.with(comp::MountState::Unmounted)
|
||||||
.with(comp::Mass(50.0))
|
.with(comp::Combo::default());
|
||||||
.with(comp::Collider::Voxel { id: ship.manifest_entry().to_string() })
|
if let Some(pos) = destination {
|
||||||
.with(comp::Body::Ship(ship))
|
builder = builder.with(comp::Agent::with_destination(pos))
|
||||||
.with(comp::Gravity(1.0))
|
|
||||||
.with(comp::Controller::default())
|
|
||||||
.with(comp::inventory::Inventory::new_empty())
|
|
||||||
.with(comp::CharacterState::default())
|
|
||||||
.with(comp::Energy::new(ship.into(), level))
|
|
||||||
.with(comp::Health::new(ship.into(), level))
|
|
||||||
.with(comp::Stats::new("Airship".to_string()))
|
|
||||||
.with(comp::Buffs::default())
|
|
||||||
.with(comp::Combo::default())
|
|
||||||
}
|
}
|
||||||
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_projectile(
|
fn create_projectile(
|
||||||
|
@ -32,7 +32,7 @@ use specs::{
|
|||||||
Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World,
|
Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World,
|
||||||
Write, WriteStorage,
|
Write, WriteStorage,
|
||||||
};
|
};
|
||||||
use std::f32::consts::PI;
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
struct AgentData<'a> {
|
struct AgentData<'a> {
|
||||||
@ -81,6 +81,7 @@ pub struct ReadData<'a> {
|
|||||||
//ReadStorage<'a, Invite>,
|
//ReadStorage<'a, Invite>,
|
||||||
time_of_day: Read<'a, TimeOfDay>,
|
time_of_day: Read<'a, TimeOfDay>,
|
||||||
light_emitter: ReadStorage<'a, LightEmitter>,
|
light_emitter: ReadStorage<'a, LightEmitter>,
|
||||||
|
world: ReadExpect<'a, Arc<world::World>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is 3.1 to last longer than the last damage timer (3.0 seconds)
|
// This is 3.1 to last longer than the last damage timer (3.0 seconds)
|
||||||
@ -603,6 +604,29 @@ impl<'a> AgentData<'a> {
|
|||||||
.cast()
|
.cast()
|
||||||
.1
|
.1
|
||||||
.map_or(true, |b| b.is_some())
|
.map_or(true, |b| b.is_some())
|
||||||
|
|| self
|
||||||
|
.body
|
||||||
|
.map(|body| {
|
||||||
|
let height_approx = self.pos.0.y
|
||||||
|
- read_data
|
||||||
|
.world
|
||||||
|
.sim()
|
||||||
|
.get_alt_approx(self.pos.0.xy().map(|x: f32| x as i32))
|
||||||
|
.unwrap_or(0.0);
|
||||||
|
|
||||||
|
height_approx < body.flying_height()
|
||||||
|
|| read_data
|
||||||
|
.terrain
|
||||||
|
.ray(
|
||||||
|
self.pos.0,
|
||||||
|
self.pos.0 - body.flying_height() * Vec3::unit_z(),
|
||||||
|
)
|
||||||
|
.until(|b: &Block| b.is_solid() || b.is_liquid())
|
||||||
|
.cast()
|
||||||
|
.1
|
||||||
|
.map_or(false, |b| b.is_some())
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
1.0 //fly up when approaching obstacles
|
1.0 //fly up when approaching obstacles
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user