nearly
This commit is contained in:
parent
be0bf33753
commit
cc64d21859
@ -4,8 +4,8 @@ use rand::prelude::*;
|
|||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
|
||||||
use skill::{Skill, Cast, Disable, EventVariant, EventConstruct};
|
use skill::{Skill, Cast};
|
||||||
use game::{Colour};
|
use game::{Colour, Disable, EventVariant, EventConstruct};
|
||||||
use effect::{Cooldown, Effect};
|
use effect::{Cooldown, Effect};
|
||||||
use spec::{Spec};
|
use spec::{Spec};
|
||||||
use item::{Item};
|
use item::{Item};
|
||||||
@ -423,11 +423,11 @@ impl Construct {
|
|||||||
match skill.cd {
|
match skill.cd {
|
||||||
Some(cd) => {
|
Some(cd) => {
|
||||||
skill.cd = Some(cd.saturating_add(turns));
|
skill.cd = Some(cd.saturating_add(turns));
|
||||||
events.push(EventVariant::CooldownIncrease { target: self.id, turns })
|
events.push(EventVariant::CooldownIncrease { construct: self.id, turns })
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
skill.cd = Some(turns);
|
skill.cd = Some(turns);
|
||||||
events.push(EventVariant::CooldownIncrease { target: self.id, turns })
|
events.push(EventVariant::CooldownIncrease { construct: self.id, turns })
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,7 +548,6 @@ impl Construct {
|
|||||||
|
|
||||||
pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec<EventVariant> {
|
pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec<EventVariant> {
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
let target = self.id;
|
|
||||||
if self.is_ko() { return events; }
|
if self.is_ko() { return events; }
|
||||||
|
|
||||||
match self.affected(Effect::Invert) {
|
match self.affected(Effect::Invert) {
|
||||||
@ -565,7 +564,7 @@ impl Construct {
|
|||||||
let blue = new_blue_life - current_blue_life;
|
let blue = new_blue_life - current_blue_life;
|
||||||
|
|
||||||
if red != 0 || blue != 0 {
|
if red != 0 || blue != 0 {
|
||||||
events.push(EventVariant::Recharge { target, red, blue });
|
events.push(EventVariant::Recharge { construct: self.id, red, blue });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true => {
|
true => {
|
||||||
@ -592,7 +591,7 @@ impl Construct {
|
|||||||
let red_damage_amount = red_current_green_life - self.green_life();
|
let red_damage_amount = red_current_green_life - self.green_life();
|
||||||
|
|
||||||
events.push(EventVariant::Damage {
|
events.push(EventVariant::Damage {
|
||||||
target,
|
construct: self.id,
|
||||||
amount: red_damage_amount,
|
amount: red_damage_amount,
|
||||||
mitigation: red_mitigation,
|
mitigation: red_mitigation,
|
||||||
colour: Colour::Red,
|
colour: Colour::Red,
|
||||||
@ -622,7 +621,7 @@ impl Construct {
|
|||||||
let blue_damage_amount = blue_current_green_life - self.green_life();
|
let blue_damage_amount = blue_current_green_life - self.green_life();
|
||||||
|
|
||||||
events.push(EventVariant::Damage {
|
events.push(EventVariant::Damage {
|
||||||
target,
|
construct: self.id,
|
||||||
amount: blue_damage_amount,
|
amount: blue_damage_amount,
|
||||||
mitigation: blue_mitigation,
|
mitigation: blue_mitigation,
|
||||||
colour: Colour::Blue,
|
colour: Colour::Blue,
|
||||||
@ -637,7 +636,7 @@ impl Construct {
|
|||||||
pub fn deal_green_damage(&mut self, amount: usize) -> Vec<EventVariant> {
|
pub fn deal_green_damage(&mut self, amount: usize) -> Vec<EventVariant> {
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
if self.is_ko() { return events; }
|
if self.is_ko() { return events; }
|
||||||
let target = self.id;
|
let construct = self.id;
|
||||||
|
|
||||||
let mods = self.effects.iter()
|
let mods = self.effects.iter()
|
||||||
.filter(|e| e.effect.modifications().contains(&Stat::GreenDamageTaken))
|
.filter(|e| e.effect.modifications().contains(&Stat::GreenDamageTaken))
|
||||||
@ -657,7 +656,7 @@ impl Construct {
|
|||||||
let overhealing = modified_power - healing;
|
let overhealing = modified_power - healing;
|
||||||
|
|
||||||
events.push(EventVariant::Healing {
|
events.push(EventVariant::Healing {
|
||||||
target,
|
construct,
|
||||||
amount: healing,
|
amount: healing,
|
||||||
overhealing,
|
overhealing,
|
||||||
});
|
});
|
||||||
@ -671,7 +670,7 @@ impl Construct {
|
|||||||
let delta = current_green_life - self.green_life();
|
let delta = current_green_life - self.green_life();
|
||||||
|
|
||||||
events.push(EventVariant::Damage {
|
events.push(EventVariant::Damage {
|
||||||
target,
|
construct,
|
||||||
amount: delta,
|
amount: delta,
|
||||||
mitigation: 0,
|
mitigation: 0,
|
||||||
colour: Colour::Green,
|
colour: Colour::Green,
|
||||||
@ -687,7 +686,7 @@ impl Construct {
|
|||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
|
|
||||||
if self.is_ko() { return events; }
|
if self.is_ko() { return events; }
|
||||||
let target = self.id;
|
let construct = self.id;
|
||||||
|
|
||||||
let mods = self.effects.iter()
|
let mods = self.effects.iter()
|
||||||
.filter(|e| e.effect.modifications().contains(&Stat::RedDamageTaken))
|
.filter(|e| e.effect.modifications().contains(&Stat::RedDamageTaken))
|
||||||
@ -716,7 +715,7 @@ impl Construct {
|
|||||||
|
|
||||||
events.push(
|
events.push(
|
||||||
EventVariant::Damage {
|
EventVariant::Damage {
|
||||||
target,
|
construct,
|
||||||
amount: delta,
|
amount: delta,
|
||||||
mitigation,
|
mitigation,
|
||||||
colour: Colour::Red,
|
colour: Colour::Red,
|
||||||
@ -724,7 +723,7 @@ impl Construct {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
if self.is_ko() {
|
if self.is_ko() {
|
||||||
events.push(EventVariant::Ko { target });
|
events.push(EventVariant::Ko { construct });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true => {
|
true => {
|
||||||
@ -743,7 +742,7 @@ impl Construct {
|
|||||||
if healing > 0 {
|
if healing > 0 {
|
||||||
events.push(
|
events.push(
|
||||||
EventVariant::Healing {
|
EventVariant::Healing {
|
||||||
target,
|
construct,
|
||||||
amount: healing,
|
amount: healing,
|
||||||
overhealing: overhealing - recharge,
|
overhealing: overhealing - recharge,
|
||||||
}
|
}
|
||||||
@ -751,7 +750,7 @@ impl Construct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if recharge > 0 {
|
if recharge > 0 {
|
||||||
events.push(EventVariant::Recharge { target, red: recharge, blue: 0 });
|
events.push(EventVariant::Recharge { construct, red: recharge, blue: 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -763,7 +762,7 @@ impl Construct {
|
|||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
|
|
||||||
if self.is_ko() { return events; }
|
if self.is_ko() { return events; }
|
||||||
let target = self.id;
|
let construct = self.id;
|
||||||
|
|
||||||
let mods = self.effects.iter()
|
let mods = self.effects.iter()
|
||||||
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamageTaken))
|
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamageTaken))
|
||||||
@ -787,7 +786,7 @@ impl Construct {
|
|||||||
let delta = current_green_life - self.green_life();
|
let delta = current_green_life - self.green_life();
|
||||||
|
|
||||||
events.push(EventVariant::Damage {
|
events.push(EventVariant::Damage {
|
||||||
target,
|
construct,
|
||||||
amount: delta,
|
amount: delta,
|
||||||
mitigation,
|
mitigation,
|
||||||
colour: Colour::Blue,
|
colour: Colour::Blue,
|
||||||
@ -808,11 +807,11 @@ impl Construct {
|
|||||||
let recharge = self.blue_life.value - current_life;
|
let recharge = self.blue_life.value - current_life;
|
||||||
|
|
||||||
if healing > 0 {
|
if healing > 0 {
|
||||||
events.push(EventVariant::Healing { target, amount: healing, overhealing });
|
events.push(EventVariant::Healing { construct, amount: healing, overhealing });
|
||||||
}
|
}
|
||||||
|
|
||||||
if recharge > 0 {
|
if recharge > 0 {
|
||||||
events.push(EventVariant::Recharge { target, red: 0, blue: recharge });
|
events.push(EventVariant::Recharge { construct, red: 0, blue: recharge });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -838,7 +837,7 @@ impl Construct {
|
|||||||
|
|
||||||
// todo modified durations cause of buffs
|
// todo modified durations cause of buffs
|
||||||
let result = EventVariant::Effect {
|
let result = EventVariant::Effect {
|
||||||
target: self.id,
|
construct: self.id,
|
||||||
effect: effect.effect,
|
effect: effect.effect,
|
||||||
duration: effect.duration,
|
duration: effect.duration,
|
||||||
display: EventConstruct::new(self)
|
display: EventConstruct::new(self)
|
||||||
|
|||||||
214
core/src/game.rs
214
core/src/game.rs
@ -10,7 +10,8 @@ use failure::Error;
|
|||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
|
||||||
use construct::{Construct, ConstructEffect, Stat};
|
use construct::{Construct, ConstructEffect, Stat};
|
||||||
use skill::{Skill, Cast, Event, EventVariant, resolve};
|
use skill::{Skill, Cast};
|
||||||
|
use effect::{Effect};
|
||||||
|
|
||||||
use player::{Player};
|
use player::{Player};
|
||||||
use instance::{TimeControl};
|
use instance::{TimeControl};
|
||||||
@ -23,6 +24,13 @@ pub enum Phase {
|
|||||||
Finished,
|
Finished,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
|
pub enum Colour {
|
||||||
|
Red,
|
||||||
|
Blue,
|
||||||
|
Green,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Stat { construct: Uuid, stat: Stat, mult: usize },
|
Stat { construct: Uuid, stat: Stat, mult: usize },
|
||||||
@ -33,22 +41,140 @@ pub enum Value {
|
|||||||
// Skills { construct: Uuid, colour: Colour },
|
// Skills { construct: Uuid, colour: Colour },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum Colour {
|
pub enum Action {
|
||||||
Red,
|
Hit { construct: Uuid },
|
||||||
Blue,
|
Cast { construct: Uuid },
|
||||||
Green,
|
Healing { construct: Uuid, values: Vec<Value>, colour: Colour },
|
||||||
|
Damage { construct: Uuid, values: Vec<Value>, colour: Colour },
|
||||||
|
Effect { construct: Uuid, effect: ConstructEffect },
|
||||||
|
IncreaseCooldowns { construct: Uuid, turns: usize },
|
||||||
|
// Recharge { skill: Skill, red: usize, blue: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum Action {
|
pub struct Event {
|
||||||
Hit { skill: Skill },
|
pub cast: Cast,
|
||||||
Cast { skill: Skill },
|
pub focus: Vec<Uuid>,
|
||||||
Damage { skill: Skill, construct: Uuid, values: Vec<Value>, colour: Colour },
|
pub variant: EventVariant,
|
||||||
Effect { skill: Skill, construct: Uuid, effect: ConstructEffect },
|
pub delay: i64,
|
||||||
IncreaseCooldowns { skill: Skill, construct: Uuid, turns: usize },
|
}
|
||||||
Healing { skill: Skill, construct: Uuid, values: Vec<Value>, colour: Colour },
|
|
||||||
// Recharge { skill: Skill, red: usize, blue: usize },
|
impl Event {
|
||||||
|
pub fn new(cast: Cast, variant: EventVariant) -> Event {
|
||||||
|
let focus = match variant {
|
||||||
|
EventVariant::HitAoe { construct: _ } => vec![cast.source, cast.target], // fixme
|
||||||
|
_ => vec![cast.source, cast.target],
|
||||||
|
};
|
||||||
|
|
||||||
|
let delay = variant.delay();
|
||||||
|
Event {
|
||||||
|
cast,
|
||||||
|
delay,
|
||||||
|
focus,
|
||||||
|
variant,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Disable = Vec<Effect>;
|
||||||
|
pub type Direction = (i8, i8);
|
||||||
|
|
||||||
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
|
pub enum EventVariant {
|
||||||
|
Cast { construct: Uuid, player: Uuid, direction: Direction },
|
||||||
|
Hit { construct: Uuid, player: Uuid, direction: Direction },
|
||||||
|
HitAoe { construct: Uuid },
|
||||||
|
|
||||||
|
Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct },
|
||||||
|
Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct },
|
||||||
|
Removal { construct: Uuid, effect: Option<Effect>, display: EventConstruct },
|
||||||
|
|
||||||
|
Healing { construct: Uuid, amount: usize, overhealing: usize },
|
||||||
|
Recharge { construct: Uuid, red: usize, blue: usize },
|
||||||
|
Inversion { construct: Uuid },
|
||||||
|
Reflection { construct: Uuid },
|
||||||
|
Ko { construct: Uuid },
|
||||||
|
|
||||||
|
CooldownIncrease { construct: Uuid, turns: usize },
|
||||||
|
CooldownDecrease { construct: Uuid, turns: usize },
|
||||||
|
Forfeit (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventVariant {
|
||||||
|
fn delay(&self) -> i64 {
|
||||||
|
// let source_duration = 1000; // Time for SOURCE ONLY
|
||||||
|
let target_duration = 1500; // Time for target animation
|
||||||
|
let target_delay = 500; // Add delay if theres source animation
|
||||||
|
let combat_text_delay = 1300; // Time for all post skill
|
||||||
|
let combat_text_overlap = 600; // overlap between animation and combat text
|
||||||
|
|
||||||
|
match self {
|
||||||
|
EventVariant::Cast { construct: _, direction: _, player: _ } => target_delay,
|
||||||
|
EventVariant::Hit { construct: _, direction: _, player: _ } |
|
||||||
|
EventVariant::HitAoe { construct: _ } => target_duration - combat_text_overlap,
|
||||||
|
_ => combat_text_delay,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to show the progress of a construct
|
||||||
|
// while the resolutions are animating
|
||||||
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
|
pub struct EventConstruct {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub red: usize,
|
||||||
|
pub green: usize,
|
||||||
|
pub blue: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventConstruct {
|
||||||
|
pub fn new(construct: &Construct) -> EventConstruct {
|
||||||
|
EventConstruct {
|
||||||
|
id: construct.id,
|
||||||
|
red: construct.red_life(),
|
||||||
|
green: construct.green_life(),
|
||||||
|
blue: construct.blue_life(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
|
pub enum EventStages {
|
||||||
|
#[serde(rename = "START_SKILL END_SKILL POST_SKILL")]
|
||||||
|
AllStages, // Anim Anim Anim
|
||||||
|
#[serde(rename = "START_SKILL END_SKILL")]
|
||||||
|
StartEnd, // Anim Anim Skip
|
||||||
|
#[serde(rename = "START_SKILL POST_SKILL")]
|
||||||
|
StartPost, // Anim Skip Anim
|
||||||
|
#[serde(rename = "START_SKILL")]
|
||||||
|
StartOnly, // Anim Skip Skip
|
||||||
|
#[serde(rename = "END_SKILL POST_SKILL")]
|
||||||
|
EndPost, // Skip Anim Anim
|
||||||
|
#[serde(rename = "END_SKILL")]
|
||||||
|
EndOnly, // Skip Anim Skip
|
||||||
|
#[serde(rename = "POST_SKILL")]
|
||||||
|
PostOnly, // Skip Skip Anim
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventStages {
|
||||||
|
fn delay(self) -> i64 {
|
||||||
|
let source_duration = 1000; // Time for SOURCE ONLY
|
||||||
|
let target_delay = 500; // Used for Source + Target
|
||||||
|
let target_duration = 1500; // Time for TARGET ONLY
|
||||||
|
let post_skill = 1000; // Time for all POST
|
||||||
|
let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time
|
||||||
|
|
||||||
|
match self {
|
||||||
|
EventStages::AllStages => source_and_target_total + post_skill, // Anim Anim Anim
|
||||||
|
EventStages::StartEnd => source_and_target_total, // Anim Anim Skip
|
||||||
|
EventStages::StartPost => source_duration + post_skill, // Anim Skip Anim
|
||||||
|
EventStages::StartOnly => source_duration, // Anim Skip Skip
|
||||||
|
EventStages::EndPost => target_duration + post_skill, // Skip Anim Anim
|
||||||
|
EventStages::EndOnly => target_duration, // Skip Anim Skip
|
||||||
|
EventStages::PostOnly => post_skill, // Skip Skip Anim
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||||
@ -445,6 +571,37 @@ impl Game {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn finalise_cast(&self, cast: Cast) -> Vec<Cast> {
|
||||||
|
let target_player = self.players.iter()
|
||||||
|
.find(|t| t.constructs.iter().any(|c| c.id == cast.target))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Some(t) = target_player.intercepting() {
|
||||||
|
return vec![Cast { target: t.id, ..cast }];
|
||||||
|
}
|
||||||
|
|
||||||
|
// if self.construct[source].multistrike() {
|
||||||
|
// return vec![
|
||||||
|
// Cast { target: t.id, ..cast },
|
||||||
|
// Cast { target: t.id, ..cast },
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
|
||||||
|
let targets = match cast.skill.aoe() {
|
||||||
|
true => self.players.iter()
|
||||||
|
.find(|t| t.constructs.iter().any(|c| c.id == cast.target))
|
||||||
|
.unwrap()
|
||||||
|
.constructs
|
||||||
|
.iter()
|
||||||
|
.map(|c| Cast { target: c.id, ..cast })
|
||||||
|
.collect(),
|
||||||
|
false => vec![cast],
|
||||||
|
};
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn resolve_stack(mut self) -> Game {
|
fn resolve_stack(mut self) -> Game {
|
||||||
if self.phase != Phase::Resolve {
|
if self.phase != Phase::Resolve {
|
||||||
panic!("game not in Resolve phase");
|
panic!("game not in Resolve phase");
|
||||||
@ -472,7 +629,12 @@ impl Game {
|
|||||||
while let Some(cast) = self.stack.pop() {
|
while let Some(cast) = self.stack.pop() {
|
||||||
// info!("{:} casts ", cast);
|
// info!("{:} casts ", cast);
|
||||||
|
|
||||||
resolve(&mut self, cast);
|
let casts = self.finalise_cast(cast);
|
||||||
|
|
||||||
|
for cast in casts {
|
||||||
|
self.resolve(cast);
|
||||||
|
}
|
||||||
|
|
||||||
// r_animation_ms = events.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay());
|
// r_animation_ms = events.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay());
|
||||||
|
|
||||||
// if theres no resolution events, the skill didn't trigger (disable etc)
|
// if theres no resolution events, the skill didn't trigger (disable etc)
|
||||||
@ -496,20 +658,22 @@ impl Game {
|
|||||||
self.skill_phase_start(r_animation_ms)
|
self.skill_phase_start(r_animation_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn actions(&mut self, cast: Cast) -> &mut Game {
|
pub fn resolve(&mut self, cast: Cast) -> &mut Game {
|
||||||
let mut events_group = vec![];
|
let mut events_group = vec![];
|
||||||
|
|
||||||
|
let skill = cast.skill;
|
||||||
|
|
||||||
// calculate values first?
|
// calculate values first?
|
||||||
// for result damage value need to pass &events and .find()
|
// for result damage value need to pass &events and .find()
|
||||||
|
|
||||||
for action in cast.actions() {
|
for action in cast.actions() {
|
||||||
let mut events = match action {
|
let mut events = match action {
|
||||||
Action::Cast { construct, skill, direction } => self.cast(construct, skill),
|
Action::Cast { construct } => self.cast(cast),
|
||||||
Action::Hit { construct, skill } => self.hit(construct, skill),
|
Action::Hit { construct } => self.hit(construct, skill),
|
||||||
Action::Damage { construct, values, colour } => self.damage(construct, values, colour),
|
Action::Damage { construct, values, colour } => self.damage(construct, values, colour),
|
||||||
Action::Healing { construct, values, colour } => unimplemented!(),
|
Action::Healing { construct, values, colour } => unimplemented!(),
|
||||||
Action::Effect { construct, effect } => self.effect(construct, effect),
|
Action::Effect { construct, effect } => self.effect(construct, effect),
|
||||||
Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns),
|
Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns),
|
||||||
};
|
};
|
||||||
|
|
||||||
events_group.append(&mut events);
|
events_group.append(&mut events);
|
||||||
@ -519,8 +683,8 @@ impl Game {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast(&mut self, construct: Uuid, skill: Skill) -> Vec<Event> {
|
fn cast(&mut self, cast: Cast) -> Vec<Event> {
|
||||||
vec![Event::new(EventVariant::Cast { skill: skill }, construct)]
|
vec![Event::new(cast, EventVariant::Cast { construct: cast.source, player: cast.player, direction: self.direction(cast) })]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hit(&mut self, construct: Uuid, skill: Skill) -> Vec<Event> {
|
fn hit(&mut self, construct: Uuid, skill: Skill) -> Vec<Event> {
|
||||||
@ -1388,7 +1552,7 @@ mod tests {
|
|||||||
let source = game.players[0].constructs[0].id;
|
let source = game.players[0].constructs[0].id;
|
||||||
let target = game.players[1].constructs[0].id;
|
let target = game.players[1].constructs[0].id;
|
||||||
|
|
||||||
game.actions(Cast::new(source, player_id, target, Skill::Bash).actions());
|
game.resolve(Cast::new(source, player_id, target, Skill::Bash));
|
||||||
|
|
||||||
println!("{:?}", game.events);
|
println!("{:?}", game.events);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -720,175 +720,6 @@ fn end() {}
|
|||||||
// return cast_actions(skill, &mut a, &mut b, resolutions);
|
// return cast_actions(skill, &mut a, &mut b, resolutions);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn modify_cast(game: &Game, cast: Cast) -> Vec<Cast> {
|
|
||||||
let target_player = game.players.iter()
|
|
||||||
.find(|t| t.constructs.iter().any(|c| c.id == cast.target))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(t) = target_player.intercepting() {
|
|
||||||
return vec![Cast { target: t.id, ..cast }];
|
|
||||||
}
|
|
||||||
|
|
||||||
// if game.construct[source].multistrike() {
|
|
||||||
// return vec![
|
|
||||||
// Cast { target: t.id, ..cast },
|
|
||||||
// Cast { target: t.id, ..cast },
|
|
||||||
// ];
|
|
||||||
// }
|
|
||||||
|
|
||||||
let targets = match cast.skill.aoe() {
|
|
||||||
true => game.players.iter()
|
|
||||||
.find(|t| t.constructs.iter().any(|c| c.id == cast.target))
|
|
||||||
.unwrap()
|
|
||||||
.constructs
|
|
||||||
.iter()
|
|
||||||
.map(|c| Cast { target: c.id, ..cast })
|
|
||||||
.collect(),
|
|
||||||
false => vec![cast],
|
|
||||||
};
|
|
||||||
|
|
||||||
return targets;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn resolve(game: &mut Game, cast: Cast) {
|
|
||||||
let casts = modify_cast(game, cast);
|
|
||||||
|
|
||||||
// let source = game.construct_by_id(cast.source).unwrap().clone();
|
|
||||||
// if skill.aoe() { // Send an aoe skill event for anims
|
|
||||||
// game.event(Event::new(&source,
|
|
||||||
// &game.construct_by_id(cast.target).unwrap().clone()).event(Event::AoeSkill { skill }).stages(EventStages::StartEnd));
|
|
||||||
// }
|
|
||||||
|
|
||||||
for cast in casts {
|
|
||||||
game.actions(cast.actions());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Disable = Vec<Effect>;
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub enum EventVariant {
|
|
||||||
Cast { target: Uuid, player: Uuid, x: i8, y: i8 },
|
|
||||||
Hit { target: Uuid, player: Uuid, x: i8, y: i8 },
|
|
||||||
HitAoe { target: Uuid },
|
|
||||||
|
|
||||||
Damage { target: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct },
|
|
||||||
Effect { target: Uuid, effect: Effect, duration: u8, display: EventConstruct },
|
|
||||||
Removal { target: Uuid, effect: Option<Effect>, display: EventConstruct },
|
|
||||||
|
|
||||||
Healing { target: Uuid, amount: usize, overhealing: usize },
|
|
||||||
Recharge { target: Uuid, red: usize, blue: usize },
|
|
||||||
Inversion { target: Uuid },
|
|
||||||
Reflection { target: Uuid },
|
|
||||||
Ko { target: Uuid },
|
|
||||||
|
|
||||||
CooldownIncrease { target: Uuid, turns: usize },
|
|
||||||
CooldownDecrease { target: Uuid, turns: usize },
|
|
||||||
Forfeit (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventVariant {
|
|
||||||
fn delay(&self) -> i64 {
|
|
||||||
// let source_duration = 1000; // Time for SOURCE ONLY
|
|
||||||
let target_duration = 1500; // Time for target animation
|
|
||||||
let target_delay = 500; // Add delay if theres source animation
|
|
||||||
let combat_text_delay = 1300; // Time for all post skill
|
|
||||||
let combat_text_overlap = 600; // overlap between animation and combat text
|
|
||||||
|
|
||||||
match self {
|
|
||||||
EventVariant::Cast { target: _, x: _, y: _, player: _ } => target_delay,
|
|
||||||
EventVariant::Hit { target: _, x: _, y: _, player: _ } |
|
|
||||||
EventVariant::HitAoe { target: _ } => target_duration - combat_text_overlap,
|
|
||||||
_ => combat_text_delay,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_event(&self, cast: Cast) -> Event {
|
|
||||||
let delay = self.delay();
|
|
||||||
let focus = match self {
|
|
||||||
EventVariant::HitAoe { target: _ } => vec![cast.source, cast.target], // some tricky multi target here l8r
|
|
||||||
_ => vec![cast.source, cast.target],
|
|
||||||
};
|
|
||||||
|
|
||||||
Event {
|
|
||||||
cast,
|
|
||||||
focus,
|
|
||||||
variant: *self,
|
|
||||||
delay,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub struct Event {
|
|
||||||
pub cast: Cast,
|
|
||||||
pub focus: Vec<Uuid>,
|
|
||||||
pub variant: EventVariant,
|
|
||||||
pub delay: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// used to show the progress of a construct
|
|
||||||
// while the resolutions are animating
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub struct EventConstruct {
|
|
||||||
pub id: Uuid,
|
|
||||||
pub red: usize,
|
|
||||||
pub green: usize,
|
|
||||||
pub blue: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventConstruct {
|
|
||||||
pub fn new(construct: &Construct) -> EventConstruct {
|
|
||||||
EventConstruct {
|
|
||||||
id: construct.id,
|
|
||||||
red: construct.red_life(),
|
|
||||||
green: construct.green_life(),
|
|
||||||
blue: construct.blue_life(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub enum EventStages {
|
|
||||||
#[serde(rename = "START_SKILL END_SKILL POST_SKILL")]
|
|
||||||
AllStages, // Anim Anim Anim
|
|
||||||
#[serde(rename = "START_SKILL END_SKILL")]
|
|
||||||
StartEnd, // Anim Anim Skip
|
|
||||||
#[serde(rename = "START_SKILL POST_SKILL")]
|
|
||||||
StartPost, // Anim Skip Anim
|
|
||||||
#[serde(rename = "START_SKILL")]
|
|
||||||
StartOnly, // Anim Skip Skip
|
|
||||||
#[serde(rename = "END_SKILL POST_SKILL")]
|
|
||||||
EndPost, // Skip Anim Anim
|
|
||||||
#[serde(rename = "END_SKILL")]
|
|
||||||
EndOnly, // Skip Anim Skip
|
|
||||||
#[serde(rename = "POST_SKILL")]
|
|
||||||
PostOnly, // Skip Skip Anim
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventStages {
|
|
||||||
fn delay(self) -> i64 {
|
|
||||||
let source_duration = 1000; // Time for SOURCE ONLY
|
|
||||||
let target_delay = 500; // Used for Source + Target
|
|
||||||
let target_duration = 1500; // Time for TARGET ONLY
|
|
||||||
let post_skill = 1000; // Time for all POST
|
|
||||||
let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time
|
|
||||||
|
|
||||||
match self {
|
|
||||||
EventStages::AllStages => source_and_target_total + post_skill, // Anim Anim Anim
|
|
||||||
EventStages::StartEnd => source_and_target_total, // Anim Anim Skip
|
|
||||||
EventStages::StartPost => source_duration + post_skill, // Anim Skip Anim
|
|
||||||
EventStages::StartOnly => source_duration, // Anim Skip Skip
|
|
||||||
EventStages::EndPost => target_duration + post_skill, // Skip Anim Anim
|
|
||||||
EventStages::EndOnly => target_duration, // Skip Anim Skip
|
|
||||||
EventStages::PostOnly => post_skill, // Skip Skip Anim
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum Skill {
|
pub enum Skill {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user