Merge branch 'master' of ssh://cryps.gg:40022/~/cryps
This commit is contained in:
commit
9a81a68a48
@ -46,7 +46,10 @@ function calculateTweenParams(sourceSpawn, targetSpawn, account) {
|
|||||||
|
|
||||||
function animatePhase(scene, game, resolution, cb) {
|
function animatePhase(scene, game, resolution, cb) {
|
||||||
// return early for disabled skills
|
// return early for disabled skills
|
||||||
if (resolution.resolution.disable.disabled) return cb();
|
const { resolution: { results } } = resolution;
|
||||||
|
if (results.length === 0) return cb();
|
||||||
|
if (results[0][0] === 'Disable') return cb();
|
||||||
|
|
||||||
const group = scene.scene.get('CombatCryps').cryps;
|
const group = scene.scene.get('CombatCryps').cryps;
|
||||||
const animations = new CombatAnimations(scene);
|
const animations = new CombatAnimations(scene);
|
||||||
const account = scene.registry.get('account');
|
const account = scene.registry.get('account');
|
||||||
@ -65,10 +68,6 @@ function animatePhase(scene, game, resolution, cb) {
|
|||||||
};
|
};
|
||||||
const castLocation = castParams();
|
const castLocation = castParams();
|
||||||
|
|
||||||
const { resolution: { results } } = resolution;
|
|
||||||
|
|
||||||
if (results.length === 0) return cb();
|
|
||||||
|
|
||||||
// Move cryps into position
|
// Move cryps into position
|
||||||
if (moveSourceBattle) scene.tweens.add(moveSourceBattle);
|
if (moveSourceBattle) scene.tweens.add(moveSourceBattle);
|
||||||
scene.tweens.add(moveTargetBattle);
|
scene.tweens.add(moveTargetBattle);
|
||||||
|
|||||||
@ -16,21 +16,19 @@
|
|||||||
# WORK WORK
|
# WORK WORK
|
||||||
## NOW
|
## NOW
|
||||||
cryp vbox
|
cryp vbox
|
||||||
|
|
||||||
ensure all skills impl
|
ensure all skills impl
|
||||||
ez
|
ez
|
||||||
Skill::Slay -> red attack with bonus somethingorother for blue / maim no healing
|
Skill::Slay -> red attack with bonus somethingorother for blue / maim no healing
|
||||||
|
Hatred -> damage received converted into bonus dmg
|
||||||
|
|
||||||
aoe
|
aoe
|
||||||
Skill::Ruin -> aoe stun
|
Skill::Ruin -> aoe stun
|
||||||
|
|
||||||
on attack
|
on attack
|
||||||
Skill::Reflect -> reflect incoming attacks back to opponent
|
|
||||||
Skill::Taunt -> redirect incomnig attacks to self
|
Skill::Taunt -> redirect incomnig attacks to self
|
||||||
Skill::Toxic -> apply debuff to attackers
|
Skill::Toxic -> apply debuff to attackers
|
||||||
|
|
||||||
colour speeds
|
|
||||||
|
|
||||||
update speed of rest of stack on cryp speed change
|
|
||||||
include target name in effect resolution
|
include target name in effect resolution
|
||||||
eg strangle applies buff to self
|
eg strangle applies buff to self
|
||||||
|
|
||||||
@ -55,7 +53,6 @@ change to ownership pattern
|
|||||||
deal_damage(colour)
|
deal_damage(colour)
|
||||||
resolutions.push(skill()).flatten()
|
resolutions.push(skill()).flatten()
|
||||||
overkill in logs
|
overkill in logs
|
||||||
immunity resolution type
|
|
||||||
|
|
||||||
* confirm cryp without skill ready
|
* confirm cryp without skill ready
|
||||||
* iconography
|
* iconography
|
||||||
|
|||||||
@ -258,9 +258,10 @@ impl Cryp {
|
|||||||
self.hp.value == 0
|
self.hp.value == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn immune(&self, skill: Skill) -> Immunity {
|
pub fn immune(&self, skill: Skill) -> Option<Immunity> {
|
||||||
|
// also checked in resolve stage so shouldn't happen really
|
||||||
if self.is_ko() {
|
if self.is_ko() {
|
||||||
return Immunity { immune: true, effects: vec![Effect::Ko]};
|
return Some(vec![Effect::Ko]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let immunities = self.effects.iter()
|
let immunities = self.effects.iter()
|
||||||
@ -269,15 +270,15 @@ impl Cryp {
|
|||||||
.collect::<Vec<Effect>>();
|
.collect::<Vec<Effect>>();
|
||||||
|
|
||||||
if immunities.len() > 0 {
|
if immunities.len() > 0 {
|
||||||
return Immunity { immune: true, effects: immunities};
|
return Some(immunities);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Immunity { immune: false, effects: vec![]};
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disabled(&self, skill: Skill) -> Disable {
|
pub fn disabled(&self, skill: Skill) -> Option<Disable> {
|
||||||
if self.is_ko() && !skill.ko_castable() {
|
if self.is_ko() && !skill.ko_castable() {
|
||||||
return Disable { disabled: true, effects: vec![Effect::Ko]};
|
return Some(vec![Effect::Ko]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let disables = self.effects.iter()
|
let disables = self.effects.iter()
|
||||||
@ -286,10 +287,10 @@ impl Cryp {
|
|||||||
.collect::<Vec<Effect>>();
|
.collect::<Vec<Effect>>();
|
||||||
|
|
||||||
if disables.len() > 0 {
|
if disables.len() > 0 {
|
||||||
return Disable { disabled: true, effects: disables};
|
return Some(disables);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Disable { disabled: false, effects: vec![]};
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -312,7 +313,7 @@ impl Cryp {
|
|||||||
pub fn available_skills(&self) -> Vec<&CrypSkill> {
|
pub fn available_skills(&self) -> Vec<&CrypSkill> {
|
||||||
self.skills.iter()
|
self.skills.iter()
|
||||||
.filter(|s| s.cd.is_none())
|
.filter(|s| s.cd.is_none())
|
||||||
.filter(|s| !self.disabled(s.skill).disabled)
|
.filter(|s| self.disabled(s.skill).is_none())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,11 +388,6 @@ impl Cryp {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn rez(&mut self) -> &mut Cryp {
|
|
||||||
// self.hp.set(self.hp.base);
|
|
||||||
// self
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
pub fn red_damage(&self) -> u64 {
|
pub fn red_damage(&self) -> u64 {
|
||||||
let red_damage_mods = self.effects.iter()
|
let red_damage_mods = self.effects.iter()
|
||||||
@ -423,11 +419,15 @@ impl Cryp {
|
|||||||
return modified_green_damage;
|
return modified_green_damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn skill_speed(&self, s: Skill) -> u64 {
|
pub fn skill_speed(&self, s: Skill) -> u64 {
|
||||||
self.speed().saturating_mul(s.speed() as u64)
|
self.speed().saturating_mul(s.speed() as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo complete with specs
|
||||||
|
pub fn skill_is_aoe(&self, s: Skill) -> bool {
|
||||||
|
s.aoe()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn speed(&self) -> u64 {
|
pub fn speed(&self) -> u64 {
|
||||||
let speed_mods = self.effects.iter()
|
let speed_mods = self.effects.iter()
|
||||||
.filter(|e| e.effect.modifications().contains(&Stat::Speed))
|
.filter(|e| e.effect.modifications().contains(&Stat::Speed))
|
||||||
@ -450,14 +450,9 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn recharge(&mut self) -> ResolutionResult {
|
pub fn recharge(&mut self) -> ResolutionResult {
|
||||||
let immunity = self.immune(Skill::Recharge);
|
if let Some(immunity) = self.immune(Skill::Recharge) {
|
||||||
let immune = immunity.immune;
|
return ResolutionResult::Immunity {
|
||||||
|
immunity,
|
||||||
if immune {
|
|
||||||
ResolutionResult::Recharge {
|
|
||||||
red: 0,
|
|
||||||
blue: 0,
|
|
||||||
immunity: immunity.clone(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,18 +462,13 @@ impl Cryp {
|
|||||||
let blue = self.blue_shield.max.saturating_sub(self.blue_shield.value);
|
let blue = self.blue_shield.max.saturating_sub(self.blue_shield.value);
|
||||||
self.blue_shield.value = self.blue_shield.max;
|
self.blue_shield.value = self.blue_shield.max;
|
||||||
|
|
||||||
ResolutionResult::Recharge { red, blue, immunity }
|
ResolutionResult::Recharge { red, blue }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deal_green_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
pub fn deal_green_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||||
let immunity = self.immune(skill);
|
if let Some(immunity) = self.immune(skill) {
|
||||||
let immune = immunity.immune;
|
return ResolutionResult::Immunity {
|
||||||
|
immunity,
|
||||||
if immune {
|
|
||||||
return ResolutionResult::Healing {
|
|
||||||
amount: 0,
|
|
||||||
overhealing: 0,
|
|
||||||
immunity: immunity.clone(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +493,6 @@ impl Cryp {
|
|||||||
return ResolutionResult::Healing {
|
return ResolutionResult::Healing {
|
||||||
amount: healing,
|
amount: healing,
|
||||||
overhealing,
|
overhealing,
|
||||||
immunity,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true => {
|
true => {
|
||||||
@ -517,21 +506,14 @@ impl Cryp {
|
|||||||
healing: 0,
|
healing: 0,
|
||||||
recharge: 0,
|
recharge: 0,
|
||||||
category: Category::GreenDamage,
|
category: Category::GreenDamage,
|
||||||
immunity,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||||
let immunity = self.immune(skill);
|
if let Some(immunity) = self.immune(skill) {
|
||||||
let immune = immunity.immune;
|
return ResolutionResult::Immunity {
|
||||||
|
|
||||||
if immune {
|
|
||||||
return ResolutionResult::Damage {
|
|
||||||
amount: 0,
|
|
||||||
mitigation: 0,
|
|
||||||
category: Category::RedDamage,
|
|
||||||
immunity,
|
immunity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -566,7 +548,6 @@ impl Cryp {
|
|||||||
amount: delta,
|
amount: delta,
|
||||||
mitigation,
|
mitigation,
|
||||||
category: Category::RedDamage,
|
category: Category::RedDamage,
|
||||||
immunity,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true => {
|
true => {
|
||||||
@ -584,7 +565,6 @@ impl Cryp {
|
|||||||
damage: 0,
|
damage: 0,
|
||||||
healing,
|
healing,
|
||||||
recharge,
|
recharge,
|
||||||
immunity,
|
|
||||||
category: Category::RedDamage,
|
category: Category::RedDamage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -592,14 +572,8 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||||
let immunity = self.immune(skill);
|
if let Some(immunity) = self.immune(skill) {
|
||||||
let immune = immunity.immune;
|
return ResolutionResult::Immunity {
|
||||||
|
|
||||||
if immune {
|
|
||||||
return ResolutionResult::Damage {
|
|
||||||
amount: 0,
|
|
||||||
mitigation: 0,
|
|
||||||
category: Category::BlueDamage,
|
|
||||||
immunity,
|
immunity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -627,7 +601,6 @@ impl Cryp {
|
|||||||
amount: delta,
|
amount: delta,
|
||||||
mitigation,
|
mitigation,
|
||||||
category: Category::BlueDamage,
|
category: Category::BlueDamage,
|
||||||
immunity,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
true => {
|
true => {
|
||||||
@ -645,7 +618,6 @@ impl Cryp {
|
|||||||
damage: 0,
|
damage: 0,
|
||||||
healing,
|
healing,
|
||||||
recharge,
|
recharge,
|
||||||
immunity,
|
|
||||||
category: Category::BlueDamage,
|
category: Category::BlueDamage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -653,20 +625,20 @@ impl Cryp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> ResolutionResult {
|
pub fn add_effect(&mut self, skill: Skill, effect: CrypEffect) -> ResolutionResult {
|
||||||
let immunity = self.immune(skill);
|
if let Some(immunity) = self.immune(skill) {
|
||||||
let immune = immunity.immune;
|
return ResolutionResult::Immunity {
|
||||||
|
immunity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// todo modified durations cause of buffs
|
// todo modified durations cause of buffs
|
||||||
let result = ResolutionResult::Effect {
|
let result = ResolutionResult::Effect {
|
||||||
effect: effect.effect,
|
effect: effect.effect,
|
||||||
duration: effect.effect.duration(),
|
duration: effect.effect.duration(),
|
||||||
immunity,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !immune {
|
|
||||||
// println!("{:?} {:?} adding effect", self.name, effect.effect);
|
// println!("{:?} {:?} adding effect", self.name, effect.effect);
|
||||||
self.effects.push(effect);
|
self.effects.push(effect);
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ pub struct Team {
|
|||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
pub player: Option<Uuid>,
|
pub player: Option<Uuid>,
|
||||||
pub bot: bool,
|
pub bot: bool,
|
||||||
cryps: Vec<Cryp>,
|
pub cryps: Vec<Cryp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Team {
|
impl Team {
|
||||||
@ -154,14 +154,14 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle missing team properly
|
// handle missing team properly
|
||||||
fn team_by_id(&mut self, id: Uuid) -> &mut Team {
|
pub fn team_by_id(&mut self, id: Uuid) -> &mut Team {
|
||||||
match self.teams.iter_mut().find(|t| t.id == id) {
|
match self.teams.iter_mut().find(|t| t.id == id) {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => panic!("id not in game {:}", id),
|
None => panic!("id not in game {:}", id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> {
|
pub fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> {
|
||||||
match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == id)) {
|
match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == id)) {
|
||||||
Some(team) => team.cryps.iter_mut().find(|c| c.id == id),
|
Some(team) => team.cryps.iter_mut().find(|c| c.id == id),
|
||||||
None => None,
|
None => None,
|
||||||
@ -177,6 +177,16 @@ impl Game {
|
|||||||
.collect::<Vec<Cryp>>()
|
.collect::<Vec<Cryp>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cryp_aoe_targets(&self, cryp_id: Uuid) -> Vec<Uuid> {
|
||||||
|
self.teams.iter()
|
||||||
|
.find(|t| t.cryps.iter().any(|c| c.id == cryp_id))
|
||||||
|
.unwrap()
|
||||||
|
.cryps
|
||||||
|
.iter()
|
||||||
|
.map(|c| c.id)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game {
|
fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game {
|
||||||
match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) {
|
match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) {
|
||||||
Some(team) => {
|
Some(team) => {
|
||||||
@ -196,14 +206,12 @@ impl Game {
|
|||||||
&& self.teams.iter().all(|t| t.cryps.len() == self.team_size)
|
&& self.teams.iter().all(|t| t.cryps.len() == self.team_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) -> &mut Game {
|
pub fn start(mut self) -> Game {
|
||||||
self.log.push("Game starting...".to_string());
|
self.log.push("Game starting...".to_string());
|
||||||
|
self.skill_phase_start()
|
||||||
self.skill_phase_start();
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skill_phase_start(&mut self) -> &mut Game {
|
fn skill_phase_start(mut self) -> Game {
|
||||||
self.log.push("<Skill Phase>".to_string());
|
self.log.push("<Skill Phase>".to_string());
|
||||||
|
|
||||||
if ![Phase::Start, Phase::Resolve].contains(&self.phase) {
|
if ![Phase::Start, Phase::Resolve].contains(&self.phase) {
|
||||||
@ -212,23 +220,21 @@ impl Game {
|
|||||||
|
|
||||||
self.phase = Phase::Skill;
|
self.phase = Phase::Skill;
|
||||||
|
|
||||||
self.stack.clear();
|
|
||||||
|
|
||||||
self.pve_add_skills();
|
self.pve_add_skills();
|
||||||
if self.skill_phase_finished() {
|
if self.skill_phase_finished() {
|
||||||
self.resolve_phase_start();
|
return self.resolve_phase_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pve_add_skills(&mut self) -> &mut Game {
|
fn pve_add_skills(&mut self) -> &mut Game {
|
||||||
for mobs in self.teams
|
let mut pve_skills = vec![];
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|t| t.bot) {
|
|
||||||
|
|
||||||
let player_team = self.teams.iter().find(|t| t.id != mobs.id).unwrap().clone();
|
for mobs in self.teams
|
||||||
|
.iter()
|
||||||
|
.filter(|t| t.bot) {
|
||||||
|
let player_team = self.teams.iter().find(|t| t.id != mobs.id).unwrap();
|
||||||
|
|
||||||
for mob in mobs.cryps.iter() {
|
for mob in mobs.cryps.iter() {
|
||||||
let skill = mob.mob_select_skill();
|
let skill = mob.mob_select_skill();
|
||||||
@ -252,16 +258,17 @@ impl Game {
|
|||||||
target = find_target();
|
target = find_target();
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.add_skill(mobs.id, mob.id, Some(target.id), s) {
|
pve_skills.push((mobs.id, mob.id, Some(target.id), s));
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => println!("{:?} could not add pve skill", e),
|
|
||||||
}
|
|
||||||
// println!("{:?}", cast);
|
|
||||||
},
|
},
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (team_id, mob_id, target_id, s) in pve_skills {
|
||||||
|
self.add_skill(team_id, mob_id, target_id, s).expect("unable to add pve mob skill");
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,9 +319,8 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check here as well so uncastable spells don't go on the stack
|
// check here as well so uncastable spells don't go on the stack
|
||||||
let check = cryp.disabled(skill);
|
if let Some(disable) = cryp.disabled(skill) {
|
||||||
if check.disabled {
|
return Err(format_err!("skill disabled {:?}", disable));
|
||||||
return Err(format_err!("skill disabled {:?}", check.effects));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +349,7 @@ impl Game {
|
|||||||
|
|
||||||
// requires no input
|
// requires no input
|
||||||
// just do it
|
// just do it
|
||||||
fn resolve_phase_start(&mut self) -> &mut Game {
|
fn resolve_phase_start(mut self) -> Game {
|
||||||
if self.phase != Phase::Skill {
|
if self.phase != Phase::Skill {
|
||||||
panic!("game not in skill phase");
|
panic!("game not in skill phase");
|
||||||
}
|
}
|
||||||
@ -355,73 +361,56 @@ impl Game {
|
|||||||
self.resolve_skills()
|
self.resolve_skills()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_resolution(&mut self, source: &mut Cryp, target: &mut Cryp, cast: &Cast) -> &mut Game {
|
fn log_resolution(&mut self, cast: &Cast) -> &mut Game {
|
||||||
match cast.resolution.disable.disabled {
|
let source = self.cryp_by_id(cast.source_cryp_id).unwrap().clone();
|
||||||
true => {
|
let target = self.cryp_by_id(cast.target_cryp_id).unwrap().clone();
|
||||||
self.log.push(format!("{:} {:?} {:} disabled {:?}", source.name, cast.skill, target.name, cast.resolution.disable.effects));
|
|
||||||
return self;
|
|
||||||
},
|
|
||||||
false => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
for result in cast.resolution.results.iter() {
|
for result in cast.resolution.results.iter() {
|
||||||
match result {
|
match result {
|
||||||
ResolutionResult::Damage { amount, mitigation, category: _, immunity } => {
|
ResolutionResult::Disable { disable } =>
|
||||||
match immunity.immune {
|
self.log.push(format!("{:} {:?} {:} disabled {:?}",
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
source.name, cast.skill, target.name, disable)),
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
|
ResolutionResult::Immunity { immunity } =>
|
||||||
|
self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
||||||
|
cast.resolution.speed, source.name, cast.skill, target.name, immunity)),
|
||||||
|
|
||||||
|
ResolutionResult::TargetKo =>
|
||||||
|
self.log.push(format!("[{:}] {:} {:?} {:} - KO",
|
||||||
|
cast.resolution.speed, source.name, cast.skill, target.name)),
|
||||||
|
|
||||||
|
ResolutionResult::Damage { amount, mitigation, category: _ } =>
|
||||||
|
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, amount, mitigation)),
|
cast.resolution.speed, source.name, cast.skill, target.name, amount, mitigation)),
|
||||||
}
|
|
||||||
},
|
ResolutionResult::Healing { amount, overhealing } =>
|
||||||
ResolutionResult::Healing { amount, overhealing, immunity } => {
|
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)",
|
||||||
match immunity.immune {
|
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:}OH)",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, amount, overhealing)),
|
cast.resolution.speed, source.name, cast.skill, target.name, amount, overhealing)),
|
||||||
}
|
|
||||||
},
|
ResolutionResult::Inversion { healing, damage, recharge, category: _ } => {
|
||||||
ResolutionResult::Inversion { healing, damage, recharge, category: _, immunity } => {
|
match *healing > 0 {
|
||||||
match immunity.immune {
|
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => match *healing > 0 {
|
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:} ({:} recharge)",
|
true => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:} ({:} recharge)",
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, healing, recharge)),
|
cast.resolution.speed, source.name, cast.skill, target.name, healing, recharge)),
|
||||||
false => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:}",
|
false => self.log.push(format!("[{:}] {:} {:?} {:} INVERTED {:}",
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, damage)),
|
cast.resolution.speed, source.name, cast.skill, target.name, damage)),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ResolutionResult::Effect { effect, duration, immunity } => {
|
|
||||||
match immunity.immune {
|
ResolutionResult::Effect { effect, duration } =>
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T",
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)),
|
cast.resolution.speed, source.name, cast.skill, target.name, effect, duration)),
|
||||||
}
|
|
||||||
},
|
ResolutionResult::Removal { effect } =>
|
||||||
ResolutionResult::Removal { effect, immunity } => {
|
self.log.push(format!("[{:}] {:?} removed {:} {:?}",
|
||||||
match immunity.immune {
|
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => self.log.push(format!("[{:}] {:?} removed {:} {:?}",
|
|
||||||
cast.resolution.speed, source.name, target.name, effect)),
|
cast.resolution.speed, source.name, target.name, effect)),
|
||||||
}
|
|
||||||
},
|
ResolutionResult::Recharge { red, blue } =>
|
||||||
ResolutionResult::Recharge { red, blue, immunity } => {
|
self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B",
|
||||||
match immunity.immune {
|
|
||||||
true => self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, immunity.effects)),
|
|
||||||
false => self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B",
|
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, red, blue)),
|
cast.resolution.speed, source.name, cast.skill, target.name, red, blue)),
|
||||||
}
|
|
||||||
},
|
ResolutionResult::Evasion { skill: _, evasion_rating } =>
|
||||||
ResolutionResult::Evasion { skill: _, evasion_rating } => {
|
|
||||||
self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)",
|
self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)",
|
||||||
cast.resolution.speed, source.name, cast.skill, target.name, evasion_rating));
|
cast.resolution.speed, source.name, cast.skill, target.name, evasion_rating)),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,12 +425,11 @@ impl Game {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.stack = sorted;
|
self.stack = sorted;
|
||||||
self.stack.reverse();
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_skills(&mut self) -> &mut Game {
|
fn resolve_skills(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");
|
||||||
}
|
}
|
||||||
@ -461,44 +449,43 @@ impl Game {
|
|||||||
|
|
||||||
self.stack_sort_speed();
|
self.stack_sort_speed();
|
||||||
|
|
||||||
// update the stack with the resolved skills
|
// temp vec of this round's resolving skills
|
||||||
for mut skill in self.stack.clone() {
|
// because need to check cooldown use before pushing them into the complete list
|
||||||
// println!("{:} resolving ", skill);
|
let mut resolving = vec![];
|
||||||
let mut source = self.cryp_by_id(skill.source_cryp_id).unwrap().clone();
|
|
||||||
let mut target = self.cryp_by_id(skill.target_cryp_id).unwrap().clone();
|
|
||||||
|
|
||||||
skill.set_resolution(&mut source, &mut target);
|
while let Some(mut cast) = self.stack.pop() {
|
||||||
|
// println!("{:} resolving ", cast);
|
||||||
|
|
||||||
self.log_resolution(&mut source, &mut target, &skill);
|
cast.finalise(&mut self);
|
||||||
|
|
||||||
self.resolved.push(skill);
|
self.log_resolution(&cast);
|
||||||
|
|
||||||
if target.is_ko() && !target.ko_logged {
|
resolving.push(cast);
|
||||||
self.log.push(format!("{:} KO", target.name));
|
|
||||||
target.effects.clear();
|
|
||||||
target.ko_logged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if source.is_ko() && !source.ko_logged {
|
// if target.is_ko() && !target.ko_logged {
|
||||||
self.log.push(format!("{:} KO", source.name));
|
// self.log.push(format!("{:} KO", target.name));
|
||||||
source.effects.clear();
|
// target.effects.clear();
|
||||||
source.ko_logged = true;
|
// target.ko_logged = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
self.update_cryp(&mut source);
|
// if source.is_ko() && !source.ko_logged {
|
||||||
self.update_cryp(&mut target);
|
// self.log.push(format!("{:} KO", source.name));
|
||||||
|
// source.effects.clear();
|
||||||
|
// source.ko_logged = true;
|
||||||
|
// }
|
||||||
|
|
||||||
// find a way to
|
// self.update_cryp(&mut source);
|
||||||
// resort the stack after each cast because
|
// self.update_cryp(&mut target);
|
||||||
// the cryp speed may have changed
|
|
||||||
// self.stack_sort_speed();
|
self.stack_sort_speed();
|
||||||
};
|
};
|
||||||
|
|
||||||
// println!("{:#?}", self.resolved);
|
// println!("{:#?}", self.resolving);
|
||||||
|
|
||||||
// now Resolve has all been assigned
|
// now Resolve has all been assigned
|
||||||
// handle cooldowns and statuses
|
// handle cooldowns and statuses
|
||||||
self.progress_durations();
|
self.progress_durations(&resolving);
|
||||||
|
self.resolved.append(&mut resolving);
|
||||||
|
|
||||||
if self.finished() {
|
if self.finished() {
|
||||||
return self.finish()
|
return self.finish()
|
||||||
@ -507,7 +494,7 @@ impl Game {
|
|||||||
self.skill_phase_start()
|
self.skill_phase_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_durations(&mut self) -> &mut Game {
|
fn progress_durations(&mut self, resolved: &Vec<Cast>) -> &mut Game {
|
||||||
for mut cryp in self.all_cryps() {
|
for mut cryp in self.all_cryps() {
|
||||||
// println!("progressing durations for {:}", cryp.name);
|
// println!("progressing durations for {:}", cryp.name);
|
||||||
|
|
||||||
@ -518,7 +505,7 @@ impl Game {
|
|||||||
// only reduce cooldowns if no cd was used
|
// only reduce cooldowns if no cd was used
|
||||||
// have to borrow self for the skill check
|
// have to borrow self for the skill check
|
||||||
{
|
{
|
||||||
if let Some(skill) = self.stack.iter_mut().find(|s| s.source_cryp_id == cryp.id) {
|
if let Some(skill) = resolved.iter().find(|s| s.source_cryp_id == cryp.id) {
|
||||||
if skill.used_cooldown() {
|
if skill.used_cooldown() {
|
||||||
cryp.skill_set_cd(skill.skill);
|
cryp.skill_set_cd(skill.skill);
|
||||||
} else {
|
} else {
|
||||||
@ -545,10 +532,9 @@ impl Game {
|
|||||||
self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko()))
|
self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&mut self) -> &mut Game {
|
fn finish(mut self) -> Game {
|
||||||
self.phase = Phase::Finish;
|
self.phase = Phase::Finish;
|
||||||
self.log.push(format!("Game finished."));
|
self.log.push(format!("Game finished."));
|
||||||
self.stack.clear();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let winner = self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko()));
|
let winner = self.teams.iter().find(|t| t.cryps.iter().any(|c| !c.is_ko()));
|
||||||
@ -588,7 +574,7 @@ pub fn game_skill(params: GameSkillParams, tx: &mut Transaction, account: &Accou
|
|||||||
game.add_skill(account.id, params.cryp_id, params.target_cryp_id, params.skill)?;
|
game.add_skill(account.id, params.cryp_id, params.target_cryp_id, params.skill)?;
|
||||||
|
|
||||||
if game.skill_phase_finished() {
|
if game.skill_phase_finished() {
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
game_update(&game, tx)?;
|
game_update(&game, tx)?;
|
||||||
@ -864,7 +850,7 @@ pub fn game_instance_join(tx: &mut Transaction, player: Player, game_id: Uuid) -
|
|||||||
game.team_add(team)?;
|
game.team_add(team)?;
|
||||||
|
|
||||||
if game.can_start() {
|
if game.can_start() {
|
||||||
game.start();
|
game = game.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:?} game joined", game.id);
|
println!("{:?} game joined", game.id);
|
||||||
@ -926,9 +912,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(game.can_start());
|
assert!(game.can_start());
|
||||||
|
|
||||||
game.start();
|
return game.start();
|
||||||
|
|
||||||
return game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_2v2_test_game() -> Game {
|
fn create_2v2_test_game() -> Game {
|
||||||
@ -974,9 +958,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(game.can_start());
|
assert!(game.can_start());
|
||||||
|
|
||||||
game.start();
|
return game.start();
|
||||||
|
|
||||||
return game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -994,7 +976,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(game.skill_phase_finished());
|
assert!(game.skill_phase_finished());
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
||||||
|
|
||||||
@ -1015,7 +997,7 @@ mod tests {
|
|||||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
|
||||||
assert!(game.skill_phase_finished());
|
assert!(game.skill_phase_finished());
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
// should auto progress back to skill phase
|
// should auto progress back to skill phase
|
||||||
assert!(game.phase == Phase::Skill);
|
assert!(game.phase == Phase::Skill);
|
||||||
@ -1045,7 +1027,7 @@ mod tests {
|
|||||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
|
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
|
||||||
|
|
||||||
assert!(game.skill_phase_finished());
|
assert!(game.skill_phase_finished());
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!(!game.team_by_id(y_team.id).cryps[0].is_stunned());
|
assert!(!game.team_by_id(y_team.id).cryps[0].is_stunned());
|
||||||
assert!(game.phase == Phase::Finish);
|
assert!(game.phase == Phase::Finish);
|
||||||
@ -1071,7 +1053,7 @@ mod tests {
|
|||||||
let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestTouch).unwrap();
|
let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestTouch).unwrap();
|
||||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
// should auto progress back to skill phase
|
// should auto progress back to skill phase
|
||||||
assert!(game.phase == Phase::Skill);
|
assert!(game.phase == Phase::Skill);
|
||||||
@ -1082,7 +1064,7 @@ mod tests {
|
|||||||
let _x_block_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::Stun).unwrap();
|
let _x_block_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::Stun).unwrap();
|
||||||
let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Stun).is_some());
|
assert!(game.team_by_id(x_team.id).cryps[0].skill_on_cd(Skill::Stun).is_some());
|
||||||
assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
|
assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none());
|
||||||
@ -1101,7 +1083,7 @@ mod tests {
|
|||||||
let _x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::TestParry).unwrap();
|
let _x_block_id = game.add_skill(x_team.id, x_cryp.id, None, Skill::TestParry).unwrap();
|
||||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestStun).unwrap();
|
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestStun).unwrap();
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
// should not be stunned because of parry
|
// should not be stunned because of parry
|
||||||
assert!(game.team_by_id(x_team.id).cryps[0].is_stunned() == false);
|
assert!(game.team_by_id(x_team.id).cryps[0].is_stunned() == false);
|
||||||
@ -1120,12 +1102,12 @@ mod tests {
|
|||||||
let _x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestSiphon).unwrap();
|
let _x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestSiphon).unwrap();
|
||||||
let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
|
game.add_skill(x_team.id, x_cryp.id, None, Skill::TestBlock).unwrap();
|
||||||
game.add_skill(y_team.id, y_cryp.id, None, Skill::TestBlock).unwrap();
|
game.add_skill(y_team.id, y_cryp.id, None, Skill::TestBlock).unwrap();
|
||||||
|
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
||||||
}
|
}
|
||||||
@ -1148,7 +1130,7 @@ mod tests {
|
|||||||
game.add_skill(x_team.id, y_cryp.id, Some(i_cryp.id), Skill::TestTouch).unwrap();
|
game.add_skill(x_team.id, y_cryp.id, Some(i_cryp.id), Skill::TestTouch).unwrap();
|
||||||
|
|
||||||
assert!(game.skill_phase_finished());
|
assert!(game.skill_phase_finished());
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
assert!([Phase::Skill, Phase::Finish].contains(&game.phase));
|
||||||
|
|
||||||
@ -1165,7 +1147,7 @@ mod tests {
|
|||||||
assert!(game.add_skill(x_team.id, x_cryp.id, Some(i_cryp.id), Skill::TestTouch).is_err());
|
assert!(game.add_skill(x_team.id, x_cryp.id, Some(i_cryp.id), Skill::TestTouch).is_err());
|
||||||
|
|
||||||
assert!(game.skill_phase_finished());
|
assert!(game.skill_phase_finished());
|
||||||
game.resolve_phase_start();
|
game = game.resolve_phase_start();
|
||||||
|
|
||||||
assert!(game.team_by_id(i_team.id).skills_required() == 1);
|
assert!(game.team_by_id(i_team.id).skills_required() == 1);
|
||||||
assert!(game.team_by_id(x_team.id).skills_required() == 2);
|
assert!(game.team_by_id(x_team.id).skills_required() == 2);
|
||||||
|
|||||||
@ -133,7 +133,7 @@ impl Instance {
|
|||||||
.team_add(plr_team)?
|
.team_add(plr_team)?
|
||||||
.team_add(bot_team)?;
|
.team_add(bot_team)?;
|
||||||
|
|
||||||
game.start();
|
game = game.start();
|
||||||
|
|
||||||
Ok(game)
|
Ok(game)
|
||||||
}
|
}
|
||||||
@ -253,7 +253,7 @@ impl Instance {
|
|||||||
.team_add(a_team).unwrap()
|
.team_add(a_team).unwrap()
|
||||||
.team_add(b_team).unwrap();
|
.team_add(b_team).unwrap();
|
||||||
|
|
||||||
game.start();
|
game = game.start();
|
||||||
|
|
||||||
assert!(game.finished());
|
assert!(game.finished());
|
||||||
let winner = game.winner().unwrap();
|
let winner = game.winner().unwrap();
|
||||||
|
|||||||
@ -2,6 +2,8 @@ use rand::{thread_rng, Rng};
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use cryp::{Cryp, CrypEffect, Stat};
|
use cryp::{Cryp, CrypEffect, Stat};
|
||||||
|
use vbox::{Var};
|
||||||
|
use game::{Game};
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub struct Cast {
|
pub struct Cast {
|
||||||
@ -29,8 +31,23 @@ impl Cast {
|
|||||||
Cast::new(source.id, source.account, target.id, skill)
|
Cast::new(source.id, source.account, target.id, skill)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_resolution(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Cast {
|
pub fn finalise(&mut self, game: &mut Game) -> &mut Cast {
|
||||||
self.resolution = self.skill.resolve(cryp, target);
|
let mut results = vec![];
|
||||||
|
let mut source = game.cryp_by_id(self.source_cryp_id).unwrap().clone();
|
||||||
|
self.resolution.speed = source.skill_speed(self.skill);
|
||||||
|
|
||||||
|
let targets = match source.skill_is_aoe(self.skill) {
|
||||||
|
true => game.cryp_aoe_targets(self.target_cryp_id),
|
||||||
|
false => vec![self.target_cryp_id],
|
||||||
|
};
|
||||||
|
|
||||||
|
for target_id in targets {
|
||||||
|
// let mut source = game.cryp_by_id(self.source_cryp_id).unwrap();
|
||||||
|
let mut target = game.cryp_by_id(target_id).unwrap();
|
||||||
|
results.append(&mut self.skill.resolve(&mut source, target));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.resolution.results = results;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,47 +56,33 @@ impl Cast {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type Disable = Vec<Effect>;
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
pub type Immunity = Vec<Effect>;
|
||||||
pub struct Immunity {
|
|
||||||
pub immune: bool,
|
|
||||||
pub effects: Vec<Effect>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub struct Disable {
|
|
||||||
pub disabled: bool,
|
|
||||||
pub effects: Vec<Effect>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Disable {
|
|
||||||
fn new() -> Disable {
|
|
||||||
Disable { disabled: false, effects: vec![] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum ResolutionResult {
|
pub enum ResolutionResult {
|
||||||
Damage { amount: u64, mitigation: u64, category: Category , immunity: Immunity },
|
TargetKo,
|
||||||
Healing { amount: u64, overhealing: u64, immunity: Immunity },
|
Disable { disable: Disable },
|
||||||
Recharge { red: u64, blue: u64, immunity: Immunity },
|
Immunity { immunity: Immunity },
|
||||||
Inversion { healing: u64, damage: u64, recharge: u64, category: Category, immunity: Immunity },
|
Damage { amount: u64, mitigation: u64, category: Category },
|
||||||
Effect { effect: Effect, duration: u8, immunity: Immunity },
|
Healing { amount: u64, overhealing: u64 },
|
||||||
Removal { effect: Effect, immunity: Immunity },
|
Recharge { red: u64, blue: u64 },
|
||||||
|
Inversion { healing: u64, damage: u64, recharge: u64, category: Category },
|
||||||
|
Effect { effect: Effect, duration: u8 },
|
||||||
|
Removal { effect: Effect },
|
||||||
Evasion { skill: Skill, evasion_rating: u64 },
|
Evasion { skill: Skill, evasion_rating: u64 },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||||
pub struct Resolution {
|
pub struct Resolution {
|
||||||
pub skill: Skill,
|
pub skill: Skill,
|
||||||
pub disable: Disable,
|
|
||||||
pub speed: u64,
|
pub speed: u64,
|
||||||
pub results: Vec<ResolutionResult>,
|
pub results: Vec<ResolutionResult>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolution {
|
impl Resolution {
|
||||||
fn new(skill: Skill) -> Resolution {
|
fn new(skill: Skill) -> Resolution {
|
||||||
Resolution { skill, results: vec![], disable: Disable::new(), speed: 0 }
|
Resolution { skill, results: vec![], speed: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,57 +552,6 @@ impl Skill {
|
|||||||
|
|
||||||
pub fn speed(&self) -> u8 {
|
pub fn speed(&self) -> u8 {
|
||||||
match self {
|
match self {
|
||||||
|
|
||||||
// defensive block
|
|
||||||
Skill::Block => 10, // reduce damage
|
|
||||||
Skill::Parry => 10, // avoid all damage
|
|
||||||
Skill::Snare => 10,
|
|
||||||
Skill::Shield => 10, // avoid magic damage,
|
|
||||||
|
|
||||||
// fast phys combat
|
|
||||||
Skill::Attack => 5,
|
|
||||||
Skill::Strike => 10,
|
|
||||||
Skill::Banish => 5,
|
|
||||||
Skill::Blast => 5,
|
|
||||||
Skill::Decay => 5, // dot
|
|
||||||
|
|
||||||
// magic combat trickery
|
|
||||||
Skill::Invert => 3, // hot
|
|
||||||
Skill::Triage => 3, // hot
|
|
||||||
Skill::Slow => 3,
|
|
||||||
Skill::Amplify => 3,
|
|
||||||
Skill::Curse => 3,
|
|
||||||
Skill::Empower => 3,
|
|
||||||
Skill::Haste => 3,
|
|
||||||
|
|
||||||
// general combat
|
|
||||||
Skill::DecayTick => 2, // hot
|
|
||||||
Skill::Siphon => 2,
|
|
||||||
Skill::SiphonTick => 2, // hot
|
|
||||||
Skill::Hex => 2,
|
|
||||||
Skill::Silence => 2,
|
|
||||||
Skill::Stun => 2,
|
|
||||||
Skill::Throw => 2, // no damage stun, adds vulnerable
|
|
||||||
Skill::TriageTick => 2, // hot
|
|
||||||
|
|
||||||
Skill::Heal => 1,
|
|
||||||
Skill::Purify => 1,
|
|
||||||
Skill::Purge => 1,
|
|
||||||
|
|
||||||
Skill::Recharge => 1,
|
|
||||||
Skill::Reflect => 5,
|
|
||||||
Skill::Ruin => 1,
|
|
||||||
Skill::Slay => 1,
|
|
||||||
Skill::Strangle => 5,
|
|
||||||
Skill::StrangleTick => 5,
|
|
||||||
Skill::Clutch => 1,
|
|
||||||
Skill::Taunt => 1,
|
|
||||||
Skill::Toxic => 1,
|
|
||||||
|
|
||||||
|
|
||||||
// unimplemented
|
|
||||||
// Skill::Lag => 2, //
|
|
||||||
|
|
||||||
// -----------------
|
// -----------------
|
||||||
// Test
|
// Test
|
||||||
// -----------------
|
// -----------------
|
||||||
@ -608,78 +560,93 @@ impl Skill {
|
|||||||
Skill::TestBlock => 10,
|
Skill::TestBlock => 10,
|
||||||
Skill::TestParry => 10,
|
Skill::TestParry => 10,
|
||||||
Skill::TestSiphon => 10,
|
Skill::TestSiphon => 10,
|
||||||
|
|
||||||
|
Skill::Strike => u8::max_value(),
|
||||||
|
|
||||||
|
Skill::SiphonTick => Var::from(Skill::Siphon).speed(),
|
||||||
|
Skill::DecayTick => Var::from(Skill::Decay).speed(),
|
||||||
|
Skill::TriageTick => Var::from(Skill::Triage).speed(),
|
||||||
|
Skill::StrangleTick => Var::from(Skill::Strangle).speed(),
|
||||||
|
|
||||||
|
_ => Var::from(*self).speed(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Resolution {
|
pub fn aoe(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Skill::Ruin => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve(&self, source: &mut Cryp, target: &mut Cryp) -> Vec<ResolutionResult> {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let _base: u64 = rng.gen();
|
let _base: u64 = rng.gen();
|
||||||
|
|
||||||
let speed = source.skill_speed(*self);
|
let mut results = vec![];
|
||||||
|
|
||||||
let mut resolution = Resolution { skill: *self, results: vec![], disable: source.disabled(*self), speed };
|
if let Some(disable) = source.disabled(*self) {
|
||||||
|
results.push(ResolutionResult::Disable { disable });
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match self.category() == Category::Red {
|
||||||
|
// true => {
|
||||||
|
// if let Some(evasion) = target.evade(*self) {
|
||||||
|
// results.push(evasion);
|
||||||
|
// return resolution;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// false => (),
|
||||||
|
// }
|
||||||
|
|
||||||
if target.is_ko() {
|
if target.is_ko() {
|
||||||
return resolution;
|
results.push(ResolutionResult::TargetKo);
|
||||||
}
|
return results;
|
||||||
|
|
||||||
if resolution.disable.disabled {
|
|
||||||
return resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.category() == Category::Red {
|
|
||||||
true => {
|
|
||||||
if let Some(evasion) = target.evade(*self) {
|
|
||||||
resolution.results.push(evasion);
|
|
||||||
return resolution;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.is_reflecting() {
|
if target.is_reflecting() {
|
||||||
// guard against overflow
|
// guard against overflow
|
||||||
if source.is_reflecting() {
|
if source.is_reflecting() {
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
let mut copy = source.clone();
|
return self.resolve(target, source);
|
||||||
return self.resolve(&mut copy, source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Skill::Amplify => amplify(source, target, resolution), // increase magic damage
|
Skill::Amplify => amplify(source, target, results), // increase magic damage
|
||||||
Skill::Attack => attack(source, target, resolution),
|
Skill::Attack => attack(source, target, results),
|
||||||
Skill::Banish => banish(source, target, resolution), // TODO prevent all actions
|
Skill::Banish => banish(source, target, results), // TODO prevent all actions
|
||||||
Skill::Blast => blast(source, target, resolution),
|
Skill::Blast => blast(source, target, results),
|
||||||
Skill::Block => block(source, target, resolution),
|
Skill::Block => block(source, target, results),
|
||||||
Skill::Curse => curse(source, target, resolution),
|
Skill::Curse => curse(source, target, results),
|
||||||
Skill::Decay => decay(source, target, resolution), // dot
|
Skill::Decay => decay(source, target, results), // dot
|
||||||
Skill::DecayTick => decay_tick(source, target, resolution), // dot
|
Skill::DecayTick => decay_tick(source, target, results), // dot
|
||||||
Skill::Empower => empower(source, target, resolution), // increased phys damage
|
Skill::Empower => empower(source, target, results), // increased phys damage
|
||||||
Skill::Haste => haste(source, target, resolution), // speed slow
|
Skill::Haste => haste(source, target, results), // speed slow
|
||||||
Skill::Heal => heal(source, target, resolution),
|
Skill::Heal => heal(source, target, results),
|
||||||
Skill::Hex => hex(source, target, resolution), // todo prevent casting
|
Skill::Hex => hex(source, target, results), // todo prevent casting
|
||||||
Skill::Invert => invert(source, target, resolution), // todo prevent casting
|
Skill::Invert => invert(source, target, results), // todo prevent casting
|
||||||
Skill::Parry => parry(source, target, resolution),
|
Skill::Parry => parry(source, target, results),
|
||||||
Skill::Purge => purge(source, target, resolution), // dispel all buffs
|
Skill::Purge => purge(source, target, results), // dispel all buffs
|
||||||
Skill::Purify => purify(source, target, resolution), // dispel all debuffs
|
Skill::Purify => purify(source, target, results), // dispel all debuffs
|
||||||
Skill::Recharge => recharge(source, target, resolution), // target is immune to magic damage and fx
|
Skill::Recharge => recharge(source, target, results), // target is immune to magic damage and fx
|
||||||
Skill::Shield => shield(source, target, resolution), // target is immune to magic damage and fx
|
Skill::Shield => shield(source, target, results), // target is immune to magic damage and fx
|
||||||
Skill::Silence => silence(source, target, resolution), // target cannot cast spells
|
Skill::Silence => silence(source, target, results), // target cannot cast spells
|
||||||
Skill::Siphon => siphon(source, target, resolution),
|
Skill::Siphon => siphon(source, target, results),
|
||||||
Skill::SiphonTick => siphon_tick(source, target, resolution), // hot
|
Skill::SiphonTick => siphon_tick(source, target, results), // hot
|
||||||
Skill::Slow => slow(source, target, resolution), // speed slow
|
Skill::Slow => slow(source, target, results), // speed slow
|
||||||
Skill::Snare => snare(source, target, resolution), // TODO prevent physical moves
|
Skill::Snare => snare(source, target, results), // TODO prevent physical moves
|
||||||
Skill::Strike => strike(source, target, resolution),
|
Skill::Strike => strike(source, target, results),
|
||||||
Skill::Stun => stun(source, target, resolution),
|
Skill::Stun => stun(source, target, results),
|
||||||
Skill::Throw => throw(source, target, resolution), // no damage stun, adds vulnerable
|
Skill::Throw => throw(source, target, results), // no damage stun, adds vulnerable
|
||||||
Skill::Triage => triage(source, target, resolution), // hot
|
Skill::Triage => triage(source, target, results), // hot
|
||||||
Skill::TriageTick => triage_tick(source, target, resolution), // hot
|
Skill::TriageTick => triage_tick(source, target, results), // hot
|
||||||
Skill::Clutch => clutch(source, target, resolution),
|
Skill::Clutch => clutch(source, target, results),
|
||||||
Skill::Strangle => strangle(source, target, resolution),
|
Skill::Strangle => strangle(source, target, results),
|
||||||
Skill::StrangleTick => strangle_tick(source, target, resolution),
|
Skill::StrangleTick => strangle_tick(source, target, results),
|
||||||
|
|
||||||
Skill::Reflect => reflect(source, target, resolution),
|
Skill::Reflect => reflect(source, target, results),
|
||||||
Skill::Ruin => unimplemented!(),
|
Skill::Ruin => unimplemented!(),
|
||||||
Skill::Slay => unimplemented!(),
|
Skill::Slay => unimplemented!(),
|
||||||
Skill::Taunt => unimplemented!(),
|
Skill::Taunt => unimplemented!(),
|
||||||
@ -688,11 +655,11 @@ impl Skill {
|
|||||||
// -----------------
|
// -----------------
|
||||||
// Test
|
// Test
|
||||||
// -----------------
|
// -----------------
|
||||||
Skill::TestTouch => Resolution { skill: Skill::TestTouch, results: vec![], disable: Disable::new(), speed: 0 },
|
Skill::TestTouch => results,
|
||||||
Skill::TestStun => stun(source, target, resolution),
|
Skill::TestStun => stun(source, target, results),
|
||||||
Skill::TestBlock => block(source, target, resolution),
|
Skill::TestBlock => block(source, target, results),
|
||||||
Skill::TestParry => parry(source, target, resolution),
|
Skill::TestParry => parry(source, target, results),
|
||||||
Skill::TestSiphon => siphon(source, target, resolution),
|
Skill::TestSiphon => siphon(source, target, results),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,35 +687,35 @@ impl Skill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attack(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn attack(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.red_damage();
|
let amount = cryp.red_damage();
|
||||||
resolution.results.push(target.deal_red_damage(Skill::Attack, amount));
|
results.push(target.deal_red_damage(Skill::Attack, amount));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stun(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn stun(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Stun, effect));
|
results.push(target.add_effect(Skill::Stun, effect));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clutch(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn clutch(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Clutch, duration: Effect::Clutch.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Clutch, effect));
|
results.push(target.add_effect(Skill::Clutch, effect));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn throw(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn throw(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let stun = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
|
let stun = CrypEffect { effect: Effect::Stun, duration: Effect::Stun.duration(), tick: None };
|
||||||
let vulnerable = CrypEffect { effect: Effect::Vulnerable, duration: Effect::Vulnerable.duration(), tick: None };
|
let vulnerable = CrypEffect { effect: Effect::Vulnerable, duration: Effect::Vulnerable.duration(), tick: None };
|
||||||
|
|
||||||
resolution.results.push(target.add_effect(Skill::Throw, stun));
|
results.push(target.add_effect(Skill::Throw, stun));
|
||||||
resolution.results.push(target.add_effect(Skill::Throw, vulnerable));
|
results.push(target.add_effect(Skill::Throw, vulnerable));
|
||||||
|
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let target_stun = CrypEffect {
|
let target_stun = CrypEffect {
|
||||||
effect: Effect::Strangle,
|
effect: Effect::Strangle,
|
||||||
duration: Effect::Strangle.duration(),
|
duration: Effect::Strangle.duration(),
|
||||||
@ -756,14 +723,14 @@ fn strangle(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> R
|
|||||||
};
|
};
|
||||||
let attacker_immunity = CrypEffect { effect: Effect::Strangling, duration: Effect::Strangling.duration(), tick: None };
|
let attacker_immunity = CrypEffect { effect: Effect::Strangling, duration: Effect::Strangling.duration(), tick: None };
|
||||||
|
|
||||||
resolution.results.push(target.add_effect(Skill::Strangle, target_stun));
|
results.push(target.add_effect(Skill::Strangle, target_stun));
|
||||||
resolution.results.push(cryp.add_effect(Skill::Strangle, attacker_immunity));
|
results.push(cryp.add_effect(Skill::Strangle, attacker_immunity));
|
||||||
return strangle_tick(cryp, target, resolution);
|
return strangle_tick(cryp, target, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.red_damage();
|
let amount = cryp.red_damage();
|
||||||
resolution.results.push(target.deal_red_damage(Skill::StrangleTick, amount));
|
results.push(target.deal_red_damage(Skill::StrangleTick, amount));
|
||||||
|
|
||||||
// remove immunity if target ko
|
// remove immunity if target ko
|
||||||
if target.is_ko() {
|
if target.is_ko() {
|
||||||
@ -774,206 +741,194 @@ fn strangle_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution)
|
|||||||
cryp.effects.remove(i);
|
cryp.effects.remove(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn block(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None };
|
let block = CrypEffect { effect: Effect::Block, duration: Effect::Block.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Block, block));
|
results.push(target.add_effect(Skill::Block, block));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parry(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn parry(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Parry, duration: Effect::Parry.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Parry, effect));
|
results.push(target.add_effect(Skill::Parry, effect));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn snare(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn snare(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None };
|
let snare = CrypEffect { effect: Effect::Snare, duration: Effect::Snare.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Snare, snare));
|
results.push(target.add_effect(Skill::Snare, snare));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None };
|
let empower = CrypEffect { effect: Effect::Empower, duration: Effect::Empower.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Empower, empower));
|
results.push(target.add_effect(Skill::Empower, empower));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heal(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn heal(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.green_damage();
|
let amount = cryp.green_damage();
|
||||||
resolution.results.push(target.deal_green_damage(Skill::Heal, amount));
|
results.push(target.deal_green_damage(Skill::Heal, amount));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn triage(cryp: &mut Cryp, target: &mut Cryp, resolution: Resolution) -> Resolution {
|
fn triage(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect {
|
let effect = CrypEffect {
|
||||||
effect: Effect::Triage,
|
effect: Effect::Triage,
|
||||||
duration: Effect::Triage.duration(),
|
duration: Effect::Triage.duration(),
|
||||||
tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)),
|
tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)),
|
||||||
};
|
};
|
||||||
target.add_effect(Skill::Triage, effect);
|
results.push(target.add_effect(Skill::Triage, effect));
|
||||||
return triage_tick(cryp, target, resolution);
|
return triage_tick(cryp, target, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.blue_damage().wrapping_div(2);
|
let amount = cryp.blue_damage().wrapping_div(2);
|
||||||
resolution.results.push(target.deal_green_damage(Skill::TriageTick, amount));
|
results.push(target.deal_green_damage(Skill::TriageTick, amount));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blast(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn blast(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.blue_damage();
|
let amount = cryp.blue_damage();
|
||||||
resolution.results.push(target.deal_blue_damage(Skill::Blast, amount));
|
results.push(target.deal_blue_damage(Skill::Blast, amount));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn amplify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn amplify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None };
|
let amplify = CrypEffect { effect: Effect::Amplify, duration: Effect::Amplify.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Amplify, amplify));
|
results.push(target.add_effect(Skill::Amplify, amplify));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn haste(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn haste(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Haste, duration: Effect::Haste.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Haste, effect));
|
results.push(target.add_effect(Skill::Haste, effect));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slow(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn slow(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Slow, duration: Effect::Slow.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Slow, effect));
|
results.push(target.add_effect(Skill::Slow, effect));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decay(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn decay(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let decay = CrypEffect {
|
let decay = CrypEffect {
|
||||||
effect: Effect::Decay,
|
effect: Effect::Decay,
|
||||||
duration: Effect::Decay.duration(),
|
duration: Effect::Decay.duration(),
|
||||||
tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)),
|
tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)),
|
||||||
};
|
};
|
||||||
resolution.results.push(target.add_effect(Skill::Decay, decay));
|
results.push(target.add_effect(Skill::Decay, decay));
|
||||||
return decay_tick(cryp, target, resolution);
|
return decay_tick(cryp, target, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.blue_damage();
|
let amount = cryp.blue_damage();
|
||||||
resolution.results.push(target.deal_blue_damage(Skill::DecayTick, amount));
|
results.push(target.deal_blue_damage(Skill::DecayTick, amount));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hex(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn hex(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None };
|
let hex = CrypEffect { effect: Effect::Hex, duration: Effect::Hex.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Hex, hex));
|
results.push(target.add_effect(Skill::Hex, hex));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None };
|
let curse = CrypEffect { effect: Effect::Curse, duration: Effect::Curse.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Curse, curse));
|
results.push(target.add_effect(Skill::Curse, curse));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invert(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn invert(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Invert, duration: Effect::Invert.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Invert, effect));
|
results.push(target.add_effect(Skill::Invert, effect));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reflect(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn reflect(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None };
|
let effect = CrypEffect { effect: Effect::Reflect, duration: Effect::Reflect.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Reflect, effect));
|
results.push(target.add_effect(Skill::Reflect, effect));
|
||||||
return resolution;;
|
return results;;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn recharge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
resolution.results.push(target.recharge());
|
results.push(target.recharge());
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let siphon = CrypEffect {
|
let siphon = CrypEffect {
|
||||||
effect: Effect::Siphon,
|
effect: Effect::Siphon,
|
||||||
duration: Effect::Siphon.duration(),
|
duration: Effect::Siphon.duration(),
|
||||||
tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)),
|
tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)),
|
||||||
};
|
};
|
||||||
resolution.results.push(target.add_effect(Skill::Siphon, siphon));
|
results.push(target.add_effect(Skill::Siphon, siphon));
|
||||||
return siphon_tick(cryp, target, resolution);
|
return siphon_tick(cryp, target, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let amount = cryp.blue_damage();
|
let amount = cryp.blue_damage();
|
||||||
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
|
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
|
||||||
resolution.results.push(siphon_damage.clone());
|
results.push(siphon_damage.clone());
|
||||||
|
|
||||||
match siphon_damage {
|
match siphon_damage {
|
||||||
ResolutionResult::Damage { amount, mitigation: _, category: _, immunity } => {
|
ResolutionResult::Damage { amount, mitigation: _, category: _, } => {
|
||||||
if !immunity.immune {
|
results.push(cryp.deal_green_damage(Skill::Heal, amount));
|
||||||
resolution.results.push(cryp.deal_green_damage(Skill::Heal, amount));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => panic!("siphon tick damage not dealt {:?}", siphon_damage),
|
_ => panic!("siphon tick damage not dealt {:?}", siphon_damage),
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shield(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn shield(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None };
|
let shield = CrypEffect { effect: Effect::Shield, duration: Effect::Shield.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Shield, shield));
|
results.push(target.add_effect(Skill::Shield, shield));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn silence(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None };
|
let silence = CrypEffect { effect: Effect::Silence, duration: Effect::Silence.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Silence, silence));
|
results.push(target.add_effect(Skill::Silence, silence));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let immunity = target.immune(Skill::Purge);
|
|
||||||
let immune = immunity.immune;
|
|
||||||
|
|
||||||
if !immune {
|
|
||||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||||
if ce.effect.category() == Category::BlueBuff {
|
if ce.effect.category() == Category::BlueBuff {
|
||||||
target.effects.remove(i);
|
target.effects.remove(i);
|
||||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
results.push(ResolutionResult::Removal { effect: ce.effect });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let immunity = target.immune(Skill::Purify);
|
|
||||||
let immune = immunity.immune;
|
|
||||||
|
|
||||||
if !immune {
|
|
||||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||||
if ce.effect.category() == Category::BlueDebuff {
|
if ce.effect.category() == Category::BlueDebuff {
|
||||||
target.effects.remove(i);
|
target.effects.remove(i);
|
||||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
results.push(ResolutionResult::Removal { effect: ce.effect });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn banish(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn banish(_cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None };
|
let banish = CrypEffect { effect: Effect::Banish, duration: Effect::Banish.duration(), tick: None };
|
||||||
resolution.results.push(target.add_effect(Skill::Banish, banish));
|
results.push(target.add_effect(Skill::Banish, banish));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strike(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
fn strike(cryp: &mut Cryp, target: &mut Cryp, mut results: Vec<ResolutionResult>) -> Vec<ResolutionResult> {
|
||||||
let _amount = cryp.red_damage();
|
let _amount = cryp.red_damage();
|
||||||
resolution.results.push(target.deal_red_damage(Skill::Attack, u64::max_value()));
|
results.push(target.deal_red_damage(Skill::Attack, u64::max_value()));
|
||||||
return resolution;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -993,7 +948,7 @@ mod tests {
|
|||||||
|
|
||||||
x.deal_red_damage(Skill::Attack, 5);
|
x.deal_red_damage(Skill::Attack, 5);
|
||||||
|
|
||||||
heal(&mut y, &mut x, Resolution::new(Skill::Heal));
|
heal(&mut y, &mut x, vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1005,7 +960,7 @@ mod tests {
|
|||||||
.named(&"camel".to_string());
|
.named(&"camel".to_string());
|
||||||
|
|
||||||
let mut log = vec![];
|
let mut log = vec![];
|
||||||
decay(&mut x, &mut y, Resolution::new(Skill::Triage));
|
decay(&mut x, &mut y, vec![]);
|
||||||
|
|
||||||
assert!(y.effects.iter().any(|e| e.effect == Effect::Decay));
|
assert!(y.effects.iter().any(|e| e.effect == Effect::Decay));
|
||||||
|
|
||||||
@ -1026,13 +981,13 @@ mod tests {
|
|||||||
x.red_damage.force(100);
|
x.red_damage.force(100);
|
||||||
y.hp.force(500);
|
y.hp.force(500);
|
||||||
|
|
||||||
block(&mut y.clone(), &mut y, Resolution::new(Skill::Block));
|
block(&mut y.clone(), &mut y, vec![]);
|
||||||
assert!(y.effects.iter().any(|e| e.effect == Effect::Block));
|
assert!(y.effects.iter().any(|e| e.effect == Effect::Block));
|
||||||
|
|
||||||
let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack));
|
let results = attack(&mut x, &mut y, vec![]);
|
||||||
|
|
||||||
match res.results[0] {
|
match results[0] {
|
||||||
ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 50),
|
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 50),
|
||||||
_ => panic!("not damage"),
|
_ => panic!("not damage"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1047,14 +1002,14 @@ mod tests {
|
|||||||
|
|
||||||
x.red_damage.force(u64::max_value());
|
x.red_damage.force(u64::max_value());
|
||||||
|
|
||||||
clutch(&mut y.clone(), &mut y, Resolution::new(Skill::Clutch));
|
clutch(&mut y.clone(), &mut y, vec![]);
|
||||||
assert!(y.is_clutch());
|
assert!(y.is_clutch());
|
||||||
|
|
||||||
let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack));
|
let results = attack(&mut x, &mut y, vec![]);
|
||||||
assert!(y.hp() == 1);
|
assert!(y.hp() == 1);
|
||||||
|
|
||||||
match res.results[0] {
|
match results[0] {
|
||||||
ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 1023),
|
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 1023),
|
||||||
_ => panic!("not damage"),
|
_ => panic!("not damage"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1072,19 +1027,19 @@ mod tests {
|
|||||||
y.red_shield.reduce(64);
|
y.red_shield.reduce(64);
|
||||||
x.red_damage.force(256 + 64);
|
x.red_damage.force(256 + 64);
|
||||||
|
|
||||||
invert(&mut y.clone(), &mut y, Resolution::new(Skill::Invert));
|
invert(&mut y.clone(), &mut y, vec![]);
|
||||||
assert!(y.is_inverted());
|
assert!(y.is_inverted());
|
||||||
|
|
||||||
// heal should deal green damage
|
// heal should deal green damage
|
||||||
heal(&mut x, &mut y, Resolution::new(Skill::Heal));
|
heal(&mut x, &mut y, vec![]);
|
||||||
assert!(y.hp() == 768);
|
assert!(y.hp() == 768);
|
||||||
|
|
||||||
// attack should heal and recharge red shield
|
// attack should heal and recharge red shield
|
||||||
let res = attack(&mut x, &mut y, Resolution::new(Skill::Attack));
|
let results = attack(&mut x, &mut y, vec![]);
|
||||||
assert!(y.hp() == 1024);
|
assert!(y.hp() == 1024);
|
||||||
|
|
||||||
match res.results[0] {
|
match results[0] {
|
||||||
ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _, immunity: _ } => assert_eq!(recharge, 64),
|
ResolutionResult::Inversion { damage: _, healing: _, recharge, category: _ } => assert_eq!(recharge, 64),
|
||||||
_ => panic!("not inversion"),
|
_ => panic!("not inversion"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1097,17 +1052,15 @@ mod tests {
|
|||||||
let mut y = Cryp::new()
|
let mut y = Cryp::new()
|
||||||
.named(&"camel".to_string());
|
.named(&"camel".to_string());
|
||||||
|
|
||||||
reflect(&mut y.clone(), &mut y, Resolution::new(Skill::Reflect));
|
reflect(&mut y.clone(), &mut y, vec![]);
|
||||||
assert!(y.is_reflecting());
|
assert!(y.is_reflecting());
|
||||||
|
|
||||||
// heal should deal green damage
|
let results = Skill::Attack.resolve(&mut x, &mut y);
|
||||||
let mut cast = Cast::new(Uuid::nil(), Uuid::nil(), Uuid::nil(), Skill::Attack);
|
|
||||||
cast.set_resolution(&mut x, &mut y);
|
|
||||||
|
|
||||||
assert!(x.hp() == 768);
|
assert!(x.hp() == 768);
|
||||||
|
|
||||||
match cast.resolution.results[0] {
|
match results[0] {
|
||||||
ResolutionResult::Damage { amount, mitigation: _, category: _, immunity: _ } => assert_eq!(amount, 256),
|
ResolutionResult::Damage { amount, mitigation: _, category: _ } => assert_eq!(amount, 256),
|
||||||
_ => panic!("not damage"),
|
_ => panic!("not damage"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1130,15 +1083,9 @@ mod tests {
|
|||||||
y.deal_red_damage(Skill::Attack, 5);
|
y.deal_red_damage(Skill::Attack, 5);
|
||||||
let prev_hp = y.hp();
|
let prev_hp = y.hp();
|
||||||
|
|
||||||
let res = Resolution::new(Skill::Triage);
|
let results = triage(&mut x, &mut y, vec![]);
|
||||||
|
|
||||||
triage(&mut x, &mut y, res);
|
|
||||||
|
|
||||||
assert!(y.effects.iter().any(|e| e.effect == Effect::Triage));
|
assert!(y.effects.iter().any(|e| e.effect == Effect::Triage));
|
||||||
|
|
||||||
let res = Resolution::new(Skill::TriageTick);
|
|
||||||
triage_tick(&mut x, &mut y, res);
|
|
||||||
|
|
||||||
assert!(y.hp() > prev_hp);
|
assert!(y.hp() > prev_hp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,11 +1103,10 @@ mod tests {
|
|||||||
y.deal_red_damage(Skill::Attack, 5);
|
y.deal_red_damage(Skill::Attack, 5);
|
||||||
y.deal_blue_damage(Skill::Blast, 5);
|
y.deal_blue_damage(Skill::Blast, 5);
|
||||||
|
|
||||||
let mut res = Resolution::new(Skill::Recharge);
|
let results = recharge(&mut x, &mut y, vec![]);
|
||||||
res = recharge(&mut x, &mut y, res);
|
|
||||||
|
|
||||||
match res.results[0] {
|
match results[0] {
|
||||||
ResolutionResult::Recharge { red, blue, immunity: _ } => {
|
ResolutionResult::Recharge { red, blue } => {
|
||||||
assert!(red == 5);
|
assert!(red == 5);
|
||||||
assert!(blue == 5);
|
assert!(blue == 5);
|
||||||
}
|
}
|
||||||
@ -1174,9 +1120,9 @@ mod tests {
|
|||||||
let mut x = Cryp::new()
|
let mut x = Cryp::new()
|
||||||
.named(&"muji".to_string());
|
.named(&"muji".to_string());
|
||||||
|
|
||||||
silence(&mut x.clone(), &mut x, Resolution::new(Skill::Silence));
|
silence(&mut x.clone(), &mut x, vec![]);
|
||||||
assert!(x.effects.iter().any(|e| e.effect == Effect::Silence));
|
assert!(x.effects.iter().any(|e| e.effect == Effect::Silence));
|
||||||
assert!(x.disabled(Skill::Silence).disabled);
|
assert!(x.disabled(Skill::Silence).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1186,7 +1132,7 @@ mod tests {
|
|||||||
|
|
||||||
x.blue_damage.force(50);
|
x.blue_damage.force(50);
|
||||||
|
|
||||||
amplify(&mut x.clone(), &mut x, Resolution::new(Skill::Amplify));
|
amplify(&mut x.clone(), &mut x, vec![]);
|
||||||
assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
|
assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
|
||||||
assert_eq!(x.blue_damage(), 100);
|
assert_eq!(x.blue_damage(), 100);
|
||||||
}
|
}
|
||||||
@ -1196,10 +1142,10 @@ mod tests {
|
|||||||
let mut x = Cryp::new()
|
let mut x = Cryp::new()
|
||||||
.named(&"muji".to_string());
|
.named(&"muji".to_string());
|
||||||
|
|
||||||
decay(&mut x.clone(), &mut x, Resolution::new(Skill::Decay));
|
decay(&mut x.clone(), &mut x, vec![]);
|
||||||
assert!(x.effects.iter().any(|e| e.effect == Effect::Decay));
|
assert!(x.effects.iter().any(|e| e.effect == Effect::Decay));
|
||||||
|
|
||||||
purify(&mut x.clone(), &mut x, Resolution::new(Skill::Purify));
|
purify(&mut x.clone(), &mut x, vec![]);
|
||||||
assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
|
assert!(!x.effects.iter().any(|e| e.effect == Effect::Decay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -145,6 +145,27 @@ impl Var {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn speed(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Var::Red => 3,
|
||||||
|
Var::Green => 2,
|
||||||
|
Var::Blue => 1,
|
||||||
|
|
||||||
|
Var::Attack => 1,
|
||||||
|
Var::Stun => 2,
|
||||||
|
Var::Block => 3,
|
||||||
|
Var::Buff => 4,
|
||||||
|
Var::Debuff => 4,
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
let combos = get_combos();
|
||||||
|
let combo = combos.iter().find(|c| c.var == *self)
|
||||||
|
.unwrap_or_else(|| panic!("unable to find components for {:?}", self));
|
||||||
|
return combo.units.iter().fold(0, |acc, c| acc + c.speed());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn effect(&self) -> Option<VarEffect> {
|
fn effect(&self) -> Option<VarEffect> {
|
||||||
if let Some(_skill) = self.into_skill() {
|
if let Some(_skill) = self.into_skill() {
|
||||||
return Some(VarEffect::Skill);
|
return Some(VarEffect::Skill);
|
||||||
@ -163,6 +184,7 @@ impl Var {
|
|||||||
Var::Blast => Some(Skill::Blast),
|
Var::Blast => Some(Skill::Blast),
|
||||||
Var::Block => Some(Skill::Block),
|
Var::Block => Some(Skill::Block),
|
||||||
Var::Curse => Some(Skill::Curse),
|
Var::Curse => Some(Skill::Curse),
|
||||||
|
Var::Decay => Some(Skill::Decay),
|
||||||
Var::Empower => Some(Skill::Empower),
|
Var::Empower => Some(Skill::Empower),
|
||||||
Var::Haste => Some(Skill::Haste),
|
Var::Haste => Some(Skill::Haste),
|
||||||
Var::Heal => Some(Skill::Heal),
|
Var::Heal => Some(Skill::Heal),
|
||||||
@ -250,6 +272,7 @@ impl From<Skill> for Var {
|
|||||||
Skill::Triage => Var::Triage,
|
Skill::Triage => Var::Triage,
|
||||||
Skill::Decay => Var::Decay,
|
Skill::Decay => Var::Decay,
|
||||||
Skill::Reflect => Var::Reflect,
|
Skill::Reflect => Var::Reflect,
|
||||||
|
Skill::Recharge => Var::Recharge,
|
||||||
|
|
||||||
Skill::TestTouch => Var::TestTouch,
|
Skill::TestTouch => Var::TestTouch,
|
||||||
Skill::TestStun => Var::TestStun,
|
Skill::TestStun => Var::TestStun,
|
||||||
@ -479,7 +502,7 @@ impl Vbox {
|
|||||||
self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
||||||
let reclaimed = self.bound.remove(i);
|
let reclaimed = self.bound.remove(i);
|
||||||
let refund = reclaimed.cost();
|
let refund = reclaimed.cost();
|
||||||
println!("reclaiming {:?} for {:?}", refund, reclaimed);
|
// println!("reclaiming {:?} for {:?}", refund, reclaimed);
|
||||||
self.balance_add(refund);
|
self.balance_add(refund);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user