First 3 abilities for tidal warrior functional. Added bubble particles.

This commit is contained in:
Sam 2021-05-23 19:45:22 -05:00
parent 59ae5ec573
commit c81e1534f7
31 changed files with 184 additions and 32 deletions

View File

@ -109,9 +109,12 @@
abilities: [],
),
Custom("Tidal Claws"): (
primary: "common.abilities.staff.flamethrower",
secondary: "common.abilities.custom.wendigomagic.singlestrike",
abilities: [],
primary: "common.abilities.custom.tidalwarrior.pincer",
secondary: "common.abilities.custom.tidalwarrior.scuttle",
abilities: [
(None, "common.abilities.custom.tidalwarrior.bubbles"),
(None, "common.abilities.custom.tidalwarrior.totem"),
],
),
Custom("Quad Med Quick"): (
primary: "common.abilities.custom.quadmedquick.triplestrike",

View File

@ -3,7 +3,7 @@ BasicMelee(
buildup_duration: 0.25,
swing_duration: 0.1,
recover_duration: 0.25,
knockback: 25.0,
knockback: ( strength: 25.0, direction: Away),
base_damage: 200,
base_poise_damage: 40,
range: 5.0,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.5,
base_damage: 200,
base_poise_damage: 50,
knockback: 10.0,
knockback: ( strength: 10.0, direction: Away),
range: 4.0,
max_angle: 45.0,
damage_effect: None,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.6,
base_damage: 150.0,
base_poise_damage: 60.0,
knockback: 15.0,
knockback: ( strength: 15.0, direction: Away),
range: 5.0,
max_angle: 60.0,
damage_effect: Some(Buff((

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.35,
base_damage: 100,
base_poise_damage: 28,
knockback: 25.0,
knockback: ( strength: 25.0, direction: Away),
range: 1.2,
max_angle: 50.0,
damage_effect: None,

View File

@ -0,0 +1,19 @@
BasicBeam(
buildup_duration: 0.5,
recover_duration: 0.5,
beam_duration: 2.5,
damage: 100,
tick_rate: 2.0,
range: 25.0,
max_angle: 15.0,
damage_effect: Some(Buff((
kind: Wet,
dur_secs: 15.0,
strength: Value(4.5),
chance: 0.25,
))),
energy_regen: 0,
energy_drain: 0,
orientation_behavior: Normal,
specifier: Bubbles,
)

View File

@ -0,0 +1,13 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.3,
swing_duration: 0.1,
recover_duration: 0.6,
base_damage: 50.0,
base_poise_damage: 0.0,
knockback: ( strength: 100.0, direction: Towards),
range: 5.0,
max_angle: 60.0,
damage_effect: None,
damage_kind: Crushing,
)

View File

@ -0,0 +1,20 @@
DashMelee(
energy_cost: 0,
base_damage: 50,
scaled_damage: 250,
base_poise_damage: 10,
scaled_poise_damage: 40,
base_knockback: 10.0,
scaled_knockback: 30.0,
range: 5.0,
angle: 90.0,
energy_drain: 0,
forward_speed: 10.0,
buildup_duration: 0.4,
charge_duration: 2.0,
swing_duration: 0.1,
recover_duration: 0.5,
charge_through: false,
is_interruptible: false,
damage_kind: Crushing,
)

View File

@ -0,0 +1,18 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.3,
swing_duration: 0.1,
recover_duration: 0.6,
base_damage: 50.0,
base_poise_damage: 100.0,
knockback: ( strength: 50.0, direction: Towards),
range: 5.0,
max_angle: 60.0,
damage_effect: Some(Buff((
kind: Crippled,
dur_secs: 15.0,
strength: Value(0.5),
chance: 1.0,
))),
damage_kind: Slashing,
)

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.3,
base_damage: 50,
base_poise_damage: 0,
knockback: 0.0,
knockback: ( strength: 0.0, direction: Away),
range: 3.5,
max_angle: 20.0,
damage_effect: None,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.9,
base_damage: 20,
base_poise_damage: 0,
knockback: 0.0,
knockback: ( strength: 0.0, direction: Away),
range: 3.5,
max_angle: 15.0,
damage_effect: None,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.15,
base_damage: 50,
base_poise_damage: 0,
knockback: 0.0,
knockback: ( strength: 0.0, direction: Away),
range: 3.5,
max_angle: 20.0,
damage_effect: None,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.15,
base_damage: 50,
base_poise_damage: 0,
knockback: 0.0,
knockback: ( strength: 0.0, direction: Away),
range: 3.5,
max_angle: 20.0,
damage_effect: None,

View File

@ -5,7 +5,7 @@ BasicMelee(
recover_duration: 0.3,
base_damage: 40,
base_poise_damage: 0,
knockback: 0.0,
knockback: ( strength: 0.0, direction: Away),
range: 3.0,
max_angle: 120.0,
damage_effect: None,

View File

@ -32,6 +32,8 @@
"buff.desc.crippled": "Your movement is crippled as your legs are heavily injured.",
"buff.title.frozen": "Frozen",
"buff.desc.frozen": "Your movements and attacks are slowed.",
"buff.title.wet": "Wet",
"buff.desc.wet": "The ground rejects your feet, making it hard to stop.",
// Buffs stats
"buff.stat.health": "Restores {str_total} Health",
"buff.stat.increase_max_stamina": "Raises Maximum Stamina by {strength}",

View File

@ -67,6 +67,7 @@ const int BLOOD = 25;
const int ENRAGED = 26;
const int BIG_SHRAPNEL = 27;
const int LASER = 28;
const int BUBBLES = 29;
// meters per second squared (acceleration)
const float earth_gravity = 9.807;
@ -181,7 +182,7 @@ void main() {
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 0.5)
);
break;
case FIRE:
case FIRE:
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
attr = Attr(
linear_motion(
@ -489,6 +490,17 @@ void main() {
spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0)
);
break;
case BUBBLES:
f_reflect = 0.0; // Magic water doesn't reflect light, it emits it
float blue_color = 1.5 + 0.2 * rand3 + 1.5 * max(floor(rand4 + 0.3), 0.0);
float size = 8.0 * (1 - slow_start(0.1)) * slow_end(0.15);
attr = Attr(
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
vec3(size),
vec4(0.5 * blue_color, 0.75 * blue_color, blue_color, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
);
break;
default:
attr = Attr(
linear_motion(

View File

@ -271,6 +271,7 @@ lazy_static! {
BuffKind::Frenzied => "frenzied",
BuffKind::Crippled => "crippled",
BuffKind::Frozen => "frozen",
BuffKind::Wet => "wet",
};
let mut buff_parser = HashMap::new();
BuffKind::iter().for_each(|kind| {buff_parser.insert(string_from_buff(kind).to_string(), kind);});

View File

@ -65,7 +65,7 @@ pub enum CharacterAbility {
recover_duration: f32,
base_damage: f32,
base_poise_damage: f32,
knockback: f32,
knockback: Knockback,
range: f32,
max_angle: f32,
damage_effect: Option<CombatEffect>,
@ -301,7 +301,10 @@ impl Default for CharacterAbility {
recover_duration: 0.5,
base_damage: 10.0,
base_poise_damage: 0.0,
knockback: 0.0,
knockback: Knockback {
strength: 0.0,
direction: combat::KnockbackDir::Away,
},
range: 3.5,
max_angle: 15.0,
damage_effect: None,

View File

@ -53,4 +53,5 @@ pub enum FrontendSpecifier {
HealingBeam,
Cultist,
ClayGolem,
Bubbles,
}

View File

@ -67,6 +67,10 @@ pub enum BuffKind {
/// speed, 1.0 is 33% speed. Movement speed debuff is scaled to be slightly
/// smaller than attack speed debuff.
Frozen,
/// Makes you wet and causes you to have reduced friction on the ground.
/// Strength scales the friction you ignore non-linearly. 0.5 is 50% ground
/// friction, 1.0 is 33% ground friction.
Wet,
}
#[cfg(not(target_arch = "wasm32"))]
@ -88,6 +92,7 @@ impl BuffKind {
BuffKind::Crippled => false,
BuffKind::Frenzied => true,
BuffKind::Frozen => false,
BuffKind::Wet => false,
}
}
@ -156,6 +161,8 @@ pub enum BuffEffect {
MovementSpeed(f32),
/// Modifies attack speed of target
AttackSpeed(f32),
/// Modifies ground friction of target
GroundFriction(f32),
}
/// Actual de/buff.
@ -316,6 +323,10 @@ impl Buff {
],
data.duration,
),
BuffKind::Wet => (
vec![BuffEffect::GroundFriction(1.0 - nn_scaling(data.strength))],
data.duration,
),
};
Buff {
kind,

View File

@ -27,6 +27,7 @@ pub struct Stats {
pub max_health_modifier: f32,
pub move_speed_modifier: f32,
pub attack_speed_modifier: f32,
pub friction_modifier: f32,
}
impl Stats {
@ -37,6 +38,7 @@ impl Stats {
max_health_modifier: 1.0,
move_speed_modifier: 1.0,
attack_speed_modifier: 1.0,
friction_modifier: 1.0,
}
}
@ -49,6 +51,7 @@ impl Stats {
max_health_modifier: 1.0,
move_speed_modifier: 1.0,
attack_speed_modifier: 1.0,
friction_modifier: 1.0,
}
}
@ -58,6 +61,7 @@ impl Stats {
self.max_health_modifier = 1.0;
self.move_speed_modifier = 1.0;
self.attack_speed_modifier = 1.0;
self.friction_modifier = 1.0;
}
}

View File

@ -1,11 +1,13 @@
use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
combat::{
Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage,
DamageKind, DamageSource, GroupTarget, Knockback,
},
comp::{tool::ToolKind, CharacterState, Melee, StateUpdate},
states::{
behavior::{CharacterBehavior, JoinData},
utils::*,
},
Damage, DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@ -24,7 +26,7 @@ pub struct StaticData {
/// Base poise reduction
pub base_poise_damage: f32,
/// Knockback
pub knockback: f32,
pub knockback: Knockback,
/// Max range
pub range: f32,
/// Max angle (45.0 will give you a 90.0 angle window)
@ -91,10 +93,7 @@ impl CharacterBehavior for Data {
.with_requirement(CombatRequirement::AnyDamage);
let knockback = AttackEffect::new(
Some(GroupTarget::OutOfGroup),
CombatEffect::Knockback(Knockback {
strength: self.static_data.knockback,
direction: KnockbackDir::Away,
}),
CombatEffect::Knockback(self.static_data.knockback),
)
.with_requirement(CombatRequirement::AnyDamage);
let energy = AttackEffect::new(None, CombatEffect::EnergyReward(50.0))

View File

@ -243,7 +243,7 @@ pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
/// Updates components to move player as if theyre on ground or in air
#[allow(clippy::assign_op_pattern)] // TODO: Pending review in #587
fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
let efficiency = efficiency * data.stats.move_speed_modifier;
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
let accel = if data.physics.on_ground {
data.body.base_accel()
@ -269,14 +269,15 @@ pub fn handle_forced_movement(
movement: ForcedMovement,
efficiency: f32,
) {
let efficiency = efficiency * data.stats.move_speed_modifier;
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
match movement {
ForcedMovement::Forward { strength } => {
if let Some(accel) = data.physics.on_ground.then_some(data.body.base_accel()) {
update.vel.0 += Vec2::broadcast(data.dt.0)
* accel
* (data.inputs.move_dir * efficiency + Vec2::from(update.ori) * strength);
* (data.inputs.move_dir + Vec2::from(update.ori) * strength)
* efficiency;
}
},
ForcedMovement::Leap {
@ -328,7 +329,7 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, efficiency:
/// Updates components to move player as if theyre swimming
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, submersion: f32) -> bool {
let efficiency = efficiency * data.stats.move_speed_modifier;
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
if let Some(force) = data.body.swim_thrust() {
let force = efficiency * force;
let mut water_accel = force / data.mass.0;
@ -366,7 +367,7 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, submers
/// Updates components to move entity as if it's flying
pub fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) -> bool {
let efficiency = efficiency * data.stats.move_speed_modifier;
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
let glider = match data.character {
CharacterState::Glide(data) => Some(data),

View File

@ -214,6 +214,9 @@ impl<'a> System<'a> for Sys {
BuffEffect::AttackSpeed(speed) => {
stat.attack_speed_modifier *= *speed;
},
BuffEffect::GroundFriction(gf) => {
stat.friction_modifier *= *gf;
},
};
}
}

View File

@ -3,7 +3,7 @@ use common::{
body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST},
fluid_dynamics::{Fluid, Wings},
BeamSegment, Body, CharacterState, Collider, Density, Mass, Mounting, Ori, PhysicsState,
Pos, PosVelDefer, PreviousPhysCache, Projectile, Scale, Shockwave, Sticky, Vel,
Pos, PosVelDefer, PreviousPhysCache, Projectile, Scale, Shockwave, Stats, Sticky, Vel,
},
consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY},
event::{EventBus, ServerEvent},
@ -124,6 +124,7 @@ pub struct PhysicsRead<'a> {
bodies: ReadStorage<'a, Body>,
character_states: ReadStorage<'a, CharacterState>,
densities: ReadStorage<'a, Density>,
stats: ReadStorage<'a, Stats>,
}
#[derive(SystemData)]
@ -779,6 +780,7 @@ impl<'a> PhysicsData<'a> {
block_snap,
climbing,
|entity, vel| land_on_ground = Some((entity, vel)),
read,
);
tgt_pos = cpos.0;
},
@ -808,6 +810,7 @@ impl<'a> PhysicsData<'a> {
block_snap,
climbing,
|entity, vel| land_on_ground = Some((entity, vel)),
read,
);
// Sticky things shouldn't move when on a surface
@ -1048,6 +1051,7 @@ impl<'a> PhysicsData<'a> {
land_on_ground =
Some((entity, Vel(ori_from.mul_direction(vel.0))));
},
read,
);
cpos.0 = transform_from.mul_point(cpos.0) + wpos;
@ -1242,6 +1246,7 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
block_snap: bool,
climbing: bool,
mut land_on_ground: impl FnMut(Entity, Vel),
read: &PhysicsRead,
) {
let (radius, z_min, z_max) = cylinder;
@ -1567,8 +1572,9 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
}
}
physics_state.on_wall = on_wall;
let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier);
if physics_state.on_ground || (physics_state.on_wall.is_some() && climbing) {
vel.0 *= (1.0 - FRIC_GROUND.min(1.0)).powf(dt.0 * 60.0);
vel.0 *= (1.0 - FRIC_GROUND.min(1.0) * fric_mod).powf(dt.0 * 60.0);
physics_state.ground_vel = ground_vel;
}

View File

@ -403,7 +403,7 @@ impl SfxMgr {
audio.emit_sfx(sfx_trigger_item, *pos, None, false);
}
},
beam::FrontendSpecifier::ClayGolem => {},
beam::FrontendSpecifier::ClayGolem | beam::FrontendSpecifier::Bubbles => {},
},
Outcome::BreakBlock { pos, .. } => {
let sfx_trigger_item = triggers.get_key_value(&SfxEvent::BreakBlock);

View File

@ -756,6 +756,10 @@ fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, templat
tracing::error!("Player was killed by a positive buff!");
localized_strings.get("hud.outcome.mysterious")
},
BuffKind::Wet => {
tracing::error!("Player was killed by a debuff that doesn't do damage!");
localized_strings.get("hud.outcome.mysterious")
},
};
template.replace("{died_of_buff}", buff_outcome)

View File

@ -3777,6 +3777,8 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id {
BuffKind::Burning { .. } => imgs.debuff_burning_0,
BuffKind::Crippled { .. } => imgs.debuff_crippled_0,
BuffKind::Frozen { .. } => imgs.debuff_frozen_0,
// TODO: Get icon for this before merging. Anyone doing code review open a comment here.
BuffKind::Wet { .. } => imgs.debuff_burning_0,
}
}
@ -3798,6 +3800,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> &str
BuffKind::Burning { .. } => localized_strings.get("buff.title.burn"),
BuffKind::Crippled { .. } => localized_strings.get("buff.title.crippled"),
BuffKind::Frozen { .. } => localized_strings.get("buff.title.frozen"),
BuffKind::Wet { .. } => localized_strings.get("buff.title.wet"),
}
}
@ -3831,6 +3834,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz
BuffKind::Burning { .. } => Cow::Borrowed(localized_strings.get("buff.desc.burn")),
BuffKind::Crippled { .. } => Cow::Borrowed(localized_strings.get("buff.desc.crippled")),
BuffKind::Frozen { .. } => Cow::Borrowed(localized_strings.get("buff.desc.frozen")),
BuffKind::Wet { .. } => Cow::Borrowed(localized_strings.get("buff.desc.wet")),
}
}

View File

@ -121,7 +121,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> String {
| BuffKind::ProtectingWard
| BuffKind::Crippled
| BuffKind::Frenzied
| BuffKind::Frozen => continue,
| BuffKind::Frozen
| BuffKind::Wet => continue,
};
write!(&mut description, "{}", buff_desc).unwrap();
@ -144,7 +145,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> String {
| BuffKind::ProtectingWard
| BuffKind::Crippled
| BuffKind::Frenzied
| BuffKind::Frozen => continue,
| BuffKind::Frozen
| BuffKind::Wet => continue,
}
} else if let BuffKind::Saturation | BuffKind::Regeneration = buff.kind {
i18n.get("buff.text.every_second").to_string()

View File

@ -79,6 +79,7 @@ pub enum ParticleMode {
Enraged = 26,
BigShrapnel = 27,
Laser = 28,
Bubbles = 29,
}
impl ParticleMode {

View File

@ -830,6 +830,31 @@ impl ParticleMgr {
)
})
},
beam::FrontendSpecifier::Bubbles => {
let mut rng = thread_rng();
let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
let m = Mat3::<f32>::rotation_from_to_3d(from, to);
self.particles.resize_with(
self.particles.len() + usize::from(beam_tick_count) / 15,
|| {
let phi: f32 = rng.gen_range(0.0..beam.properties.angle);
let theta: f32 = rng.gen_range(0.0..2.0 * PI);
let offset_z = Vec3::new(
phi.sin() * theta.cos(),
phi.sin() * theta.sin(),
phi.cos(),
);
let random_ori = offset_z * m * Vec3::new(-1.0, -1.0, 1.0);
Particle::new_directed(
beam.properties.duration,
time,
ParticleMode::Bubbles,
pos.0,
pos.0 + random_ori * range,
)
},
);
},
}
}
}