From 58f186d2fdeafe53b8df50ba46712820c753c11f Mon Sep 17 00:00:00 2001 From: ntr Date: Thu, 8 Nov 2018 00:00:46 +1100 Subject: [PATCH] passives and lots and lots of skills --- client/cryps.css | 3 + client/index.js | 2 + client/src/components/game.jsx | 12 +- server/Cargo.toml | 1 + server/src/cryp.rs | 91 ++---- server/src/game.rs | 6 +- server/src/main.rs | 2 + server/src/passives.rs | 70 +++++ server/src/skill.rs | 532 ++++++++++++++++++++++++--------- 9 files changed, 508 insertions(+), 211 deletions(-) create mode 100644 client/cryps.css create mode 100644 server/src/passives.rs diff --git a/client/cryps.css b/client/cryps.css new file mode 100644 index 00000000..5055091d --- /dev/null +++ b/client/cryps.css @@ -0,0 +1,3 @@ +body { + background-color: #181818; +} diff --git a/client/index.js b/client/index.js index 0787daa8..6ad41876 100755 --- a/client/index.js +++ b/client/index.js @@ -1,2 +1,4 @@ +require('./cryps.css'); + // kick it off require('./src/main'); diff --git a/client/src/components/game.jsx b/client/src/components/game.jsx index 82b8f954..0a81b6a7 100755 --- a/client/src/components/game.jsx +++ b/client/src/components/game.jsx @@ -55,8 +55,8 @@ function GamePanel(props) { ); }); - const statuses = cryp.statuses.map((status, i) => ( -
{status} for {status.turns}T
+ const effects = cryp.effects.map((effect, i) => ( +
{effect} for {effect.turns}T
)); return ( @@ -84,7 +84,7 @@ function GamePanel(props) {
{cryp.xp} / {Math.pow(2, cryp.lvl + 1)} XP
- {statuses} + {effects} {skills} ); @@ -101,8 +101,8 @@ function GamePanel(props) { } function OpponentCrypCard(cryp) { - const statuses = cryp.statuses.map((status, i) => ( -
{status.status} for {status.turns}T
+ const effects = cryp.effects.map((effect, i) => ( +
{effect.effect} for {effect.turns}T
)); return ( @@ -127,7 +127,7 @@ function GamePanel(props) { - {statuses} + {effects} ); } diff --git a/server/Cargo.toml b/server/Cargo.toml index d64ff304..725929a2 100755 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -12,6 +12,7 @@ serde_cbor = "0.9" tungstenite = "0.6" bcrypt = "0.2" +petgraph = "0.4" dotenv = "0.9.0" env_logger = "*" diff --git a/server/src/cryp.rs b/server/src/cryp.rs index 282675db..5cc5248e 100755 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -10,7 +10,7 @@ use failure::err_msg; use account::Account; use rpc::{CrypSpawnParams}; use game::{Log}; -use skill::{Skill, Cooldown, Roll, Effect}; +use skill::{Skill, Cooldown, Effect}; #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub struct CrypSkill { @@ -31,8 +31,8 @@ impl CrypSkill { #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub struct CrypEffect { - effect: Effect, - duration: u8, + pub effect: Effect, + pub duration: u8, } #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] @@ -40,6 +40,8 @@ pub enum Stat { Str, Agi, Int, + PhysicalDmg, + SpellPower, Hp, Stam, } @@ -66,10 +68,9 @@ impl CrypStat { pub struct Cryp { pub id: Uuid, pub account: Uuid, - pub str: CrypStat, - pub agi: CrypStat, - pub int: CrypStat, - pub stam: CrypStat, + pub phys_dmg: CrypStat, + pub spell_dmg: CrypStat, + pub stamina: CrypStat, pub hp: CrypStat, pub xp: u64, pub lvl: u8, @@ -89,10 +90,9 @@ impl Cryp { return Cryp { id, account: id, - str: CrypStat { value: 0, stat: Stat::Str }, - agi: CrypStat { value: 0, stat: Stat::Agi }, - int: CrypStat { value: 0, stat: Stat::Int }, - stam: CrypStat { value: 0, stat: Stat::Stam }, + phys_dmg: CrypStat { value: 0, stat: Stat::Str }, + spell_dmg: CrypStat { value: 0, stat: Stat::Int }, + stamina: CrypStat { value: 0, stat: Stat::Stam }, hp: CrypStat { value: 0, stat: Stat::Hp }, lvl: 0, xp: 0, @@ -143,13 +143,17 @@ impl Cryp { false => 2_u64.pow(self.lvl.into()), }; + let min = match self.lvl == 1 { + true => 2_u64, + false => 2_u64.pow(self.lvl.saturating_sub(1).into()), + }; + self.xp = max; - self.str.set(rng.gen_range(1, max)); - self.agi.set(rng.gen_range(1, max)); - self.int.set(rng.gen_range(1, max)); - self.stam.set(rng.gen_range(1, max)); - self.hp.set(self.stam.value); + self.phys_dmg.set(rng.gen_range(min, max)); + self.spell_dmg.set(rng.gen_range(min, max)); + self.stamina.set(rng.gen_range(min, max)); + self.hp.set(self.stamina.value); self } @@ -217,52 +221,9 @@ impl Cryp { } pub fn rez(&mut self) -> &mut Cryp { - self.hp.set(self.stam.value); + self.hp.set(self.stamina.value); self } - - pub fn roll(&self, skill: Skill) -> Roll { - let mut rng = thread_rng(); - let base: u64 = rng.gen(); - - let stat = skill.stat(self); - - let mut roll = Roll { base, result: base }; - - println!("{:?}'s stats", self.name); - println!("{:064b} <- finalised", roll.result); - roll.result = roll.result & stat.value; - - println!("{:064b} & <- attribute roll", stat.value); - println!("{:064b} = {:?}", roll.result, roll.result); - println!(""); - - return roll; - } - - pub fn stun(&mut self, _roll: Roll, log: &mut Log) -> &mut Cryp { - if !self.effects.iter().any(|s| s.effect == Effect::Block) { - let stun = CrypEffect { effect: Effect::Stun, duration: Skill::Stun.duration() }; - self.effects.push(stun); - log.push(format!("{:?} is {:?} for {:?}T", self.name, stun.effect, stun.duration)) - } else { - log.push(format!("{:?} blocks.", self.name)) - } - self - } - - pub fn attack(&mut self, roll: Roll, log: &mut Log) -> &mut Cryp { - self.hp.reduce(roll.result); - self - } - - pub fn block(&mut self, _roll: Roll, log: &mut Log) -> &mut Cryp { - let effect = CrypEffect { effect: Effect::Block, duration: Skill::Block.duration() }; - self.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", self.name, effect.effect, effect.duration)); - self - } - } pub fn cryp_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result { @@ -350,13 +311,13 @@ mod tests { // pub fn assign_str(&mut self, opp: &Cryp, plr_t: &mut Turn, opp_t: &Turn) -> &mut Cryp { - // // let final_str = opp_t.str.result.saturating_sub(plr_t.agi.result); - // // let blocked = opp_t.str.result.saturating_sub(final_str); + // // let final_str = opp_t.phys_dmg.result.saturating_sub(plr_t.agi.result); + // // let blocked = opp_t.phys_dmg.result.saturating_sub(final_str); - // let final_str = opp_t.str.result & !plr_t.agi.result; - // let blocked = opp_t.str.result & plr_t.agi.result; + // let final_str = opp_t.phys_dmg.result & !plr_t.agi.result; + // let blocked = opp_t.phys_dmg.result & plr_t.agi.result; - // plr_t.log.push(format!("{:064b} <- attacking roll {:?}", opp_t.str.result, opp_t.str.result)); + // plr_t.log.push(format!("{:064b} <- attacking roll {:?}", opp_t.phys_dmg.result, opp_t.phys_dmg.result)); // // plr_t.log.push(format!("{:064b} <- blocking roll {:?}", plr_t.agi.result, plr_t.agi.result)); // plr_t.log.push(format!("{:064b} <- final str {:?} ({:?} blocked)", final_str, final_str, blocked)); diff --git a/server/src/game.rs b/server/src/game.rs index 2241d983..d0dd47bd 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -356,14 +356,14 @@ impl Game { let mut target = self.cryp_by_id(skill.target_cryp_id.unwrap()).unwrap().clone(); self.log.push(format!("{:?} uses {:?} on {:?}", source.name, skill.skill, target.name)); - let resolution = skill.resolve(&mut source, &mut target, &mut self.log); - self.resolved.push(*resolution); + let resolution = skill.set_resolution(&mut source, &mut target, &mut self.log); + self.resolved.push(resolution.clone()); self.update_cryp(&mut source); self.update_cryp(&mut target); - return *resolution; + return resolution.clone(); }).collect::>(); // now Resolve has all been assigned diff --git a/server/src/main.rs b/server/src/main.rs index 7189ae3c..a52e5dfd 100755 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -5,6 +5,7 @@ extern crate env_logger; extern crate bcrypt; extern crate dotenv; +extern crate petgraph; extern crate postgres; extern crate r2d2; extern crate r2d2_postgres; @@ -21,6 +22,7 @@ mod cryp; mod game; mod net; mod skill; +mod passives; mod rpc; mod account; mod item; diff --git a/server/src/passives.rs b/server/src/passives.rs new file mode 100644 index 00000000..6ecc5d97 --- /dev/null +++ b/server/src/passives.rs @@ -0,0 +1,70 @@ +use petgraph::graph::{Graph, UnGraph, NodeIndex}; +use petgraph::dot::{Dot, Config}; + +#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash,PartialOrd,Ord,Serialize,Deserialize)] +pub struct Passive { + id: &'static str, + allocated: bool, + effect: usize, +} + +impl Passive { + fn new(id: &'static str) -> Passive { + return Passive { + id, + allocated: false, + effect: 0, + }; + } +} + +pub fn create_passive_graph() -> UnGraph { + let mut gr = Graph::new_undirected(); + + let start = gr.add_node(Passive::new("START")); + let mut last; + let mut next; + + // Natural Selection nodes + next = gr.add_node(Passive::new("NS")); + gr.add_edge(start, next, ()); + last = next; + + next = gr.add_node(Passive::new("NSPD0000")); + gr.add_edge(last, next, ()); + last = next; + + next = gr.add_node(Passive::new("NSPD0001")); + gr.add_edge(last, next, ()); + last = next; + + next = gr.add_node(Passive::new("NSPD0002")); + gr.add_edge(last, next, ()); + last = next; + + next = gr.add_node(Passive::new("NSPD0003")); + gr.add_edge(last, next, ()); + last = next; + + next = gr.add_node(Passive::new("NSBLOCK")); + gr.add_edge(last, next, ()); + last = next; + + return gr; +} + +#[cfg(test)] +mod tests { + use passives::*; + + #[test] + fn create_graph() { + let _graph = create_passive_graph(); + // good shit; + // let nodes = graph.node_indices().collect::>(); + // println!("{:?}", nodes[0]); + // println!("{:?}", graph.node_weight(nodes[0])); + + // println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); + } +} diff --git a/server/src/skill.rs b/server/src/skill.rs index 12fc63d2..1bbfad12 100755 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -1,30 +1,179 @@ -// use rand::prelude::*; +use rand::prelude::*; use uuid::Uuid; -use cryp::{Cryp, CrypSkill, CrypStat}; use game::{Log}; +use cryp::{Cryp, CrypEffect}; #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct Roll { +pub struct Cast { + pub id: Uuid, + pub skill: Skill, + pub source_team_id: Uuid, + pub source_cryp_id: Uuid, + pub target_cryp_id: Option, + pub target_team_id: Uuid, + pub resolution: Option, +} + +impl Cast { + pub fn new(source_cryp_id: Uuid, source_team_id: Uuid, target_team_id: Option, skill: Skill) -> Cast { + + let (target_cryp_id, target_team_id) = match skill.self_targeting() { + true => (Some(source_cryp_id), source_team_id), + false => (None, target_team_id.unwrap()) + }; + + return Cast { + id: Uuid::new_v4(), + source_cryp_id, + source_team_id, + target_cryp_id, + target_team_id, + skill, + resolution: None, + }; + } + + pub fn set_resolution(&mut self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) -> &mut Cast { + self.resolution = Some(self.skill.resolve(cryp, target, log)); + self + } + + pub fn set_target(&mut self, cryp_id: Uuid) -> &mut Cast { + self.target_cryp_id = Some(cryp_id); + self + } + + pub fn used_cooldown(self) -> bool { + return self.skill.cd().is_some(); + } +} + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub struct Resolution { pub base: u64, - pub result: u64, + pub result: Option, } pub type Cooldown = Option; +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum Effect { + // physical + Stun, + Block, + Bleed, + Leech, + Airborne, + Untouchable, + Deadly, + Vulnerable, + Fury, + Evasion, + Blind, + + // magic + Silence, + Banish, + Slow, + Haste, + Enslave, + Mesmerise, + + // magic immunity + Immune, + + // effects over time + Triage, + Decay, + Regen, + Degen, + + SpeedDrain, + SpeedIncrease, +} + +impl Effect { + pub fn prevents(&self, skill: Skill) -> bool { + match self { + Effect::Block => match skill { + Skill::Stun => true, + _ => false, + }, + _ => false, + } + } +} + #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub enum Skill { Attack, - Block, + + // ----------------- + // Nature + // ----------------- + Block, // reduce dmg + Parry, // avoid all dmg + Snare, + + Paralyse, + + // Strangle + Stun, Dodge, - Banish, + Evasion, // additional layer of dmg avoidance + + + // ----------------- + // Technology + // ----------------- + Replicate, + Swarm, + Orbit, + Repair, + Scout, // track? + + // ----------------- + // Nonviolence + // ----------------- Heal, - Accuracy, - Evasion, + Triage, // hot + Throw, // no dmg stun, adds vulnerable + Charm, + Calm, + Rez, + + // ------------------- + // Destruction + // ------------------- + Blast, Amplify, - HoT, - DoT, + Decay, // dot + Drain, + Curse, + Plague, // aoe dot + Ruin, // aoe + + // ----------------- + // Purity + // ----------------- + Accuracy, + Inspire, + Slay, + Shield, + Silence, + Inquiry, + Purify, + + // ----------------- + // Chaos + // ----------------- + Banish, + Hex, + Fear, + Taunt, + Pause, // speed slow // used by tests, no cd, no dmg TestTouch, @@ -37,19 +186,74 @@ impl Skill { match self { Skill::Attack => None, - Skill::Block => Some(1), - Skill::Dodge => Some(1), - Skill::Amplify => Some(1), - Skill::Evasion => Some(1), + // ----------------- + // Nature + // ----------------- + Skill::Block => Some(1), // reduce dmg + Skill::Parry => Some(1), // avoid all dmg + Skill::Snare => Some(2), + + Skill::Paralyse => Some(3), + + // Strangle + + Skill::Stun => Some(1), + Skill::Dodge => Some(2), + Skill::Evasion => Some(3), // additional layer of dmg avoidance + + // ----------------- + // Technology + // ----------------- + Skill::Replicate => Some(1), + Skill::Swarm => Some(3), + Skill::Orbit => Some(2), + Skill::Repair => Some(1), + Skill::Scout => Some(2), // track? + + // ----------------- + // Preservation + // ----------------- + Skill::Heal => Some(1), + Skill::Triage => Some(1), // hot + Skill::Throw => Some(2), // no dmg stun, adds vulnerable + Skill::Charm => Some(2), + Skill::Calm => Some(2), + Skill::Rez => Some(4), + + // ----------------- + // Destruction + // ----------------- + Skill::Blast => Some(1), + Skill::Amplify => Some(2), + Skill::Decay => Some(1), // dot + Skill::Drain => Some(2), + Skill::Curse => Some(2), + Skill::Plague => Some(2), // aoe dot + Skill::Ruin => Some(3), // aoe + + // ----------------- + // Purity + // ----------------- Skill::Accuracy => Some(1), + Skill::Inspire => Some(2), + Skill::Slay => Some(1), + Skill::Shield => Some(1), + Skill::Silence => Some(2), + Skill::Inquiry => Some(2), + Skill::Purify => Some(1), - Skill::Heal => Some(2), - Skill::Stun => Some(2), - Skill::DoT => Some(2), - Skill::HoT => Some(2), - - Skill::Banish => Some(3), + // ----------------- + // Chaos + // ----------------- + Skill::Banish => Some(2), + Skill::Hex => Some(1), + Skill::Fear => Some(1), + Skill::Taunt => Some(2), + Skill::Pause => Some(2), // speed slow + // ----------------- + // Test + // ----------------- Skill::TestTouch => None, Skill::TestStun => None, Skill::TestBlock => None, @@ -58,46 +262,175 @@ impl Skill { pub fn speed(&self) -> u8 { match self { - Skill::Dodge => 12, - Skill::Attack => 10, + Skill::Attack => 5, - Skill::Block => 5, - Skill::Amplify => 5, - Skill::Accuracy => 5, - Skill::Evasion => 5, - Skill::HoT => 5, - Skill::DoT => 5, + // ----------------- + // Nature + // ----------------- + Skill::Block => 10, // reduce dmg + Skill::Dodge => 10, + Skill::Parry => 10, // avoid all dmg + Skill::Snare => 10, - Skill::Heal => 2, - Skill::Stun => 2, + Skill::Paralyse => 5, + + // Strangle + + Skill::Stun => 5, + Skill::Evasion => 3, // additional layer of dmg avoidance + + // ----------------- + // Technology + // ----------------- + Skill::Replicate => 1, + Skill::Swarm => 3, + Skill::Orbit => 2, + Skill::Repair => 1, + Skill::Scout => 2, // track? + + // ----------------- + // Preservation + // ----------------- + Skill::Heal => 1, + Skill::Triage => 1, // hot + Skill::Throw => 2, // no dmg stun, adds vulnerable + Skill::Charm => 2, + Skill::Calm => 2, + Skill::Rez => 4, + + // ----------------- + // Destruction + // ----------------- + Skill::Blast => 1, + Skill::Amplify => 2, + Skill::Decay => 1, // dot + Skill::Drain => 2, + Skill::Curse => 2, + Skill::Plague => 2, // aoe dot + Skill::Ruin => 3, // aoe + + // ----------------- + // Purity + // ----------------- + Skill::Accuracy => 1, + Skill::Inspire => 2, + Skill::Slay => 1, + Skill::Shield => 1, + Skill::Silence => 2, + Skill::Inquiry => 2, + Skill::Purify => 1, + + // ----------------- + // Chaos + // ----------------- Skill::Banish => 2, + Skill::Hex => 1, + Skill::Fear => 1, + Skill::Taunt => 2, + Skill::Pause => 2, // speed slow - // test skills + // ----------------- + // Test + // ----------------- Skill::TestTouch => 10, - Skill::TestStun => 2, - Skill::TestBlock => 5, + Skill::TestStun => 5, + Skill::TestBlock => 10, } } - pub fn stat(&self, cryp: &Cryp) -> CrypStat { - match self { - Skill::Attack => cryp.str, - Skill::Block => cryp.str, - Skill::Stun => cryp.str, - Skill::Dodge => cryp.agi, - Skill::Heal => cryp.int, - Skill::Banish => cryp.str, - Skill::Evasion => cryp.str, - Skill::Accuracy => cryp.str, - Skill::Amplify => cryp.str, - Skill::HoT => cryp.str, - Skill::DoT => cryp.str, + pub fn resolve(&self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) -> Resolution { + let mut rng = thread_rng(); + let base: u64 = rng.gen(); - // test skills - Skill::TestTouch => cryp.int, - Skill::TestStun => cryp.str, - Skill::TestBlock => cryp.str, - } + let mut res = Resolution { base, result: None }; + + // println!("{:?}'s stats", self.name); + // println!("{:064b} <- finalised", roll.result); + // roll.result = roll.result & stat.value; + + // println!("{:064b} & <- attribute roll", stat.value); + // println!("{:064b} = {:?}", roll.result, roll.result); + // println!(""); + + // return Some(roll); + + match self { + Skill::Attack => { + target.hp.reduce(cryp.phys_dmg.value); + }, + // ----------------- + // Nature + // ----------------- + Skill::Block => block(cryp, target, log), + Skill::Dodge => panic!("nyi"), + Skill::Parry => panic!("nyi"), // avoid all dmg + Skill::Snare => panic!("nyi"), + + Skill::Paralyse => panic!("nyi"), + // Strangle + + Skill::Stun => stun(cryp, target, log), + Skill::Evasion => panic!("nyi"), // additional layer of dmg avoidance + + // ----------------- + // Technology + // ----------------- + Skill::Replicate => panic!("nyi"), + Skill::Swarm => panic!("nyi"), + Skill::Orbit => panic!("nyi"), + Skill::Repair => panic!("nyi"), + Skill::Scout => panic!("nyi"), // track? + + // ----------------- + // Preservation + // ----------------- + Skill::Heal => panic!("nyi"), + Skill::Triage => panic!("nyi"), // hot + Skill::Throw => panic!("nyi"), // no dmg stun, adds vulnerable + Skill::Charm => panic!("nyi"), + Skill::Calm => panic!("nyi"), + Skill::Rez => panic!("nyi"), + + // ----------------- + // Destruction + // ----------------- + Skill::Blast => panic!("nyi"), + Skill::Amplify => panic!("nyi"), + Skill::Decay => panic!("nyi"), // dot + Skill::Drain => panic!("nyi"), + Skill::Curse => panic!("nyi"), + Skill::Plague => panic!("nyi"), // aoe dot + Skill::Ruin => panic!("nyi"), // aoe + + // ----------------- + // Purity + // ----------------- + Skill::Accuracy => panic!("nyi"), + Skill::Inspire => panic!("nyi"), + Skill::Slay => panic!("nyi"), + Skill::Shield => panic!("nyi"), + Skill::Silence => panic!("nyi"), + Skill::Inquiry => panic!("nyi"), + Skill::Purify => panic!("nyi"), + + // ----------------- + // Chaos + // ----------------- + Skill::Banish => panic!("nyi"), + Skill::Hex => panic!("nyi"), + Skill::Fear => panic!("nyi"), + Skill::Taunt => panic!("nyi"), + Skill::Pause => panic!("nyi"), // speed slow + + // ----------------- + // Test + // ----------------- + Skill::TestTouch => (), + Skill::TestStun => stun(cryp, target, log), + Skill::TestBlock => block(cryp, target, log), + }; + + return res; } pub fn duration(&self) -> u8 { @@ -128,95 +461,20 @@ impl Skill { } } - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct Cast { - pub id: Uuid, - pub skill: Skill, - pub source_team_id: Uuid, - pub source_cryp_id: Uuid, - pub target_cryp_id: Option, - pub target_team_id: Uuid, - pub roll: Option, -} - -impl Cast { - pub fn new(source_cryp_id: Uuid, source_team_id: Uuid, target_team_id: Option, skill: Skill) -> Cast { - - let (target_cryp_id, target_team_id) = match skill.self_targeting() { - true => (Some(source_cryp_id), source_team_id), - false => (None, target_team_id.unwrap()) - }; - - return Cast { - id: Uuid::new_v4(), - source_cryp_id, - source_team_id, - target_cryp_id, - target_team_id, - skill, - roll: None, - }; - } - - pub fn resolve(&mut self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) -> &mut Cast { - let roll = cryp.roll(self.skill); - - match self.skill { - // the real deal - Skill::Stun => target.stun(roll, log), - Skill::Attack => target.attack(roll, log), - Skill::Block => target.block(roll, log), - Skill::Heal => target, - Skill::Dodge => target, - Skill::Banish => target, - Skill::Accuracy => target, - Skill::Evasion => target, - Skill::Amplify => target, - Skill::HoT => target, - Skill::DoT => target, - - // Test Skills - Skill::TestStun => target.stun(roll, log), - Skill::TestBlock => target.block(roll, log), - Skill::TestTouch => target, - }; - - self.roll = Some(roll); - self - } - - pub fn set_target(&mut self, cryp_id: Uuid) -> &mut Cast { - self.target_cryp_id = Some(cryp_id); - self - } - - pub fn used_cooldown(self) -> bool { - let cs = CrypSkill::new(self.skill); - return cs.cd.is_some(); +fn stun(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + if !target.effects.iter().any(|e| e.effect.prevents(Skill::Stun)) { + let stun = CrypEffect { effect: Effect::Stun, duration: Skill::Stun.duration() }; + target.effects.push(stun); + log.push(format!("{:?} -> {:?} | {:?} for {:?}T", cryp.name, target.name, stun.effect, stun.duration)); + } else { + log.push(format!("{:?} blocks.", target.name)); } } -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum Effect { - // Skill Effects - Stun, - Silence, - Banish, - Block, - Haste, - Slow, - Regen, - Degen, - Bleed, - Leech, - Airborne, - Immune, - - // Passives / items - Ghost, - Stone, - Evasion, +fn block(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + let effect = CrypEffect { effect: Effect::Block, duration: Skill::Block.duration() }; + target.effects.push(effect); + log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); } // #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]