mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Doors can be opened and closed with interaction key (logic for door interaction, code for input event, 2 new vox files)
This commit is contained in:
parent
3239fc1f2f
commit
5f077e880d
BIN
assets/voxygen/voxel/sprite/door/door-1.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/door/door-1.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/door/door-2.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/door/door-2.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -545,6 +545,14 @@ impl Client {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn interact_with_door(&mut self, pos: Vec3<i32>) {
|
||||
self.singleton_stream
|
||||
.send(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::DoorInteraction(pos),
|
||||
)))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn collect_block(&mut self, pos: Vec3<i32>) {
|
||||
self.singleton_stream
|
||||
.send(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
|
||||
|
@ -12,6 +12,7 @@ pub const DEFAULT_HOLD_DURATION: Duration = Duration::from_millis(200);
|
||||
pub enum InventoryManip {
|
||||
Pickup(Uid),
|
||||
Collect(Vec3<i32>),
|
||||
DoorInteraction(Vec3<i32>),
|
||||
Use(Slot),
|
||||
Swap(Slot, Slot),
|
||||
Drop(Slot),
|
||||
@ -153,6 +154,7 @@ pub struct ControllerInputs {
|
||||
pub secondary: Input,
|
||||
pub ability3: Input,
|
||||
pub jump: Input,
|
||||
pub interact: Input,
|
||||
pub roll: Input,
|
||||
pub glide: Input,
|
||||
pub wall_leap: Input,
|
||||
@ -178,6 +180,7 @@ impl ControllerInputs {
|
||||
self.secondary.tick(dt);
|
||||
self.ability3.tick(dt);
|
||||
self.jump.tick(dt);
|
||||
self.interact.tick(dt);
|
||||
self.roll.tick(dt);
|
||||
self.glide.tick(dt);
|
||||
self.wall_leap.tick(dt);
|
||||
@ -190,6 +193,7 @@ impl ControllerInputs {
|
||||
self.secondary.tick_freshness();
|
||||
self.ability3.tick_freshness();
|
||||
self.jump.tick_freshness();
|
||||
self.interact.tick_freshness();
|
||||
self.roll.tick_freshness();
|
||||
self.glide.tick_freshness();
|
||||
self.wall_leap.tick_freshness();
|
||||
@ -203,6 +207,7 @@ impl ControllerInputs {
|
||||
self.secondary.update_with_new(new.secondary);
|
||||
self.ability3.update_with_new(new.ability3);
|
||||
self.jump.update_with_new(new.jump);
|
||||
self.interact.update_with_new(new.interact);
|
||||
self.roll.update_with_new(new.roll);
|
||||
self.glide.update_with_new(new.glide);
|
||||
self.wall_leap.update_with_new(new.wall_leap);
|
||||
|
@ -61,6 +61,8 @@ pub enum BlockKind {
|
||||
StreetLamp,
|
||||
StreetLampTall,
|
||||
Door,
|
||||
DoorOpen1,
|
||||
DoorOpen2,
|
||||
Bed,
|
||||
Bench,
|
||||
ChairSingle,
|
||||
@ -95,6 +97,13 @@ impl BlockKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_tangible2(&self) -> bool {
|
||||
match self {
|
||||
BlockKind::Air => false,
|
||||
kind => !kind.is_fluid(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_air(&self) -> bool {
|
||||
match self {
|
||||
BlockKind::Air => true,
|
||||
@ -146,6 +155,8 @@ impl BlockKind {
|
||||
BlockKind::StreetLamp => true,
|
||||
BlockKind::StreetLampTall => true,
|
||||
BlockKind::Door => false,
|
||||
BlockKind::DoorOpen1 => false,
|
||||
BlockKind::DoorOpen2 => false,
|
||||
BlockKind::Bed => false,
|
||||
BlockKind::Bench => false,
|
||||
BlockKind::ChairSingle => false,
|
||||
@ -230,6 +241,8 @@ impl BlockKind {
|
||||
BlockKind::StreetLamp => false,
|
||||
BlockKind::StreetLampTall => false,
|
||||
BlockKind::Door => false,
|
||||
BlockKind::DoorOpen1 => false,
|
||||
BlockKind::DoorOpen2 => false,
|
||||
BlockKind::Bed => false,
|
||||
BlockKind::Bench => false,
|
||||
BlockKind::ChairSingle => false,
|
||||
@ -301,7 +314,9 @@ impl BlockKind {
|
||||
BlockKind::Scarecrow => true,
|
||||
BlockKind::StreetLamp => true,
|
||||
BlockKind::StreetLampTall => true,
|
||||
BlockKind::Door => false,
|
||||
BlockKind::Door => true,
|
||||
BlockKind::DoorOpen1 => false,
|
||||
BlockKind::DoorOpen2 => false,
|
||||
BlockKind::Bed => true,
|
||||
BlockKind::Bench => true,
|
||||
BlockKind::ChairSingle => true,
|
||||
@ -350,6 +365,8 @@ impl BlockKind {
|
||||
BlockKind::Carrot => 0.18,
|
||||
BlockKind::Radish => 0.18,
|
||||
BlockKind::Door => 3.0,
|
||||
BlockKind::DoorOpen1 => 3.0,
|
||||
BlockKind::DoorOpen2 => 3.0,
|
||||
BlockKind::Bed => 1.54,
|
||||
BlockKind::Bench => 1.45,
|
||||
BlockKind::ChairSingle => 1.36,
|
||||
@ -389,6 +406,18 @@ impl BlockKind {
|
||||
BlockKind::VeloriteFrag => true,
|
||||
BlockKind::Chest => true,
|
||||
BlockKind::Coconut => true,
|
||||
BlockKind::Door => false,
|
||||
BlockKind::DoorOpen1 => false,
|
||||
BlockKind::DoorOpen2 => false,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_interactable_terrain(&self) -> bool {
|
||||
match self {
|
||||
BlockKind::Door => true,
|
||||
BlockKind::DoorOpen1 => true,
|
||||
BlockKind::DoorOpen2 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -423,6 +452,8 @@ impl Block {
|
||||
| BlockKind::Window2
|
||||
| BlockKind::Window3
|
||||
| BlockKind::Window4
|
||||
| BlockKind::DoorOpen1
|
||||
| BlockKind::DoorOpen2
|
||||
| BlockKind::Door => Some(self.color[0] & 0b111),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use common::{
|
||||
Pos, MAX_PICKUP_RANGE_SQR,
|
||||
},
|
||||
sync::{Uid, WorldSyncExt},
|
||||
terrain::block::Block,
|
||||
terrain::{Block, BlockKind},
|
||||
vol::{ReadVol, Vox},
|
||||
};
|
||||
use rand::Rng;
|
||||
@ -92,6 +92,83 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
state.write_component(entity, event);
|
||||
},
|
||||
|
||||
// the interaction of opening and closing doors
|
||||
// this might be better off in a different class
|
||||
comp::InventoryManip::DoorInteraction(pos) => {
|
||||
let first_door = state.terrain().get(pos).ok().copied();
|
||||
|
||||
if let Some(first_door) = first_door {
|
||||
// check for block that is supported by this interaction (in case this method gets extended)
|
||||
if first_door.is_interactable_terrain() {
|
||||
|
||||
if first_door.kind() == BlockKind::Door {
|
||||
|
||||
let ori = first_door.get_ori().unwrap();
|
||||
let color = first_door.get_color().unwrap();
|
||||
|
||||
// the orientation of doors is saved in the first 'color' as the rgb color is not needed
|
||||
// the orientation is a value between 0 and 7, the function get ori retrieves a value modulo 8 automatically
|
||||
// the left and right closed doors facing in the same direction have different orientation so we add the difference (difference of 4, modulo 8)
|
||||
let rgb = [ori + 4, color[1], color[2]].into();
|
||||
state.try_set_block(pos, Block::new(BlockKind::DoorOpen2, rgb));
|
||||
|
||||
// TODO add a sound effect for 'opening' doors here
|
||||
|
||||
// calculate where to look for a second door
|
||||
let mut pos2 = pos.clone();
|
||||
if ori == 0 { pos2 += (1,0,0); }
|
||||
else if ori == 2 { pos2 += (0,1,0); }
|
||||
else if ori == 4 { pos2 += (-1,0,0); }
|
||||
else if ori == 6 { pos2 += (0,-1,0); }
|
||||
|
||||
let second_door = state.terrain().get(pos2).ok().copied().unwrap();
|
||||
|
||||
// check if there is a fitting door there
|
||||
if second_door.kind() == BlockKind::Door {
|
||||
if second_door.get_ori().unwrap() == (ori + 4) & 0b111 {
|
||||
state.try_set_block(pos2, Block::new(BlockKind::DoorOpen1, rgb));
|
||||
}
|
||||
}
|
||||
} else if first_door.kind() == BlockKind::DoorOpen1 || first_door.kind() == BlockKind::DoorOpen2 {
|
||||
|
||||
let ori = first_door.get_ori().unwrap();
|
||||
let color = first_door.get_color().unwrap();
|
||||
|
||||
// same as above, but only needed for open door 2
|
||||
let rgb = [ori + 4, color[1], color[2]].into();
|
||||
|
||||
if first_door.kind() == BlockKind::DoorOpen1 {
|
||||
state.try_set_block(pos, Block::new(BlockKind::Door, color));
|
||||
}else{
|
||||
state.try_set_block(pos, Block::new(BlockKind::Door, rgb));
|
||||
}
|
||||
|
||||
// TODO add a sound effect for 'closing' doors here
|
||||
|
||||
// calculate where to look for a second door
|
||||
// (cant think of a smarter way to do this for the case of closing doors. kind and ori is not enough anymore to differentiate left and right)
|
||||
let positions = [(1,0,0),(0,1,0),(-1,0,0),(0,-1,0)];
|
||||
|
||||
for i in 0..4 {
|
||||
let pos2 = pos.clone() + positions[i];
|
||||
let second_door = state.terrain().get(pos2).ok().copied().unwrap();
|
||||
|
||||
//check if there is a fitting door there
|
||||
if second_door.kind() == BlockKind::DoorOpen1 || second_door.kind() == BlockKind::DoorOpen2 {
|
||||
if second_door.kind() != first_door.kind() {
|
||||
if second_door.kind() == BlockKind::DoorOpen1 {
|
||||
state.try_set_block(pos2, Block::new(BlockKind::Door, color));
|
||||
}else{
|
||||
state.try_set_block(pos2, Block::new(BlockKind::Door, rgb));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
comp::InventoryManip::Collect(pos) => {
|
||||
let block = state.terrain().get(pos).ok().copied();
|
||||
|
||||
|
@ -254,6 +254,14 @@ fn sprite_config_for(kind: BlockKind) -> Option<SpriteConfig> {
|
||||
variations: 1,
|
||||
wind_sway: 0.0,
|
||||
}),
|
||||
BlockKind::DoorOpen1 => Some(SpriteConfig {
|
||||
variations: 1,
|
||||
wind_sway: 0.0,
|
||||
}),
|
||||
BlockKind::DoorOpen2 => Some(SpriteConfig {
|
||||
variations: 1,
|
||||
wind_sway: 0.0,
|
||||
}),
|
||||
BlockKind::Bed => Some(SpriteConfig {
|
||||
variations: 1,
|
||||
wind_sway: 0.0,
|
||||
@ -2178,6 +2186,22 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
Vec3::one(),
|
||||
),
|
||||
),
|
||||
(
|
||||
(BlockKind::DoorOpen1, 0),
|
||||
make_models(
|
||||
"voxygen.voxel.sprite.door.door-1",
|
||||
Vec3::new(-5.5, -5.5, 0.0),
|
||||
Vec3::one(),
|
||||
),
|
||||
),
|
||||
(
|
||||
(BlockKind::DoorOpen2, 0),
|
||||
make_models(
|
||||
"voxygen.voxel.sprite.door.door-2",
|
||||
Vec3::new(-5.5, -5.5, 0.0),
|
||||
Vec3::one(),
|
||||
),
|
||||
),
|
||||
// Bed
|
||||
(
|
||||
(BlockKind::Bed, 0),
|
||||
|
@ -268,7 +268,7 @@ impl PlayState for SessionState {
|
||||
.state()
|
||||
.terrain()
|
||||
.get(*sp)
|
||||
.map(|b| b.is_collectible() || can_build)
|
||||
.map(|b| b.is_collectible() || can_build || b.is_interactable_terrain())
|
||||
.unwrap_or(false)
|
||||
}));
|
||||
|
||||
@ -453,9 +453,13 @@ impl PlayState for SessionState {
|
||||
},
|
||||
Event::InputUpdate(GameInput::Interact, state) => {
|
||||
let mut client = self.client.borrow_mut();
|
||||
self.inputs.interact.set_state(state);
|
||||
|
||||
// Collect terrain sprites
|
||||
if let Some(select_pos) = self.scene.select_pos() {
|
||||
if self.inputs.interact.is_just_pressed() {
|
||||
client.interact_with_door(select_pos);
|
||||
}
|
||||
client.collect_block(select_pos);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user