Merge branch 'combos'
This commit is contained in:
+23
-23
@@ -55,43 +55,43 @@ Debuff `Base enemy debuff - reduce enemy speed`
|
||||
|
||||
# Nature Type (red) #
|
||||
|
||||
Bite - (Attack + 3R) Deal significant `Red` damage
|
||||
Strangle - (Stun + 3R) - Applies stun and physical dot
|
||||
Regenerate - (Buff + 3R) Restore red defense for target ally
|
||||
Snare - (Debuff + 3R) Disable enemy red skills for (3?) turns
|
||||
Parry - (Block + 3R) Avoid all damage for this turn
|
||||
Bite - (Attack RR) Deal significant `Red` damage
|
||||
Strangle - (Stun RR) - Applies stun and physical dot
|
||||
Regenerate - (Buff RR) Restore red defense for target ally
|
||||
Snare - (Debuff RR) Disable enemy red skills for (3?) turns
|
||||
Parry - (Block RR) Avoid all damage for this turn
|
||||
|
||||
# Destruction Type (blue) #
|
||||
|
||||
Blast - (Attack + 3B) Deal significant `Blue` damage
|
||||
Ruin - (Stun + 3B) - AOE stun on the enemy team for remaind of turn
|
||||
Amplify - (Buff + 3B) Increased blue damage dealt by target ally
|
||||
Curse - (Debuff + 3B) Decrease damage dealt by target enemy
|
||||
Plague Shield - (Block + 3B) Apply dot debuff to attackers
|
||||
Blast - (Attack BB) Deal significant `Blue` damage
|
||||
Ruin - (Stun BB) - AOE stun on the enemy team for remaind of turn
|
||||
Amplify - (Buff BB) Increased blue damage dealt by target ally
|
||||
Curse - (Debuff BB) Decrease damage dealt by target enemy
|
||||
Plague Shield - (Block BB) Apply dot debuff to attackers
|
||||
|
||||
# Non-Violence Type (green) #
|
||||
|
||||
Heal - (Attack + 3G) Heal ally for X
|
||||
Throw - (Stun + 3G) - Disable target and increase damage taken
|
||||
Triage - (Buff + 3G) Buff which heals ally for X over Y turns
|
||||
Purge - (Debuff + 3G) - Remove all enemy target buffs
|
||||
Reflect - (Block + 3G) - Will use targetted attacks on source
|
||||
Heal - (Attack GG) Heal ally for X
|
||||
Throw - (Stun GG) - Disable target and increase damage taken
|
||||
Triage - (Buff GG) Buff which heals ally for X over Y turns
|
||||
Purge - (Debuff GG) - Remove all enemy target buffs
|
||||
Reflect - (Block GG) - Will use targetted attacks on source
|
||||
|
||||
# Chaos Type (red / blue) #
|
||||
|
||||
Bannish - (Attack + 1R + 2B) - deal `Hybrid Red & Blue` + enemy can't attack or be attacked 3 turns
|
||||
Hex - (Stun + 2R + 1B) - enemy stunned for 3 turns
|
||||
Haste - (Buff + 2R + 1B) - significantly increase ally speed
|
||||
Slow - (Debuff + 1R + 2B) - significantly decrease enemy speed
|
||||
Taunt - (Block + 2B + 1R) - Redirect all enemy targetted skills
|
||||
Bannish - (Attack RB) - deal `Hybrid Red & Blue` + enemy can't attack or be attacked 3 turns
|
||||
Hex - (Stun RB) - enemy stunned for 3 turns
|
||||
Haste - (Buff RB) - significantly increase ally speed
|
||||
Slow - (Debuff RB) - significantly decrease enemy speed
|
||||
Taunt - (Block RB) - Redirect all enemy targetted skills
|
||||
|
||||
# Purity Type (red / green) #
|
||||
|
||||
Slay - (Attack + 1G + 2R) - deal `Red` damage. Bonus damage if the target has blue defense
|
||||
Slay - (Attack + 1G + 1R) - deal `Red` damage. Bonus damage if the target has blue defense
|
||||
Silence - (Stun + 2G + 1R) - enemy can't use blue skills for 3 turns
|
||||
Purify - (Buff + 2G + 1R) - remove all debuffs from target
|
||||
Empower - (Buff + 1G + 2R) - Increased red damage dealt by target ally
|
||||
???? - (Debuff + 1R + 2B) - ???
|
||||
Empower - (Buff + 1G + 1R) - Increased red damage dealt by target ally
|
||||
???? - (Debuff RB) - ???
|
||||
Shield - (Block + 2G + 1R) - Take no blue damage for the next 3 turns
|
||||
|
||||
# Technology Type (green / blue) type - ??? maybe rework and rename #
|
||||
|
||||
+9
-9
@@ -6,16 +6,16 @@
|
||||
Rare `Increased Stamina`
|
||||
|
||||
Common `Increased Evasion rating`
|
||||
Common `Increased Spell Shield rating`
|
||||
Common `Increased Armour rating`
|
||||
Common `Increased Blue Shield rating`
|
||||
Common `Increased RedShield rating`
|
||||
Common `Increased Healing done`
|
||||
Common `Increased Healing received`
|
||||
Common `Increased Spell Damage`
|
||||
Common `Increased Physical Damage`
|
||||
Common `Increased Blue Damage`
|
||||
Common `Increased Red Damage`
|
||||
|
||||
Uncommon `Reduced hp loss penalty to evade chance`
|
||||
Uncommon `Increased base evasion chance per X evasion rating`
|
||||
Uncommon `Increased % mitigation from armour`
|
||||
Uncommon `Increased % mitigation from red_shield`
|
||||
Uncommon `Increased % mitigation from spell shield`
|
||||
Uncommon `Increased damage over time`
|
||||
|
||||
@@ -30,11 +30,11 @@ Rare `25% hex for blast`
|
||||
Rare `cooldown reduction`
|
||||
Rare `effect duration`
|
||||
|
||||
Rare `increased phys dmg, 0 spell damage`
|
||||
Rare `increased spell dmg, 0 phys damage`
|
||||
Rare `increased phys damage, 0 spell damage`
|
||||
Rare `increased spell damage, 0 phys damage`
|
||||
|
||||
Rare `increased phys dmg, silenced`
|
||||
Rare `increased spell dmg, snared`
|
||||
Rare `increased phys damage, silenced`
|
||||
Rare `increased spell damage, snared`
|
||||
|
||||
Rare `increased speed, increased durations`
|
||||
Rare `increased speed, increased cooldowns`
|
||||
|
||||
+3
-3
@@ -21,11 +21,11 @@ resolve phase:
|
||||
2.2 <- attack (normal resolve)
|
||||
1.1 <- hexed (no skills for the rest of this turn and next)
|
||||
|
||||
## Dmg Chart
|
||||
## Damage Chart
|
||||
|
||||
| Physical | Magic | Modifiers |
|
||||
| Red | Magic | Modifiers |
|
||||
| ------ | ------ | ------ |
|
||||
| dmg | dmg | speed |
|
||||
| damage | damage | speed |
|
||||
| evasion | resistance | cooldowns |
|
||||
| reduction | absorption? | durations |
|
||||
|
||||
|
||||
Executable
+166
@@ -0,0 +1,166 @@
|
||||
### Specs ###
|
||||
|
||||
Numbers are placeholder
|
||||
`Specs get a bonus dependent on the total of Red / Green / Blue in team skills`
|
||||
|
||||
# Example to meet 5 red tag bonus
|
||||
In your team Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `Snare`
|
||||
- RR skill `Strike` contributes 2 red tags to the total red tags (2 total)
|
||||
- RG skill `Slay` contributes 1 red tag to the total red tags (3 total)
|
||||
- GG skill `Heal` contirubes 0 red tags to the total red tags (3 total)
|
||||
- RR skill `Snare` contirubes 2 red tags to the total red tags (5 total)
|
||||
|
||||
# Specs also have `Class points`
|
||||
Basic specs (Damage / Health / Defense) will generate class points
|
||||
Advanced specs (Skill Specific Damage, Cooldown reduction, Increased durations, etc) will consume class points
|
||||
|
||||
### Generic Specs
|
||||
|
||||
(Base white skills not upgraded count as have 1 tag basic ?)
|
||||
|
||||
# Basic Damage
|
||||
`Base` -> 10% inc basic damage
|
||||
`Bonus` -> 3 basic tags -> +10% // 6 basic tags -> +15% // 12 basic tags -> +25%
|
||||
Maximum 60% inc basic damage
|
||||
|
||||
# Basic % Life
|
||||
`Base` -> 5% inc life
|
||||
`Bonus` -> 3 basic tags -> +5% // 6 basic tags -> +10% // 12 basic tags -> +15%
|
||||
Maximum 35% inc life
|
||||
|
||||
# Basic Speed
|
||||
`Base` -> 5% inc speed
|
||||
`Bonus` -> 3 basic tags -> +10% // 6 basic tags -> +15% // 12 basic tags -> +20%
|
||||
Maximum 50% inc speed
|
||||
|
||||
# Basic Class Spec
|
||||
`Base` -> +2 all class points
|
||||
`Bonus` -> 3 basic tags -> +2 // 6 basic tags -> +4 // 12 basic tags -> +6
|
||||
Maximum +14 all class points
|
||||
|
||||
# Basic Duration
|
||||
|
||||
### Increased Damage Combos ###
|
||||
|
||||
Generate by combining `Generic Spec (Basic Damage)` with respective RGB
|
||||
|
||||
# Red Damage (Dmg + RR)
|
||||
Add 5 `Nature` Class Points
|
||||
`Base` -> 10% inc red dmg
|
||||
`Bonus` 5 red tags -> +10% // 10 red tags -> +15% // 20 red tags -> +25%
|
||||
Maximum +60% red damage
|
||||
|
||||
# Blue Damage (Dmg + BB) #
|
||||
Add 5 `Destruction` Class Points
|
||||
`Base` -> 10% inc blue dmg
|
||||
`Bonus` 5 blue tags -> +10% // 10 blue tags -> +15% // 20 blue tags -> +25%
|
||||
Maximum +60% blue damage
|
||||
|
||||
# Healing (Dmg + GG) #
|
||||
Add 5 `Non-Violence` Class Points
|
||||
`Base` -> 10% inc healing
|
||||
`Bonus` 5 green tags -> +10% // 10 green tags -> +15% // 20 green tags -> +25%
|
||||
Maximum +60% inc healing
|
||||
|
||||
# Red damage and healing (Dmg + RG)
|
||||
Add 5 `Purity` Class Points
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Bonus` (2R + 2G tags) -> +5% + 5% // (5R + 5G tags) -> +10% + 10% % // (10R + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc red damage and 35% inc healing
|
||||
|
||||
# Red and blue damage (Dmg + RB)
|
||||
Add 5 `Chaos` Class Points
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Bonus` (2 red + 2 green tags) -> +5% + 5% // (5 red + 5 green tags) -> +10% + 10% % // 20 green tags -> +15% + 15%
|
||||
Maximum +35% inc damage and 35% inc healing
|
||||
|
||||
# Blue damage and healing (Dmg + BG)
|
||||
Add 5 `??????` Class Points
|
||||
`Base` -> 5% inc blue damage and 5% inc healing
|
||||
`Bonus` (2B + 2G tags) -> +5% + 5% // (5B + 5G tags) -> +10% + 10% % // (10B + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc blue damage and 35% inc healing
|
||||
|
||||
### Increased Life Combos ###
|
||||
|
||||
Generate by combining `Generic Spec (Basic Life)` with respective RGB
|
||||
|
||||
# Increased % Red Shield (Basic %HP + 2R)
|
||||
Add 5 Nature Class Points
|
||||
`Base` -> 10% inc red shield
|
||||
`Bonus` 5 red tags -> +10% // 10 red tags -> +15% // 20 red tags -> +20%
|
||||
Maximum +55% inc red shield
|
||||
|
||||
# Increased % Red Shield and Life (Basic %HP + 1R1G)
|
||||
Add 5 Purity Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2R + 2G tags) -> +5% + 5% // (5R + 5G tags) -> +10% + 10% % // (10R + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc red shield and 35% inc life
|
||||
|
||||
# Increased % Blue Shield (Basic %HP + 2B)
|
||||
Add 5 Destruction Class Points
|
||||
`Base` -> 10% inc red shield
|
||||
`Bonus` 5 blue tags -> +10% // 10 blue tags -> +15% // 20 blue tags -> +20%
|
||||
Maximum +55% inc blue shield
|
||||
|
||||
# Increased % Blue Shield and Life (Basic %HP + 1B1G)
|
||||
Add 5 ??? Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2B + 2G tags) -> +5% + 5% // (5B + 5G tags) -> +10% + 10% % // (10B + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc life
|
||||
|
||||
# Increased % Life (Basic %HP + 2G)
|
||||
Add 5 Non-Violence Class Points
|
||||
`Base` -> 10% inc hp
|
||||
`Bonus` 5 green tags -> +10% // 10 green tags -> +15% // 20 green tags -> +20%
|
||||
Maximum +55% inc hp
|
||||
|
||||
# Increased % Blue and Red Shield (Basic %HP + 1B1R)
|
||||
Add 5 Chaos Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2B + 2R tags) -> +5% + 5% // (5B + 5R tags) -> +10% + 10% % // (10B + 10R) tags -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc red shield
|
||||
|
||||
## Upgraded Attack Spec Combos
|
||||
|
||||
# Increased Strike Damage (Combine Strike + Red Damage Spec x 2)
|
||||
Consumes 15 Nature Class Points
|
||||
`Base` -> 15% increased strike damage
|
||||
`Bonus` 5 red tags -> +15% // 10 red tags -> +20% // 20 red tags -> +30%
|
||||
Maximum 80% increased strike damage
|
||||
|
||||
# Improved Heal (Combine Heal + Healing Spec x 2)
|
||||
Consumes 15 Non-Violence Class Points
|
||||
`Base` -> 15% increased heal healing
|
||||
`Bonus` 5 green tags -> +15% // green red tags -> +20% // green red tags -> +30%
|
||||
Maximum 80% increased heal healing
|
||||
|
||||
# Increased Blast Damage (Combine Blast + Blue Spec x 2)
|
||||
Consumes 15 Destruction Class Points
|
||||
`Base` -> 15% increased blast damage
|
||||
`Bonus` 5 blue tags -> +15% // 10 blue tags -> +20% // 20 blue tags -> +30%
|
||||
Maximum 80% increased blast damage
|
||||
|
||||
# Increased Slay Damage (Combine Slay + Red Damage Spec + Healing Spec)
|
||||
Consumes 15 Purity Class Points
|
||||
`Base` -> 15% increased slay damage
|
||||
`Bonus` (2R + 2G) tags -> +15% // (5R + 5G) tags -> +20% // (10R + 10G) tags -> +30%
|
||||
Maximum 80% increased slay damage
|
||||
|
||||
# Increased Banish Damage (Combine Slay + Red Damage Spec + Blue Damage Spec)
|
||||
Consumes 15 Chaos Class Points
|
||||
`Base` -> 15% increased slay damage
|
||||
`Bonus` (2R + 2B) tags -> +15% // (5R + 5B) tags -> +20% // (10R + 10B) tags -> +30%
|
||||
Maximum 80% increased banish damage
|
||||
|
||||
## Other Combos
|
||||
|
||||
# Increased % Red Speed (Basic Speed + 2R)
|
||||
Add 5 Nature Class Points
|
||||
`Base` -> 15% inc red speed
|
||||
`Bonus` 5 red tags -> +15% // 10 red tags -> +20% // 20 red tags -> +25%
|
||||
Maximum 80% inc red speed
|
||||
|
||||
# Nature Affinity (Basic Class spec + 2R)
|
||||
`Base` -> 10 Nature Class Points
|
||||
`Bonus` 5 red tags -> +10 // 10 red tags -> +15 // 20 red tags -> +20
|
||||
Maximum 45 Nature Class Points
|
||||
+1
-33
@@ -30,7 +30,7 @@
|
||||
* phys is faster and chaotic
|
||||
* spells are slow and reliable
|
||||
* defensives are implicit
|
||||
* armour is restored, not gained
|
||||
* red_shield is restored, not gained
|
||||
* players can feel aggressive
|
||||
|
||||
# ask sam
|
||||
@@ -56,38 +56,6 @@ taunt
|
||||
|
||||
## NOW
|
||||
|
||||
inventory + drops table
|
||||
id
|
||||
data
|
||||
game
|
||||
|
||||
drops_buy(game_id, index)
|
||||
drops_get()
|
||||
inventory_get()
|
||||
|
||||
reduce balance
|
||||
move drop into inventory
|
||||
|
||||
drops_update()
|
||||
inventory_update()
|
||||
|
||||
-> inventory
|
||||
|
||||
inventory_combine(game_id, [indices])
|
||||
inventory_get()
|
||||
|
||||
new item =
|
||||
match base item
|
||||
match modifiers
|
||||
|
||||
update inventory[base_index]
|
||||
|
||||
inventory_update()
|
||||
|
||||
-> inventory
|
||||
|
||||
|
||||
|
||||
## SOON
|
||||
* clean up categories
|
||||
* why is the text fucked?
|
||||
|
||||
+64
-64
@@ -45,14 +45,14 @@ pub enum Stat {
|
||||
Hp,
|
||||
Speed,
|
||||
Stamina,
|
||||
PhysicalDamage,
|
||||
PhysicalDamageTaken,
|
||||
SpellDamage,
|
||||
SpellDamageTaken,
|
||||
RedDamage,
|
||||
RedDamageTaken,
|
||||
BlueDamage,
|
||||
BlueDamageTaken,
|
||||
Healing,
|
||||
HealingTaken,
|
||||
Armour,
|
||||
SpellShield,
|
||||
RedShield,
|
||||
BlueShield,
|
||||
Evasion,
|
||||
}
|
||||
|
||||
@@ -136,13 +136,13 @@ pub struct CrypRecover {
|
||||
pub struct Cryp {
|
||||
pub id: Uuid,
|
||||
pub account: Uuid,
|
||||
pub phys_dmg: CrypStat,
|
||||
pub spell_dmg: CrypStat,
|
||||
pub red_damage: CrypStat,
|
||||
pub red_shield: CrypStat,
|
||||
pub blue_shield: CrypStat,
|
||||
pub blue_damage: CrypStat,
|
||||
pub speed: CrypStat,
|
||||
pub stamina: CrypStat,
|
||||
pub hp: CrypStat,
|
||||
pub armour: CrypStat,
|
||||
pub spell_shield: CrypStat,
|
||||
pub evasion: CrypStat,
|
||||
pub xp: u64,
|
||||
pub lvl: u8,
|
||||
@@ -164,13 +164,13 @@ impl Cryp {
|
||||
return Cryp {
|
||||
id,
|
||||
account: id,
|
||||
phys_dmg: CrypStat { base: 0, value: 0, stat: Stat::PhysicalDamage },
|
||||
spell_dmg: CrypStat { base: 0, value: 0, stat: Stat::SpellDamage },
|
||||
red_damage: CrypStat { base: 0, value: 0, stat: Stat::RedDamage },
|
||||
red_shield: CrypStat { base: 0, value: 0, stat: Stat::RedShield },
|
||||
blue_damage: CrypStat { base: 0, value: 0, stat: Stat::BlueDamage },
|
||||
blue_shield: CrypStat { base: 0, value: 0, stat: Stat::BlueShield },
|
||||
speed: CrypStat { base: 0, value: 0, stat: Stat::Speed },
|
||||
stamina: CrypStat { base: 0, value: 0, stat: Stat::Stamina },
|
||||
hp: CrypStat { base: 0, value: 0, stat: Stat::Hp },
|
||||
armour: CrypStat { base: 0, value: 0, stat: Stat::Armour },
|
||||
spell_shield: CrypStat { base: 0, value: 0, stat: Stat::SpellShield },
|
||||
evasion: CrypStat { base: 0, value: 0, stat: Stat::Evasion },
|
||||
lvl: 0,
|
||||
xp: 0,
|
||||
@@ -238,15 +238,15 @@ impl Cryp {
|
||||
let evasion_max = 5;
|
||||
|
||||
match stat {
|
||||
Stat::PhysicalDamage => self.phys_dmg.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::SpellDamage => self.spell_dmg.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::RedDamage => self.red_damage.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::BlueDamage => self.blue_damage.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Speed => self.speed.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Stamina => {
|
||||
self.stamina.set(rng.gen_range(stam_min, stam_max), &self.specs);
|
||||
self.hp.set(self.stamina.base, &self.specs)
|
||||
},
|
||||
Stat::SpellShield => self.spell_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Armour => self.armour.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::BlueShield => self.blue_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::RedShield => self.red_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Evasion => self.evasion.set(rng.gen_range(evasion_min, evasion_max), &self.specs),
|
||||
_ => panic!("{:?} not a rollable stat", stat),
|
||||
};
|
||||
@@ -262,8 +262,8 @@ impl Cryp {
|
||||
|
||||
self.xp = xp;
|
||||
|
||||
self.roll_stat(Stat::PhysicalDamage);
|
||||
self.roll_stat(Stat::SpellDamage);
|
||||
self.roll_stat(Stat::RedDamage);
|
||||
self.roll_stat(Stat::BlueDamage);
|
||||
self.roll_stat(Stat::Speed);
|
||||
self.roll_stat(Stat::Stamina);
|
||||
|
||||
@@ -306,7 +306,7 @@ impl Cryp {
|
||||
return Ok(self.recalculate_stats());
|
||||
}
|
||||
|
||||
pub fn spec_remove(mut self, spec: Spec) -> Result<Cryp, Error> {
|
||||
pub fn spec_remove(&mut self, spec: Spec) -> Result<&mut Cryp, Error> {
|
||||
let find_spec = |spec_v: &Vec<Spec>| spec_v.iter().position(|s| s.spec == spec.spec);
|
||||
|
||||
match spec.level {
|
||||
@@ -324,18 +324,18 @@ impl Cryp {
|
||||
},
|
||||
};
|
||||
|
||||
Ok(self)
|
||||
Ok(self.recalculate_stats())
|
||||
}
|
||||
|
||||
|
||||
fn recalculate_stats(&mut self) -> &mut Cryp {
|
||||
self.stamina.recalculate(&self.specs);
|
||||
self.hp.recalculate(&self.specs);
|
||||
self.phys_dmg.recalculate(&self.specs);
|
||||
self.spell_dmg.recalculate(&self.specs);
|
||||
self.red_damage.recalculate(&self.specs);
|
||||
self.red_shield.recalculate(&self.specs);
|
||||
self.blue_damage.recalculate(&self.specs);
|
||||
self.blue_shield.recalculate(&self.specs);
|
||||
self.evasion.recalculate(&self.specs);
|
||||
self.armour.recalculate(&self.specs);
|
||||
self.spell_shield.recalculate(&self.specs);
|
||||
self.speed.recalculate(&self.specs);
|
||||
|
||||
self
|
||||
@@ -468,24 +468,24 @@ impl Cryp {
|
||||
// }
|
||||
|
||||
// Stats
|
||||
pub fn phys_dmg(&self) -> u64 {
|
||||
let phys_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::PhysicalDamage))
|
||||
pub fn red_damage(&self) -> u64 {
|
||||
let red_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::RedDamage))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
let modified_phys_dmg = phys_dmg_mods.iter().fold(self.phys_dmg.value, |acc, m| m.apply(acc));
|
||||
return modified_phys_dmg;
|
||||
let modified_red_damage = red_damage_mods.iter().fold(self.red_damage.value, |acc, m| m.apply(acc));
|
||||
return modified_red_damage;
|
||||
}
|
||||
|
||||
pub fn spell_dmg(&self) -> u64 {
|
||||
let spell_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::SpellDamage))
|
||||
pub fn blue_damage(&self) -> u64 {
|
||||
let blue_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamage))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
let modified_spell_dmg = spell_dmg_mods.iter().fold(self.spell_dmg.value, |acc, m| m.apply(acc));
|
||||
return modified_spell_dmg;
|
||||
let modified_blue_damage = blue_damage_mods.iter().fold(self.blue_damage.value, |acc, m| m.apply(acc));
|
||||
return modified_blue_damage;
|
||||
}
|
||||
|
||||
pub fn skill_speed(&self, s: Skill) -> u64 {
|
||||
@@ -518,7 +518,7 @@ impl Cryp {
|
||||
ResolutionResult::Healing {
|
||||
amount: 0,
|
||||
overhealing: 0,
|
||||
category: Category::PhysHeal,
|
||||
category: Category::RedHeal,
|
||||
immunity: immunity.clone(),
|
||||
};
|
||||
}
|
||||
@@ -546,12 +546,12 @@ impl Cryp {
|
||||
return ResolutionResult::Healing {
|
||||
amount: healing,
|
||||
overhealing,
|
||||
category: Category::PhysHeal,
|
||||
category: Category::RedHeal,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deal_phys_dmg(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
let immunity = self.immune(skill);
|
||||
let immune = immunity.immune;
|
||||
|
||||
@@ -559,29 +559,29 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: 0,
|
||||
mitigation: 0,
|
||||
category: Category::PhysDmg,
|
||||
category: Category::RedDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
let phys_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::PhysicalDamageTaken))
|
||||
let red_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::RedDamageTaken))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
// println!("{:?}", phys_dmg_mods);
|
||||
// println!("{:?}", red_damage_mods);
|
||||
|
||||
let modified_dmg = phys_dmg_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let modified_damage = red_damage_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
|
||||
// calculate amount of damage armour will not absorb
|
||||
// eg 50 armour 25 dmg -> 0 remainder 25 mitigation
|
||||
// 50 armour 100 dmg -> 50 remainder 50 mitigation
|
||||
// 50 armour 5 dmg -> 0 remainder 5 mitigation
|
||||
let remainder = modified_dmg.saturating_sub(self.armour.value);
|
||||
let mitigation = modified_dmg.saturating_sub(remainder);
|
||||
// calculate amount of damage red_shield will not absorb
|
||||
// eg 50 red_shield 25 damage -> 0 remainder 25 mitigation
|
||||
// 50 red_shield 100 damage -> 50 remainder 50 mitigation
|
||||
// 50 red_shield 5 damage -> 0 remainder 5 mitigation
|
||||
let remainder = modified_damage.saturating_sub(self.red_shield.value);
|
||||
let mitigation = modified_damage.saturating_sub(remainder);
|
||||
|
||||
// reduce armour by mitigation amount
|
||||
self.armour.reduce(mitigation);
|
||||
// reduce red_shield by mitigation amount
|
||||
self.red_shield.reduce(mitigation);
|
||||
|
||||
// deal remainder to hp
|
||||
self.hp.reduce(remainder);
|
||||
@@ -589,12 +589,12 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: remainder,
|
||||
mitigation,
|
||||
category: Category::PhysDmg,
|
||||
category: Category::RedDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deal_spell_dmg(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
let immunity = self.immune(skill);
|
||||
let immune = immunity.immune;
|
||||
|
||||
@@ -602,29 +602,29 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: 0,
|
||||
mitigation: 0,
|
||||
category: Category::SpellDmg,
|
||||
category: Category::BlueDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
let spell_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::SpellDamageTaken))
|
||||
let blue_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamageTaken))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
// println!("{:?}", spell_dmg_mods);
|
||||
// println!("{:?}", blue_damage_mods);
|
||||
|
||||
let modified_dmg = spell_dmg_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let remainder = modified_dmg.saturating_sub(self.armour.value);
|
||||
let mitigation = modified_dmg.saturating_sub(remainder);
|
||||
let modified_damage = blue_damage_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let remainder = modified_damage.saturating_sub(self.blue_shield.value);
|
||||
let mitigation = modified_damage.saturating_sub(remainder);
|
||||
|
||||
self.armour.reduce(mitigation);
|
||||
self.blue_shield.reduce(mitigation);
|
||||
self.hp.reduce(remainder);
|
||||
|
||||
return ResolutionResult::Damage {
|
||||
amount: remainder,
|
||||
mitigation,
|
||||
category: Category::SpellDmg,
|
||||
category: Category::BlueDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
@@ -734,7 +734,7 @@ pub fn cryp_forget(params: CrypForgetParams, tx: &mut Transaction, account: &Acc
|
||||
|
||||
pub fn cryp_unspec(params: CrypUnspecParams, tx: &mut Transaction, account: &Account) -> Result<Cryp, Error> {
|
||||
let mut cryp = cryp_get(tx, params.id, account.id)?;
|
||||
cryp = cryp.spec_remove(params.spec)?;
|
||||
cryp.spec_remove(params.spec)?;
|
||||
return cryp_write(cryp, tx);
|
||||
}
|
||||
|
||||
|
||||
+7
-14
@@ -11,7 +11,6 @@ use account::Account;
|
||||
use rpc::{GameStateParams, GameSkillParams, GamePveParams, GamePvpParams, GameJoinParams};
|
||||
use cryp::{Cryp, cryp_get};
|
||||
use skill::{Skill, Cast, ResolutionResult};
|
||||
use item::{item_drop};
|
||||
use zone::{node_finish};
|
||||
use mob::{generate_mob_team};
|
||||
|
||||
@@ -685,12 +684,6 @@ pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> {
|
||||
result.iter().next().ok_or(format_err!("game {:?} could not be written", game))?;
|
||||
|
||||
if game.finished() {
|
||||
if let Some(t) = game.winner() {
|
||||
if !t.id.is_nil() {
|
||||
item_drop(tx, t.id, game.mode)?;
|
||||
}
|
||||
}
|
||||
|
||||
// check for zone update
|
||||
if let Some((z, i)) = game.zone {
|
||||
node_finish(game, z, i, tx)?;
|
||||
@@ -854,7 +847,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block)
|
||||
@@ -868,7 +861,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block)
|
||||
@@ -1014,12 +1007,12 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().phys_dmg.force(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().red_damage.force(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().speed.force(u64::max_value());
|
||||
|
||||
// just in case
|
||||
// remove all mitigation
|
||||
game.team_by_id(x_team.id).cryp_by_id(x_cryp.id).unwrap().armour.force(0);
|
||||
game.team_by_id(x_team.id).cryp_by_id(x_cryp.id).unwrap().red_shield.force(0);
|
||||
|
||||
let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap();
|
||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
|
||||
@@ -1088,7 +1081,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_test() {
|
||||
fn siphon_test() {
|
||||
let mut game = create_test_game();
|
||||
|
||||
let x_team = game.teams[0].clone();
|
||||
@@ -1097,7 +1090,7 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
let _x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestDrain).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();
|
||||
|
||||
game.resolve_phase_start();
|
||||
@@ -1107,7 +1100,7 @@ mod tests {
|
||||
|
||||
game.resolve_phase_start();
|
||||
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -938,7 +938,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Block)
|
||||
.create();
|
||||
@@ -950,7 +950,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Block)
|
||||
.create();
|
||||
@@ -1104,7 +1104,7 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().phys_dmg.set(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().red_damage.set(u64::max_value());
|
||||
|
||||
let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestStun).unwrap();
|
||||
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::Attack).unwrap();
|
||||
@@ -1194,7 +1194,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_test() {
|
||||
fn siphon_test() {
|
||||
let mut game = create_test_game();
|
||||
|
||||
let x_team = game.teams[0].clone();
|
||||
@@ -1203,13 +1203,13 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
let x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestDrain).unwrap();
|
||||
let x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestSiphon).unwrap();
|
||||
let y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
|
||||
|
||||
game.target_phase_start();
|
||||
|
||||
game.add_target(x_team.id, x_cryp.id, y_touch_id).unwrap();
|
||||
game.add_target(y_team.id, y_cryp.id, x_drain_id).unwrap();
|
||||
game.add_target(y_team.id, y_cryp.id, x_siphon_id).unwrap();
|
||||
|
||||
game.resolve_phase_start();
|
||||
|
||||
@@ -1218,7 +1218,7 @@ mod tests {
|
||||
|
||||
game.target_phase_start();
|
||||
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+26
-26
@@ -17,19 +17,19 @@ use spec::{Spec, SpecType};
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum ItemAction {
|
||||
RerollPhysDamage,
|
||||
RerollSpellDamage,
|
||||
RerollRedDamage,
|
||||
RerollBlueDamage,
|
||||
RerollSpeed,
|
||||
RerollStamina,
|
||||
RerollArmour,
|
||||
RerollSpellShield,
|
||||
RerollRedShield,
|
||||
RerollBlueShield,
|
||||
RerollEvasion,
|
||||
|
||||
SpecPhysDmg5,
|
||||
SpecSpellDmg5,
|
||||
SpecArmour5,
|
||||
SpecSpellShield5,
|
||||
SpecSpellEvasion5,
|
||||
SpecRedDamage5,
|
||||
SpecBlueDamage5,
|
||||
SpecRedShield5,
|
||||
SpecBlueShield5,
|
||||
SpecBlueEvasion5,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
@@ -44,24 +44,24 @@ impl Item {
|
||||
pub fn new(action: ItemAction, account_id: Uuid) -> Item {
|
||||
let id = Uuid::new_v4();
|
||||
return Item {
|
||||
id,
|
||||
account: account_id,
|
||||
action,
|
||||
id,
|
||||
account: account_id,
|
||||
action,
|
||||
};
|
||||
}
|
||||
|
||||
fn apply(&mut self, tx: &mut Transaction, target: Uuid) -> Result<(), Error> {
|
||||
match self.action {
|
||||
ItemAction::RerollStamina => reroll(self, tx, target, Stat::Stamina),
|
||||
ItemAction::RerollPhysDamage => reroll(self, tx, target, Stat::PhysicalDamage),
|
||||
ItemAction::RerollSpellDamage => reroll(self, tx, target, Stat::SpellDamage),
|
||||
ItemAction::RerollRedDamage => reroll(self, tx, target, Stat::RedDamage),
|
||||
ItemAction::RerollBlueDamage => reroll(self, tx, target, Stat::BlueDamage),
|
||||
ItemAction::RerollSpeed => reroll(self, tx, target, Stat::Speed),
|
||||
ItemAction::RerollArmour => reroll(self, tx, target, Stat::Armour),
|
||||
ItemAction::RerollSpellShield => reroll(self, tx, target, Stat::SpellShield),
|
||||
ItemAction::RerollRedShield => reroll(self, tx, target, Stat::RedShield),
|
||||
ItemAction::RerollBlueShield => reroll(self, tx, target, Stat::BlueShield),
|
||||
ItemAction::RerollEvasion => reroll(self, tx, target, Stat::Evasion),
|
||||
|
||||
ItemAction::SpecPhysDmg5 => spec_add(self, tx, target, SpecType::PhysDamage5),
|
||||
ItemAction::SpecSpellDmg5 => spec_add(self, tx, target, SpecType::SpellDamage5),
|
||||
ItemAction::SpecRedDamage5 => spec_add(self, tx, target, SpecType::RedDamage5),
|
||||
ItemAction::SpecBlueDamage5 => spec_add(self, tx, target, SpecType::BlueDamage5),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
@@ -86,8 +86,8 @@ fn mode_drops(mode: GameMode) -> Vec<(ItemAction, usize)> {
|
||||
match mode {
|
||||
GameMode::Normal => vec![
|
||||
(ItemAction::RerollStamina, 1),
|
||||
(ItemAction::RerollPhysDamage, 1),
|
||||
(ItemAction::RerollSpellDamage, 1),
|
||||
(ItemAction::RerollRedDamage, 1),
|
||||
(ItemAction::RerollBlueDamage, 1),
|
||||
],
|
||||
GameMode::Pvp => vec![
|
||||
(ItemAction::RerollSpeed, 1),
|
||||
@@ -96,19 +96,19 @@ fn mode_drops(mode: GameMode) -> Vec<(ItemAction, usize)> {
|
||||
GameMode::Zone2v2Caster |
|
||||
GameMode::Zone3v3MeleeMiniboss => vec![
|
||||
(ItemAction::RerollEvasion, 1),
|
||||
(ItemAction::RerollArmour, 1),
|
||||
(ItemAction::RerollSpellShield, 1),
|
||||
(ItemAction::RerollRedShield, 1),
|
||||
(ItemAction::RerollBlueShield, 1),
|
||||
],
|
||||
GameMode::Zone3v3HealerBoss => vec![
|
||||
(ItemAction::RerollSpeed, 1),
|
||||
],
|
||||
// _ => vec![
|
||||
// (ItemAction::RerollStamina, 1),
|
||||
// (ItemAction::RerollPhysDamage, 1),
|
||||
// (ItemAction::RerollSpellDamage, 1),
|
||||
// (ItemAction::RerollRedDamage, 1),
|
||||
// (ItemAction::RerollBlueDamage, 1),
|
||||
// (ItemAction::RerollSpeed, 1),
|
||||
// (ItemAction::RerollArmour, 1),
|
||||
// (ItemAction::RerollSpellShield, 1),
|
||||
// (ItemAction::RerollRedShield, 1),
|
||||
// (ItemAction::RerollBlueShield, 1),
|
||||
// (ItemAction::RerollEvasion, 1),
|
||||
// ],
|
||||
}
|
||||
|
||||
+3
-1
@@ -26,10 +26,12 @@ mod spec;
|
||||
// mod passives;
|
||||
mod rpc;
|
||||
mod account;
|
||||
mod item;
|
||||
// mod item;
|
||||
mod zone;
|
||||
mod mob;
|
||||
|
||||
mod vbox;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use net::{start};
|
||||
|
||||
|
||||
+151
-77
@@ -18,10 +18,10 @@ use net::Db;
|
||||
use cryp::{Cryp, cryp_spawn, cryp_learn, cryp_forget, cryp_unspec};
|
||||
use game::{Game, game_state, game_pve, game_pvp, game_join, game_joinable_list, game_skill};
|
||||
use account::{Account, account_create, account_login, account_from_token, account_cryps, account_zone};
|
||||
use item::{Item, ItemAction, items_list, item_use, item_create};
|
||||
use skill::{Skill};
|
||||
use zone::{Zone, zone_create, zone_join, zone_close};
|
||||
use spec::{Spec};
|
||||
use vbox::{Vbox, vbox_state, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_drop};
|
||||
|
||||
pub struct Rpc;
|
||||
|
||||
@@ -76,11 +76,14 @@ impl Rpc {
|
||||
"zone_join" => Rpc::zone_join(data, &mut tx, account.unwrap(), client),
|
||||
"zone_close" => Rpc::zone_close(data, &mut tx, account.unwrap(), client),
|
||||
"account_cryps" => Rpc::account_cryps(data, &mut tx, account.unwrap(), client),
|
||||
"account_items" => Rpc::account_items(data, &mut tx, account.unwrap(), client),
|
||||
"account_zone" => Rpc::account_zone(data, &mut tx, account.unwrap(), client),
|
||||
"item_use" => Rpc::item_use(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
"press_r" => Rpc::press_r(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_state" => Rpc::vbox_state(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_accept" => Rpc::vbox_accept(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_apply" => Rpc::vbox_apply(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_drop" => Rpc::vbox_drop(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_combine" => Rpc::vbox_combine(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_discard" => Rpc::vbox_discard(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
_ => Err(format_err!("unknown method - {:?}", v.method)),
|
||||
};
|
||||
@@ -251,8 +254,6 @@ impl Rpc {
|
||||
Ok(cryp_list)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn account_create(data: Vec<u8>, tx: &mut Transaction, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
match from_slice::<AccountCreateMsg>(&data) {
|
||||
Ok(v) => Ok(RpcResponse {
|
||||
@@ -290,7 +291,7 @@ impl Rpc {
|
||||
let cryp = cryp_spawn(CrypSpawnParams { name }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Decay }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Blast }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Drain }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Siphon }, tx, &account)?;
|
||||
|
||||
let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
|
||||
let cryp = cryp_spawn(CrypSpawnParams { name }, tx, &account)?;
|
||||
@@ -314,13 +315,6 @@ impl Rpc {
|
||||
})
|
||||
}
|
||||
|
||||
fn account_items(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
Ok(RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
})
|
||||
}
|
||||
|
||||
fn account_zone(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
Ok(RpcResponse {
|
||||
method: "zone_state".to_string(),
|
||||
@@ -328,49 +322,6 @@ impl Rpc {
|
||||
})
|
||||
}
|
||||
|
||||
fn press_r(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
for action in [
|
||||
ItemAction::RerollPhysDamage,
|
||||
ItemAction::RerollSpellDamage,
|
||||
ItemAction::RerollSpeed,
|
||||
ItemAction::RerollStamina,
|
||||
ItemAction::RerollArmour,
|
||||
ItemAction::RerollSpellShield,
|
||||
ItemAction::RerollEvasion,
|
||||
ItemAction::SpecPhysDmg5,
|
||||
ItemAction::SpecSpellDmg5,
|
||||
].into_iter() {
|
||||
let item = Item::new(*action, account.id);
|
||||
item_create(item, tx, account.id)?;
|
||||
}
|
||||
|
||||
let res = RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
|
||||
fn item_use(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<ItemUseMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
item_use(msg.params, tx, &account)?;
|
||||
|
||||
Rpc::send_msg(client, RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
})?;
|
||||
|
||||
let cryps_list = RpcResponse {
|
||||
method: "account_cryps".to_string(),
|
||||
params: RpcResult::CrypList(account_cryps(tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(cryps_list);
|
||||
}
|
||||
|
||||
fn zone_create(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
// let _msg = from_slice::<ZoneCreateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
@@ -404,6 +355,77 @@ impl Rpc {
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxStateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_state(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_accept(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxAcceptMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_accept(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_discard(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxDiscardMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_discard(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
|
||||
fn vbox_combine(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxCombineMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_combine(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_apply(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxApplyMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_apply(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
Rpc::send_msg(client, RpcResponse {
|
||||
method: "account_cryps".to_string(),
|
||||
params: RpcResult::CrypList(account_cryps(tx, &account)?)
|
||||
})?;
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_drop(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxDropMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_drop(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
@@ -422,10 +444,10 @@ pub enum RpcResult {
|
||||
CrypList(Vec<Cryp>),
|
||||
GameState(Game),
|
||||
GameJoinableList(Vec<Game>),
|
||||
ItemList(Vec<Item>),
|
||||
ItemUse(()),
|
||||
ZoneState(Zone),
|
||||
ZoneClose(()),
|
||||
|
||||
VboxState(Vbox),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
@@ -589,24 +611,6 @@ struct AccountCrypsMsg {
|
||||
params: (),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ItemListMsg {
|
||||
method: String,
|
||||
params: (),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ItemUseMsg {
|
||||
method: String,
|
||||
params: ItemUseParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct ItemUseParams {
|
||||
pub item: Uuid,
|
||||
pub target: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ZoneCreateMsg {
|
||||
method: String,
|
||||
@@ -637,6 +641,76 @@ pub struct ZoneCloseParams {
|
||||
pub zone_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxStateMsg {
|
||||
method: String,
|
||||
params: VboxStateParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxStateParams {
|
||||
pub game_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxAcceptMsg {
|
||||
method: String,
|
||||
params: VboxAcceptParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxAcceptParams {
|
||||
pub game_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxDiscardMsg {
|
||||
method: String,
|
||||
params: VboxDiscardParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxDiscardParams {
|
||||
pub game_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxCombineMsg {
|
||||
method: String,
|
||||
params: VboxCombineParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxCombineParams {
|
||||
pub game_id: Uuid,
|
||||
pub indices: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxApplyMsg {
|
||||
method: String,
|
||||
params: VboxApplyParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxApplyParams {
|
||||
pub game_id: Uuid,
|
||||
pub cryp_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxDropMsg {
|
||||
method: String,
|
||||
params: VboxDropParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxDropParams {
|
||||
pub game_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
|
||||
+165
-165
@@ -125,9 +125,9 @@ pub enum Effect {
|
||||
Triage,
|
||||
Decay,
|
||||
Regen,
|
||||
Drain,
|
||||
Siphon,
|
||||
|
||||
SpeedDrain,
|
||||
SpeedSiphon,
|
||||
SpeedIncrease,
|
||||
|
||||
Ko,
|
||||
@@ -137,13 +137,13 @@ impl Effect {
|
||||
pub fn immune(&self, skill: Skill) -> bool {
|
||||
match self {
|
||||
Effect::Parry => match skill.category() {
|
||||
Category::Spell => false,
|
||||
Category::Physical => true,
|
||||
Category::Blue => false,
|
||||
Category::Red => true,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Shield => match skill.category() {
|
||||
Category::Spell => true,
|
||||
Category::Physical => false,
|
||||
Category::Blue => true,
|
||||
Category::Red => false,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Banish => true,
|
||||
@@ -157,18 +157,18 @@ impl Effect {
|
||||
Effect::Hex => true,
|
||||
Effect::Banish => true,
|
||||
Effect::Silence => match skill.category() {
|
||||
Category::Spell => true,
|
||||
Category::Physical => false,
|
||||
Category::Blue => true,
|
||||
Category::Red => false,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Snare => match skill.category() {
|
||||
Category::Spell => false,
|
||||
Category::Physical => true,
|
||||
Category::Blue => false,
|
||||
Category::Red => true,
|
||||
_ => false,
|
||||
},
|
||||
|
||||
Effect::Ko => match skill.category() {
|
||||
Category::SpellTick => false,
|
||||
Category::BlueTick => false,
|
||||
_ => true,
|
||||
},
|
||||
_ => false,
|
||||
@@ -177,12 +177,12 @@ impl Effect {
|
||||
|
||||
pub fn modifications(&self) -> Vec<Stat> {
|
||||
match self {
|
||||
Effect::Empower => vec![Stat::PhysicalDamage],
|
||||
Effect::Vulnerable => vec![Stat::PhysicalDamageTaken],
|
||||
Effect::Block => vec![Stat::PhysicalDamageTaken],
|
||||
Effect::Empower => vec![Stat::RedDamage],
|
||||
Effect::Vulnerable => vec![Stat::RedDamageTaken],
|
||||
Effect::Block => vec![Stat::RedDamageTaken],
|
||||
|
||||
Effect::Amplify => vec![Stat::SpellDamage],
|
||||
Effect::Curse => vec![Stat::SpellDamageTaken],
|
||||
Effect::Amplify => vec![Stat::BlueDamage],
|
||||
Effect::Curse => vec![Stat::BlueDamageTaken],
|
||||
|
||||
Effect::Haste => vec![Stat::Speed],
|
||||
Effect::Slow => vec![Stat::Speed],
|
||||
@@ -216,43 +216,43 @@ impl Effect {
|
||||
pub fn category(&self) -> Category {
|
||||
match self {
|
||||
// physical
|
||||
Effect::Stun => Category::PhysDebuff,
|
||||
Effect::Block => Category::PhysBuff,
|
||||
Effect::Parry => Category::PhysBuff,
|
||||
Effect::Bleed => Category::PhysDebuff,
|
||||
Effect::Leech => Category::PhysDebuff,
|
||||
Effect::Airborne => Category::PhysDebuff,
|
||||
Effect::Untouchable => Category::PhysBuff,
|
||||
Effect::Deadly => Category::PhysBuff,
|
||||
Effect::Vulnerable => Category::PhysDebuff,
|
||||
Effect::Fury => Category::PhysBuff,
|
||||
Effect::Blind => Category::PhysDebuff,
|
||||
Effect::Snare => Category::PhysDebuff,
|
||||
Effect::Stun => Category::RedDebuff,
|
||||
Effect::Block => Category::RedBuff,
|
||||
Effect::Parry => Category::RedBuff,
|
||||
Effect::Bleed => Category::RedDebuff,
|
||||
Effect::Leech => Category::RedDebuff,
|
||||
Effect::Airborne => Category::RedDebuff,
|
||||
Effect::Untouchable => Category::RedBuff,
|
||||
Effect::Deadly => Category::RedBuff,
|
||||
Effect::Vulnerable => Category::RedDebuff,
|
||||
Effect::Fury => Category::RedBuff,
|
||||
Effect::Blind => Category::RedDebuff,
|
||||
Effect::Snare => Category::RedDebuff,
|
||||
|
||||
Effect::Empower => Category::PhysBuff,
|
||||
Effect::Empower => Category::RedBuff,
|
||||
|
||||
// magic
|
||||
Effect::Hex => Category::SpellDebuff,
|
||||
Effect::Curse => Category::SpellDebuff,
|
||||
Effect::Banish => Category::SpellDebuff, // todo randomise
|
||||
Effect::Slow => Category::SpellDebuff,
|
||||
Effect::Haste => Category::SpellBuff,
|
||||
Effect::Enslave => Category::SpellDebuff,
|
||||
Effect::Mesmerise => Category::SpellDebuff,
|
||||
Effect::Amplify => Category::SpellBuff,
|
||||
Effect::Silence => Category::SpellDebuff,
|
||||
Effect::Hex => Category::BlueDebuff,
|
||||
Effect::Curse => Category::BlueDebuff,
|
||||
Effect::Banish => Category::BlueDebuff, // todo randomise
|
||||
Effect::Slow => Category::BlueDebuff,
|
||||
Effect::Haste => Category::BlueBuff,
|
||||
Effect::Enslave => Category::BlueDebuff,
|
||||
Effect::Mesmerise => Category::BlueDebuff,
|
||||
Effect::Amplify => Category::BlueBuff,
|
||||
Effect::Silence => Category::BlueDebuff,
|
||||
|
||||
// magic immunity
|
||||
Effect::Shield => Category::SpellBuff,
|
||||
Effect::Shield => Category::BlueBuff,
|
||||
|
||||
// effects over time
|
||||
Effect::Triage => Category::SpellBuff,
|
||||
Effect::Decay => Category::SpellDebuff,
|
||||
Effect::Regen => Category::SpellBuff,
|
||||
Effect::Drain => Category::SpellDebuff,
|
||||
Effect::Triage => Category::BlueBuff,
|
||||
Effect::Decay => Category::BlueDebuff,
|
||||
Effect::Regen => Category::BlueBuff,
|
||||
Effect::Siphon => Category::BlueDebuff,
|
||||
|
||||
Effect::SpeedDrain => Category::SpellDebuff,
|
||||
Effect::SpeedIncrease => Category::SpellBuff,
|
||||
Effect::SpeedSiphon => Category::BlueDebuff,
|
||||
Effect::SpeedIncrease => Category::BlueBuff,
|
||||
|
||||
Effect::Ko => Category::Ko,
|
||||
}
|
||||
@@ -283,7 +283,7 @@ impl Effect {
|
||||
|
||||
Effect::Triage => 3,
|
||||
Effect::Decay => 3,
|
||||
Effect::Drain => 2,
|
||||
Effect::Siphon => 2,
|
||||
|
||||
_ => {
|
||||
println!("{:?} does not have a duration", self);
|
||||
@@ -296,18 +296,18 @@ impl Effect {
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum Category {
|
||||
Physical,
|
||||
PhysHeal,
|
||||
PhysDmg,
|
||||
PhysDebuff,
|
||||
PhysBuff,
|
||||
PhysTick,
|
||||
Spell,
|
||||
SpellDmg,
|
||||
SpellHeal,
|
||||
SpellDebuff,
|
||||
SpellBuff,
|
||||
SpellTick,
|
||||
Red,
|
||||
RedHeal,
|
||||
RedDamage,
|
||||
RedDebuff,
|
||||
RedBuff,
|
||||
RedTick,
|
||||
Blue,
|
||||
BlueDamage,
|
||||
BlueHeal,
|
||||
BlueDebuff,
|
||||
BlueBuff,
|
||||
BlueTick,
|
||||
Ko,
|
||||
}
|
||||
|
||||
@@ -318,8 +318,8 @@ pub enum Skill {
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Block, // reduce dmg
|
||||
Parry, // avoid all dmg
|
||||
Block, // reduce damage
|
||||
Parry, // avoid all damage
|
||||
Snare,
|
||||
|
||||
Paralyse,
|
||||
@@ -345,7 +345,7 @@ pub enum Skill {
|
||||
Heal,
|
||||
Triage, // hot
|
||||
TriageTick,
|
||||
Throw, // no dmg stun, adds vulnerable
|
||||
Throw, // no damage stun, adds vulnerable
|
||||
Charm,
|
||||
Calm,
|
||||
Rez,
|
||||
@@ -360,8 +360,8 @@ pub enum Skill {
|
||||
Amplify,
|
||||
Decay, // dot
|
||||
DecayTick, // dot
|
||||
Drain,
|
||||
DrainTick,
|
||||
Siphon,
|
||||
SiphonTick,
|
||||
Curse,
|
||||
Plague, // aoe dot
|
||||
Ruin, // aoe
|
||||
@@ -389,12 +389,12 @@ pub enum Skill {
|
||||
Haste,
|
||||
Slow,
|
||||
|
||||
// used by tests, no cd, no dmg
|
||||
// used by tests, no cd, no damage
|
||||
TestTouch,
|
||||
TestStun,
|
||||
TestBlock,
|
||||
TestParry,
|
||||
TestDrain,
|
||||
TestSiphon,
|
||||
}
|
||||
|
||||
impl Skill {
|
||||
@@ -405,8 +405,8 @@ impl Skill {
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Skill::Block => None, // reduce dmg
|
||||
Skill::Parry => None, // avoid all dmg
|
||||
Skill::Block => None, // reduce damage
|
||||
Skill::Parry => None, // avoid all damage
|
||||
Skill::Snare => Some(1),
|
||||
|
||||
Skill::Paralyse => Some(1),
|
||||
@@ -431,7 +431,7 @@ impl Skill {
|
||||
Skill::Heal => None,
|
||||
Skill::Triage => None, // hot
|
||||
Skill::TriageTick => None,
|
||||
Skill::Throw => Some(1), // no dmg stun, adds vulnerable
|
||||
Skill::Throw => Some(1), // no damage stun, adds vulnerable
|
||||
Skill::Charm => Some(1),
|
||||
Skill::Calm => None,
|
||||
Skill::Rez => Some(2),
|
||||
@@ -443,8 +443,8 @@ impl Skill {
|
||||
Skill::Amplify => Some(1),
|
||||
Skill::Decay => None, // dot
|
||||
Skill::DecayTick => None,
|
||||
Skill::Drain => Some(1),
|
||||
Skill::DrainTick => None,
|
||||
Skill::Siphon => Some(1),
|
||||
Skill::SiphonTick => None,
|
||||
Skill::Curse => Some(1),
|
||||
Skill::Plague => Some(1), // aoe dot
|
||||
Skill::Ruin => Some(2), // aoe
|
||||
@@ -478,95 +478,95 @@ impl Skill {
|
||||
Skill::TestTouch => None,
|
||||
Skill::TestStun => None,
|
||||
Skill::TestBlock => None,
|
||||
Skill::TestDrain => None,
|
||||
Skill::TestSiphon => None,
|
||||
Skill::TestParry => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn category(&self) -> Category {
|
||||
match self {
|
||||
Skill::Attack => Category::Physical,
|
||||
Skill::Attack => Category::Red,
|
||||
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Skill::Block => Category::Physical, // reduce dmg
|
||||
Skill::Parry => Category::Physical, // avoid all dmg
|
||||
Skill::Snare => Category::Physical,
|
||||
Skill::Block => Category::Red, // reduce damage
|
||||
Skill::Parry => Category::Red, // avoid all damage
|
||||
Skill::Snare => Category::Red,
|
||||
|
||||
Skill::Paralyse => Category::Physical,
|
||||
Skill::Strangle => Category::Physical,
|
||||
Skill::Paralyse => Category::Red,
|
||||
Skill::Strangle => Category::Red,
|
||||
|
||||
// Strangle
|
||||
|
||||
Skill::Stun => Category::Physical,
|
||||
Skill::Stun => Category::Red,
|
||||
|
||||
// -----------------
|
||||
// Technology
|
||||
// -----------------
|
||||
Skill::Replicate => Category::Physical,
|
||||
Skill::Swarm => Category::Physical,
|
||||
Skill::Orbit => Category::Physical,
|
||||
Skill::Repair => Category::Physical,
|
||||
Skill::Scan => Category::Physical, // track?
|
||||
Skill::Replicate => Category::Red,
|
||||
Skill::Swarm => Category::Red,
|
||||
Skill::Orbit => Category::Red,
|
||||
Skill::Repair => Category::Red,
|
||||
Skill::Scan => Category::Red, // track?
|
||||
|
||||
// -----------------
|
||||
// Preservation
|
||||
// -----------------
|
||||
Skill::Heal => Category::Physical,
|
||||
Skill::Triage => Category::Spell, // hot
|
||||
Skill::TriageTick => Category::SpellTick, // hot
|
||||
Skill::Throw => Category::Physical, // no dmg stun, adds vulnerable
|
||||
Skill::Charm => Category::Spell,
|
||||
Skill::Calm => Category::Physical,
|
||||
Skill::Rez => Category::Spell,
|
||||
Skill::Heal => Category::Red,
|
||||
Skill::Triage => Category::Blue, // hot
|
||||
Skill::TriageTick => Category::BlueTick, // hot
|
||||
Skill::Throw => Category::Red, // no damage stun, adds vulnerable
|
||||
Skill::Charm => Category::Blue,
|
||||
Skill::Calm => Category::Red,
|
||||
Skill::Rez => Category::Blue,
|
||||
|
||||
// -----------------
|
||||
// Destruction
|
||||
// -----------------
|
||||
Skill::Blast => Category::Spell,
|
||||
Skill::Amplify => Category::Spell,
|
||||
Skill::Decay => Category::Spell, // dot
|
||||
Skill::DecayTick => Category::SpellTick, // hot
|
||||
Skill::Drain => Category::Spell,
|
||||
Skill::DrainTick => Category::SpellTick, // hot
|
||||
Skill::Curse => Category::Spell,
|
||||
Skill::Plague => Category::Spell, // aoe dot
|
||||
Skill::Ruin => Category::Spell, // aoe
|
||||
Skill::Blast => Category::Blue,
|
||||
Skill::Amplify => Category::Blue,
|
||||
Skill::Decay => Category::Blue, // dot
|
||||
Skill::DecayTick => Category::BlueTick, // hot
|
||||
Skill::Siphon => Category::Blue,
|
||||
Skill::SiphonTick => Category::BlueTick, // hot
|
||||
Skill::Curse => Category::Blue,
|
||||
Skill::Plague => Category::Blue, // aoe dot
|
||||
Skill::Ruin => Category::Blue, // aoe
|
||||
|
||||
// -----------------
|
||||
// Purity
|
||||
// -----------------
|
||||
// Skill::Precision => 1,
|
||||
Skill::Empower => Category::Physical,
|
||||
Skill::Slay => Category::Physical,
|
||||
Skill::Shield => Category::Spell,
|
||||
Skill::Silence => Category::Spell,
|
||||
Skill::Inquiry => Category::Spell,
|
||||
Skill::Purify => Category::Spell,
|
||||
Skill::Purge => Category::Spell,
|
||||
Skill::Empower => Category::Red,
|
||||
Skill::Slay => Category::Red,
|
||||
Skill::Shield => Category::Blue,
|
||||
Skill::Silence => Category::Blue,
|
||||
Skill::Inquiry => Category::Blue,
|
||||
Skill::Purify => Category::Blue,
|
||||
Skill::Purge => Category::Blue,
|
||||
|
||||
// -----------------
|
||||
// Chaos
|
||||
// -----------------
|
||||
Skill::Banish => Category::Spell,
|
||||
Skill::Hex => Category::Spell,
|
||||
Skill::Fear => Category::Spell,
|
||||
Skill::Taunt => Category::Spell,
|
||||
Skill::Pause => Category::Spell, // extend durations
|
||||
Skill::Banish => Category::Blue,
|
||||
Skill::Hex => Category::Blue,
|
||||
Skill::Fear => Category::Blue,
|
||||
Skill::Taunt => Category::Blue,
|
||||
Skill::Pause => Category::Blue, // extend durations
|
||||
// Skill::Lag => 2, //
|
||||
Skill::Haste => Category::Spell,
|
||||
Skill::Slow => Category::Spell,
|
||||
Skill::Haste => Category::Blue,
|
||||
Skill::Slow => Category::Blue,
|
||||
|
||||
|
||||
// -----------------
|
||||
// Test
|
||||
// -----------------
|
||||
Skill::TestTouch => Category::Physical,
|
||||
Skill::TestStun => Category::Physical,
|
||||
Skill::TestParry => Category::Physical,
|
||||
Skill::TestBlock => Category::Physical,
|
||||
Skill::TestDrain => Category::Spell,
|
||||
Skill::TestTouch => Category::Red,
|
||||
Skill::TestStun => Category::Red,
|
||||
Skill::TestParry => Category::Red,
|
||||
Skill::TestBlock => Category::Red,
|
||||
Skill::TestSiphon => Category::Blue,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,7 +574,7 @@ impl Skill {
|
||||
match self {
|
||||
Skill::TriageTick => true,
|
||||
Skill::DecayTick => true,
|
||||
Skill::DrainTick => true,
|
||||
Skill::SiphonTick => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -583,10 +583,10 @@ impl Skill {
|
||||
match self {
|
||||
|
||||
// defensive block
|
||||
Skill::Block => 10, // reduce dmg
|
||||
Skill::Parry => 10, // avoid all dmg
|
||||
Skill::Block => 10, // reduce damage
|
||||
Skill::Parry => 10, // avoid all damage
|
||||
Skill::Snare => 10,
|
||||
Skill::Shield => 10, // avoid magic dmg,
|
||||
Skill::Shield => 10, // avoid magic damage,
|
||||
|
||||
// fast phys combat
|
||||
Skill::Attack => 5,
|
||||
@@ -607,14 +607,14 @@ impl Skill {
|
||||
|
||||
// general combat
|
||||
Skill::DecayTick => 2, // hot
|
||||
Skill::Drain => 2,
|
||||
Skill::DrainTick => 2, // hot
|
||||
Skill::Siphon => 2,
|
||||
Skill::SiphonTick => 2, // hot
|
||||
Skill::Hex => 2,
|
||||
Skill::Pause => 2, // extend durations
|
||||
Skill::Plague => 2, // aoe dot
|
||||
Skill::Silence => 2,
|
||||
Skill::Stun => 2,
|
||||
Skill::Throw => 2, // no dmg stun, adds vulnerable
|
||||
Skill::Throw => 2, // no damage stun, adds vulnerable
|
||||
Skill::TriageTick => 2, // hot
|
||||
|
||||
Skill::Heal => 1,
|
||||
@@ -644,7 +644,7 @@ impl Skill {
|
||||
Skill::TestStun => 5,
|
||||
Skill::TestBlock => 10,
|
||||
Skill::TestParry => 10,
|
||||
Skill::TestDrain => 10,
|
||||
Skill::TestSiphon => 10,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +664,7 @@ impl Skill {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
match self.category() == Category::Physical {
|
||||
match self.category() == Category::Red {
|
||||
true => {
|
||||
if let Some(evasion) = target.evade(*self) {
|
||||
resolution.results.push(evasion);
|
||||
@@ -703,7 +703,7 @@ impl Skill {
|
||||
Skill::Heal => heal(source, target, resolution),
|
||||
Skill::Triage => triage(source, target, resolution), // hot
|
||||
Skill::TriageTick => triage_tick(source, target, resolution), // hot
|
||||
Skill::Throw => throw(source, target, resolution), // no dmg stun, adds vulnerable
|
||||
Skill::Throw => throw(source, target, resolution), // no damage stun, adds vulnerable
|
||||
Skill::Charm => panic!("nyi"), // target casts random spell on teammate
|
||||
Skill::Calm => panic!("nyi"), // physical fear, taunt removal
|
||||
Skill::Rez => panic!("nyi"),
|
||||
@@ -712,11 +712,11 @@ impl Skill {
|
||||
// Destruction
|
||||
// -----------------
|
||||
Skill::Blast => blast(source, target, resolution),
|
||||
Skill::Amplify => amplify(source, target, resolution), // increase magic dmg
|
||||
Skill::Amplify => amplify(source, target, resolution), // increase magic damage
|
||||
Skill::Decay => decay(source, target, resolution), // dot
|
||||
Skill::DecayTick => decay_tick(source, target, resolution), // dot
|
||||
Skill::Drain => drain(source, target, resolution),
|
||||
Skill::DrainTick => drain_tick(source, target, resolution), // hot
|
||||
Skill::Siphon => siphon(source, target, resolution),
|
||||
Skill::SiphonTick => siphon_tick(source, target, resolution), // hot
|
||||
Skill::Curse => curse(source, target, resolution),
|
||||
Skill::Plague => panic!("nyi"), // dot that spreads every turn
|
||||
Skill::Ruin => panic!("nyi"), // aoe version of blast
|
||||
@@ -725,9 +725,9 @@ impl Skill {
|
||||
// Purity
|
||||
// -----------------
|
||||
// Skill::Precision => panic!("nyi"),
|
||||
Skill::Empower => empower(source, target, resolution), // increased phys dmg
|
||||
Skill::Slay => panic!("nyi"), // phys dmg mult by target magic dmg
|
||||
Skill::Shield => shield(source, target, resolution), // target is immune to magic dmg and fx
|
||||
Skill::Empower => empower(source, target, resolution), // increased phys damage
|
||||
Skill::Slay => panic!("nyi"), // phys damage mult by target magic damage
|
||||
Skill::Shield => shield(source, target, resolution), // target is immune to magic damage and fx
|
||||
Skill::Silence => silence(source, target, resolution), // target cannot cast spells
|
||||
Skill::Inquiry => panic!("nyi"), //
|
||||
Skill::Purify => purify(source, target, resolution), // dispel all debuffs
|
||||
@@ -751,7 +751,7 @@ impl Skill {
|
||||
Skill::TestStun => stun(source, target, resolution),
|
||||
Skill::TestBlock => block(source, target, resolution),
|
||||
Skill::TestParry => parry(source, target, resolution),
|
||||
Skill::TestDrain => drain(source, target, resolution),
|
||||
Skill::TestSiphon => siphon(source, target, resolution),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,8 +780,8 @@ impl Skill {
|
||||
}
|
||||
|
||||
fn attack(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.phys_dmg();
|
||||
resolution.results.push(target.deal_phys_dmg(Skill::Attack, amount));
|
||||
let amount = cryp.red_damage();
|
||||
resolution.results.push(target.deal_red_damage(Skill::Attack, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@@ -828,7 +828,7 @@ fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> R
|
||||
}
|
||||
|
||||
fn heal(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.heal(Skill::Heal, amount));
|
||||
return resolution;
|
||||
}
|
||||
@@ -858,14 +858,14 @@ fn triage(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
}
|
||||
|
||||
fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg().wrapping_div(2);
|
||||
let amount = cryp.blue_damage().wrapping_div(2);
|
||||
resolution.results.push(target.heal(Skill::TriageTick, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
fn blast(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
resolution.results.push(target.deal_spell_dmg(Skill::Blast, amount));
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.deal_blue_damage(Skill::Blast, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@@ -898,8 +898,8 @@ fn decay(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Reso
|
||||
}
|
||||
|
||||
fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
resolution.results.push(target.deal_spell_dmg(Skill::DecayTick, amount));
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.deal_blue_damage(Skill::DecayTick, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@@ -915,28 +915,28 @@ fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
return resolution;;
|
||||
}
|
||||
|
||||
fn drain(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let drain = CrypEffect {
|
||||
effect: Effect::Drain,
|
||||
duration: Effect::Drain.duration(),
|
||||
tick: Some(Cast::new_tick(cryp, target, Skill::DrainTick)),
|
||||
fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let siphon = CrypEffect {
|
||||
effect: Effect::Siphon,
|
||||
duration: Effect::Siphon.duration(),
|
||||
tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)),
|
||||
};
|
||||
resolution.results.push(target.add_effect(Skill::Drain, drain));
|
||||
resolution.results.push(target.add_effect(Skill::Siphon, siphon));
|
||||
return resolution;;
|
||||
}
|
||||
|
||||
fn drain_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
let drain_dmg = target.deal_spell_dmg(Skill::DrainTick, amount);
|
||||
resolution.results.push(drain_dmg.clone());
|
||||
fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.blue_damage();
|
||||
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
|
||||
resolution.results.push(siphon_damage.clone());
|
||||
|
||||
match drain_dmg {
|
||||
match siphon_damage {
|
||||
ResolutionResult::Damage { amount, mitigation, category: _, immunity } => {
|
||||
if !immunity.immune {
|
||||
resolution.results.push(cryp.heal(Skill::Heal, amount));
|
||||
}
|
||||
},
|
||||
_ => panic!("drain tick dmg not dealt {:?}", drain_dmg),
|
||||
_ => panic!("siphon tick damage not dealt {:?}", siphon_damage),
|
||||
}
|
||||
|
||||
return resolution;
|
||||
@@ -960,7 +960,7 @@ fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
|
||||
if !immune {
|
||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||
if ce.effect.category() == Category::SpellBuff {
|
||||
if ce.effect.category() == Category::BlueBuff {
|
||||
target.effects.remove(i);
|
||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
||||
}
|
||||
@@ -976,7 +976,7 @@ fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Re
|
||||
|
||||
if !immune {
|
||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||
if ce.effect.category() == Category::SpellDebuff {
|
||||
if ce.effect.category() == Category::BlueDebuff {
|
||||
target.effects.remove(i);
|
||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
||||
}
|
||||
@@ -1011,7 +1011,7 @@ mod tests {
|
||||
.learn(Skill::Heal)
|
||||
.create();
|
||||
|
||||
x.deal_phys_dmg(Skill::Attack, 5);
|
||||
x.deal_red_damage(Skill::Attack, 5);
|
||||
|
||||
heal(&mut y, &mut x, Resolution::new(Skill::Heal));
|
||||
}
|
||||
@@ -1051,7 +1051,7 @@ mod tests {
|
||||
.create();
|
||||
|
||||
// ensure it doesn't have 0 pd
|
||||
x.phys_dmg.force(100);
|
||||
x.red_damage.force(100);
|
||||
y.hp.force(500);
|
||||
|
||||
block(&mut y.clone(), &mut y, Resolution::new(Skill::Block));
|
||||
@@ -1078,13 +1078,13 @@ mod tests {
|
||||
.create();
|
||||
|
||||
// ensure it doesn't have 0 sd
|
||||
x.spell_dmg.force(50);
|
||||
x.blue_damage.force(50);
|
||||
|
||||
// remove all mitigation
|
||||
y.armour.force(0);
|
||||
y.spell_shield.force(0);
|
||||
y.red_shield.force(0);
|
||||
y.blue_shield.force(0);
|
||||
|
||||
y.deal_phys_dmg(Skill::Attack, 5);
|
||||
y.deal_red_damage(Skill::Attack, 5);
|
||||
let prev_hp = y.hp();
|
||||
|
||||
let res = Resolution::new(Skill::Triage);
|
||||
@@ -1118,11 +1118,11 @@ mod tests {
|
||||
.level(8)
|
||||
.create();
|
||||
|
||||
x.spell_dmg.force(50);
|
||||
x.blue_damage.force(50);
|
||||
|
||||
amplify(&mut x.clone(), &mut x, Resolution::new(Skill::Amplify));
|
||||
assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
|
||||
assert_eq!(x.spell_dmg(), 100);
|
||||
assert_eq!(x.blue_damage(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+8
-8
@@ -25,30 +25,30 @@ impl Spec {
|
||||
|
||||
pub fn apply(&self, modified: u64, base: u64) -> u64 {
|
||||
match self.spec {
|
||||
SpecType::PhysDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::SpellDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::RedDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::BlueDamage5 => modified + (base * 5 / 100),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq)]
|
||||
pub enum SpecType {
|
||||
PhysDamage5,
|
||||
SpellDamage5,
|
||||
RedDamage5,
|
||||
BlueDamage5,
|
||||
}
|
||||
|
||||
impl SpecType {
|
||||
fn affects(&self) -> Stat {
|
||||
match *self {
|
||||
SpecType::PhysDamage5 => Stat::PhysicalDamage,
|
||||
SpecType::SpellDamage5 => Stat::SpellDamage,
|
||||
SpecType::RedDamage5 => Stat::RedDamage,
|
||||
SpecType::BlueDamage5 => Stat::BlueDamage,
|
||||
}
|
||||
}
|
||||
|
||||
fn level(&self) -> SpecLevel {
|
||||
match *self {
|
||||
SpecType::PhysDamage5 => SpecLevel::Common,
|
||||
SpecType::SpellDamage5 => SpecLevel::Common,
|
||||
SpecType::RedDamage5 => SpecLevel::Common,
|
||||
SpecType::BlueDamage5 => SpecLevel::Common,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,406 @@
|
||||
use std::iter;
|
||||
use uuid::Uuid;
|
||||
|
||||
// drops
|
||||
use rand::prelude::*;
|
||||
use rand::{thread_rng};
|
||||
use rand::distributions::{WeightedIndex};
|
||||
|
||||
use serde_cbor::{from_slice, to_vec};
|
||||
|
||||
use postgres::transaction::Transaction;
|
||||
|
||||
use failure::Error;
|
||||
use failure::err_msg;
|
||||
|
||||
use account::Account;
|
||||
use rpc::{VboxStateParams, VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxDropParams};
|
||||
use skill::{Skill};
|
||||
use cryp::{cryp_get, cryp_write};
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum Var {
|
||||
Blue,
|
||||
Green,
|
||||
Red,
|
||||
|
||||
Attack,
|
||||
Block,
|
||||
Stun,
|
||||
Buff,
|
||||
Debuff,
|
||||
|
||||
Amplify,
|
||||
Banish,
|
||||
Blast,
|
||||
Curse,
|
||||
Empower,
|
||||
Haste,
|
||||
Heal,
|
||||
Hex,
|
||||
Parry,
|
||||
Purge,
|
||||
Purify,
|
||||
Reflect,
|
||||
Ruin,
|
||||
Shield,
|
||||
Silence,
|
||||
Slay,
|
||||
Slow,
|
||||
Snare,
|
||||
Strangle,
|
||||
Strike,
|
||||
Siphon,
|
||||
Survival,
|
||||
Taunt,
|
||||
Throw,
|
||||
Toxic,
|
||||
Triage,
|
||||
}
|
||||
|
||||
impl Var {
|
||||
fn is_base(&self) -> bool {
|
||||
match self {
|
||||
Var::Attack |
|
||||
Var::Block |
|
||||
Var::Stun |
|
||||
Var::Debuff |
|
||||
Var::Buff => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn skill(&self) -> Result<Skill, Error> {
|
||||
match self {
|
||||
Var::Amplify => Ok(Skill::Amplify),
|
||||
Var::Banish => Ok(Skill::Banish),
|
||||
Var::Blast => Ok(Skill::Blast),
|
||||
Var::Curse => Ok(Skill::Curse),
|
||||
Var::Empower => Ok(Skill::Empower),
|
||||
Var::Haste => Ok(Skill::Haste),
|
||||
Var::Heal => Ok(Skill::Heal),
|
||||
Var::Hex => Ok(Skill::Hex),
|
||||
Var::Parry => Ok(Skill::Parry),
|
||||
Var::Purge => Ok(Skill::Purge),
|
||||
Var::Purify => Ok(Skill::Purify),
|
||||
// Var::Reflect => Ok(Skill::Reflect),
|
||||
Var::Ruin => Ok(Skill::Ruin),
|
||||
Var::Shield => Ok(Skill::Shield),
|
||||
Var::Silence => Ok(Skill::Silence),
|
||||
Var::Slay => Ok(Skill::Slay),
|
||||
Var::Slow => Ok(Skill::Slow),
|
||||
Var::Snare => Ok(Skill::Snare),
|
||||
Var::Strangle => Ok(Skill::Strangle),
|
||||
// Var::Strike => Ok(Skill::Strike),
|
||||
// Var::Survival => Ok(Skill::Survival),
|
||||
// Var::Taunt => Ok(Skill::Taunt),
|
||||
Var::Throw => Ok(Skill::Throw),
|
||||
// Var::Toxic => Ok(Skill::Toxic),
|
||||
Var::Triage => Ok(Skill::Triage),
|
||||
_ => Err(err_msg("not a usable var"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
enum ColourCode {
|
||||
RR,
|
||||
GG,
|
||||
BB,
|
||||
RG,
|
||||
BR,
|
||||
GB,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct Vbox {
|
||||
pub id: Uuid,
|
||||
pub balance: u16,
|
||||
pub free: Vec<Var>,
|
||||
pub bound: Vec<Var>,
|
||||
pub game: Uuid,
|
||||
pub account: Uuid,
|
||||
}
|
||||
|
||||
impl Vbox {
|
||||
pub fn new(account_id: Uuid, game_id: Uuid) -> Vbox {
|
||||
Vbox {
|
||||
id: Uuid::new_v4(),
|
||||
account: account_id,
|
||||
game: game_id,
|
||||
free: vec![],
|
||||
bound: vec![],
|
||||
balance: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fill(mut self: Vbox) -> Vbox {
|
||||
let vars = vec![
|
||||
(Var::Red, 1),
|
||||
(Var::Green, 1),
|
||||
(Var::Blue, 1),
|
||||
|
||||
(Var::Attack, 1),
|
||||
(Var::Block, 1),
|
||||
(Var::Buff, 1),
|
||||
(Var::Debuff, 1),
|
||||
(Var::Stun, 1),
|
||||
];
|
||||
|
||||
self.free = iter::
|
||||
repeat_with(|| {
|
||||
let mut rng = thread_rng();
|
||||
let dist = WeightedIndex::new(vars.iter().map(|item| item.1)).unwrap();
|
||||
return vars[dist.sample(&mut rng)].0;
|
||||
})
|
||||
.take(8)
|
||||
.collect::<Vec<Var>>();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn accept(&mut self, i: usize) -> Result<&mut Vbox, Error> {
|
||||
if self.bound.len() >= 9 {
|
||||
return Err(err_msg("too many vars bound"));
|
||||
}
|
||||
|
||||
self.free.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
||||
self.bound.push(self.free.remove(i));
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn drop(&mut self, i: usize) -> Result<&mut Vbox, Error> {
|
||||
self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
||||
self.bound.remove(i);
|
||||
// balance update
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, mut indices: Vec<usize>) -> Result<&mut Vbox, Error> {
|
||||
if indices.len() != 3 {
|
||||
return Err(err_msg("exactly 3 indices required"));
|
||||
}
|
||||
|
||||
if !indices.iter().all(|i| self.bound.get(*i).is_some()) {
|
||||
return Err(err_msg("var missing index"));
|
||||
}
|
||||
|
||||
// have to sort the indices and keep track of the iteration
|
||||
// because when removing the elements the array shifts
|
||||
indices.sort();
|
||||
let mut vars = indices
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, index)| {
|
||||
self.bound.remove(*index - i)
|
||||
})
|
||||
.collect::<Vec<Var>>();
|
||||
|
||||
let base_index = vars
|
||||
.iter()
|
||||
.position(|v| v.is_base())
|
||||
.ok_or(err_msg("no base item selected"))?;
|
||||
|
||||
let base = vars.remove(base_index);
|
||||
|
||||
// fold colours into RGB
|
||||
let colours = vars
|
||||
.iter()
|
||||
.fold([0, 0, 0], |mut acc, c| {
|
||||
match c {
|
||||
Var::Red => acc[0] += 1,
|
||||
Var::Green => acc[1] += 1,
|
||||
Var::Blue => acc[2] += 1,
|
||||
_ => (),
|
||||
};
|
||||
acc
|
||||
});
|
||||
|
||||
let colour_code = match colours {
|
||||
[2,0,0] => ColourCode::RR,
|
||||
[0,2,0] => ColourCode::GG,
|
||||
[0,0,2] => ColourCode::BB,
|
||||
[1,1,0] => ColourCode::RG,
|
||||
[0,1,1] => ColourCode::GB,
|
||||
[1,0,1] => ColourCode::BR,
|
||||
_ => return Err(err_msg("not a combo")),
|
||||
};
|
||||
|
||||
let new = match base {
|
||||
Var::Attack => match colour_code {
|
||||
ColourCode::RR => Var::Strike,
|
||||
ColourCode::GG => Var::Heal,
|
||||
ColourCode::BB => Var::Blast,
|
||||
ColourCode::RG => Var::Slay, //
|
||||
ColourCode::GB => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::BR => Var::Banish, //
|
||||
},
|
||||
Var::Block => match colour_code {
|
||||
ColourCode::RR => Var::Parry,
|
||||
ColourCode::GG => Var::Reflect,
|
||||
ColourCode::BB => Var::Toxic,
|
||||
ColourCode::RG => Var::Taunt,
|
||||
ColourCode::GB => Var::Shield,
|
||||
ColourCode::BR => return Err(err_msg("unhandled skill combo")),
|
||||
},
|
||||
Var::Buff => match colour_code {
|
||||
ColourCode::RR => Var::Empower,
|
||||
ColourCode::GG => Var::Triage,
|
||||
ColourCode::BB => Var::Amplify,
|
||||
ColourCode::RG => Var::Survival,
|
||||
ColourCode::GB => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::BR => Var::Haste,
|
||||
},
|
||||
Var::Debuff => match colour_code {
|
||||
ColourCode::RR => Var::Snare,
|
||||
ColourCode::GG => Var::Purge,
|
||||
ColourCode::BB => Var::Curse,
|
||||
ColourCode::RG => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::GB => Var::Siphon,
|
||||
ColourCode::BR => Var::Slow,
|
||||
},
|
||||
Var::Stun => match colour_code {
|
||||
ColourCode::RR => Var::Strangle,
|
||||
ColourCode::GG => Var::Throw,
|
||||
ColourCode::BB => Var::Ruin,
|
||||
ColourCode::RG => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::GB => Var::Silence,
|
||||
ColourCode::BR => Var::Hex,
|
||||
},
|
||||
_ => panic!("wrong base {:?}", base),
|
||||
};
|
||||
|
||||
self.bound.push(new);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vbox_create(vbox: Vbox, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let vbox_bytes = to_vec(&vbox)?;
|
||||
|
||||
let query = "
|
||||
INSERT INTO vbox (id, account, game, data)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&vbox.id, &account.id, &vbox.game, &vbox_bytes])?;
|
||||
|
||||
result.iter().next().ok_or(format_err!("no vbox written"))?;
|
||||
|
||||
// println!("{:} wrote vbox", vbox.id);
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
pub fn vbox_write(vbox: Vbox, tx: &mut Transaction) -> Result<Vbox, Error> {
|
||||
let vbox_bytes = to_vec(&vbox)?;
|
||||
|
||||
let query = "
|
||||
UPDATE vbox
|
||||
SET data = $1
|
||||
WHERE id = $2
|
||||
RETURNING id, account, data;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&vbox_bytes, &vbox.id])?;
|
||||
|
||||
result.iter().next().ok_or(err_msg("no vbox row returned"))?;
|
||||
|
||||
// println!("{:?} wrote vbox", vbox.id);
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
|
||||
pub fn vbox_get(tx: &mut Transaction, game_id: Uuid, account: &Account) -> Result<Vbox, Error> {
|
||||
let query = "
|
||||
SELECT *
|
||||
FROM vbox
|
||||
WHERE account = $1
|
||||
AND game = $2;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&account.id, &game_id])?;
|
||||
|
||||
let returned = match result.iter().next() {
|
||||
Some(row) => row,
|
||||
None => return Err(err_msg("vbox not found")),
|
||||
};
|
||||
|
||||
// tells from_slice to cast into a cryp
|
||||
let vbox_bytes: Vec<u8> = returned.get("data");
|
||||
let vbox = from_slice::<Vbox>(&vbox_bytes)?;
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
pub fn vbox_state(params: VboxStateParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
match vbox_get(tx, params.game_id, account) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
vbox_create(Vbox::new(account.id, params.game_id).fill(), tx, account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vbox_discard(params: VboxDiscardParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let vbox = vbox_get(tx, params.game_id, account)?;
|
||||
return vbox_write(vbox.fill(), tx);
|
||||
}
|
||||
|
||||
pub fn vbox_accept(params: VboxAcceptParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.accept(params.index)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.combine(params.indices)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_drop(params: VboxDropParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.drop(params.index)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
let mut cryp = cryp_get(tx, params.cryp_id, account.id)?;
|
||||
|
||||
let var = vbox.bound.remove(params.index);
|
||||
|
||||
// done here because i teach them a tonne of skills for tests
|
||||
let max_skills = 4;
|
||||
if cryp.skills.len() >= max_skills {
|
||||
return Err(format_err!("cryp at max skills ({:?})", max_skills));
|
||||
}
|
||||
|
||||
let skill = var.skill()?;
|
||||
cryp = cryp.learn(skill);
|
||||
cryp_write(cryp, tx)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn combine_test() {
|
||||
let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4());
|
||||
vbox.bound = vec![Var::Attack, Var::Green, Var::Green];
|
||||
vbox.combine(vec![1,2,0]).unwrap();
|
||||
assert_eq!(vbox.bound[0], Var::Heal);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user