Make the camera zoom as the bow (or any ChargedRanged attack) is charging.

This commit is contained in:
Avi Weinstock 2021-05-22 15:50:29 -04:00
parent d7c7f6bf5d
commit 4d7828ec94
3 changed files with 32 additions and 15 deletions

View File

@ -62,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Chat tabs - Chat tabs
- NPC's now hear certain sounds - NPC's now hear certain sounds
- Renamed Animal Trainers to Beastmasters and gave them their own set of armor to wear - Renamed Animal Trainers to Beastmasters and gave them their own set of armor to wear
- ChargedRanged attacks (such as some bow attacks) use an FOV zoom effect to indicate charge.
- Add chest to each dungeon with unique loot - Add chest to each dungeon with unique loot
### Changed ### Changed

View File

@ -61,6 +61,13 @@ pub struct Data {
pub exhausted: bool, pub exhausted: bool,
} }
impl Data {
/// How complete the charge is, on a scale of 0.0 to 1.0
pub fn charge_frac(&self) -> f32 {
(self.timer.as_secs_f32() / self.static_data.charge_duration.as_secs_f32()).min(1.0)
}
}
impl CharacterBehavior for Data { impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate { fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data); let mut update = StateUpdate::from(data);
@ -91,9 +98,7 @@ impl CharacterBehavior for Data {
}, },
StageSection::Charge => { StageSection::Charge => {
if !input_is_pressed(data, self.static_data.ability_info.input) && !self.exhausted { if !input_is_pressed(data, self.static_data.ability_info.input) && !self.exhausted {
let charge_frac = (self.timer.as_secs_f32() let charge_frac = self.charge_frac();
/ self.static_data.charge_duration.as_secs_f32())
.min(1.0);
let arrow = ProjectileConstructor::Arrow { let arrow = ProjectileConstructor::Arrow {
damage: self.static_data.initial_damage as f32 damage: self.static_data.initial_damage as f32
+ charge_frac * self.static_data.scaled_damage as f32, + charge_frac * self.static_data.scaled_damage as f32,

View File

@ -295,6 +295,22 @@ impl PlayState for SessionState {
camera.set_orientation(cam_dir); camera.set_orientation(cam_dir);
} }
let client = self.client.borrow();
let player_entity = client.entity();
let fov_scaling = {
if let Some(comp::CharacterState::ChargedRanged(cr)) = client
.state()
.read_storage::<comp::CharacterState>()
.get(player_entity)
{
1.0 - 3.0 * cr.charge_frac() / 4.0
} else {
1.0
}
};
camera.set_fov((global_state.settings.graphics.fov as f32 * fov_scaling).to_radians());
// Compute camera data // Compute camera data
camera.compute_dependents(&*self.client.borrow().state().terrain()); camera.compute_dependents(&*self.client.borrow().state().terrain());
let camera::Dependents { let camera::Dependents {
@ -305,18 +321,17 @@ impl PlayState for SessionState {
let cam_pos = cam_pos + focus_off; let cam_pos = cam_pos + focus_off;
let (is_aiming, aim_dir_offset) = { let (is_aiming, aim_dir_offset) = {
let client = self.client.borrow();
let is_aiming = client let is_aiming = client
.state() .state()
.read_storage::<comp::CharacterState>() .read_storage::<comp::CharacterState>()
.get(client.entity()) .get(player_entity)
.map(|cs| cs.is_aimed()) .map(|cs| cs.is_aimed())
.unwrap_or(false); .unwrap_or(false);
( (
is_aiming, is_aiming,
if is_aiming && self.scene.camera().get_mode() == CameraMode::ThirdPerson { if is_aiming && self.scene.camera().get_mode() == CameraMode::ThirdPerson {
Vec3::unit_z() * 0.05 Vec3::unit_z() * 0.025
} else { } else {
Vec3::zero() Vec3::zero()
}, },
@ -324,25 +339,21 @@ impl PlayState for SessionState {
}; };
self.is_aiming = is_aiming; self.is_aiming = is_aiming;
let player_entity = self.client.borrow().entity(); let can_build = client
let can_build = self
.client
.borrow()
.state() .state()
.read_storage::<comp::CanBuild>() .read_storage::<comp::CanBuild>()
.get(player_entity) .get(player_entity)
.map_or_else(|| false, |cb| cb.enabled); .map_or_else(|| false, |cb| cb.enabled);
let is_mining = self let is_mining = client
.client
.borrow()
.inventories() .inventories()
.get(player_entity) .get(player_entity)
.and_then(|inv| inv.equipped(EquipSlot::ActiveMainhand)) .and_then(|inv| inv.equipped(EquipSlot::ActiveMainhand))
.and_then(|item| item.tool()) .and_then(|item| item.tool())
.map_or(false, |tool| tool.kind == ToolKind::Pick) .map_or(false, |tool| tool.kind == ToolKind::Pick)
&& self.client.borrow().is_wielding() == Some(true); && client.is_wielding() == Some(true);
drop(client);
// Check to see whether we're aiming at anything // Check to see whether we're aiming at anything
let (build_pos, select_pos, target_entity) = let (build_pos, select_pos, target_entity) =