Merge branch 'release/1.11.0'
This commit is contained in:
commit
9cf81735f1
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,3 +1,15 @@
|
|||||||
|
## [1.10.1] - 2019-12-04
|
||||||
|
### Changed
|
||||||
|
- Reduced the number of items to create + and ++ versions from 3 to 2 (need 4 items total to make a ++)
|
||||||
|
- Reduced the power of ++ skills to be closer to the power of previous + versions
|
||||||
|
- Tweaked all values of power specs to reduce their power bonuses
|
||||||
|
|
||||||
|
## [1.10.0] - 2019-11-29
|
||||||
|
### Changed
|
||||||
|
- Reworked the vbox layout
|
||||||
|
- Floating combat text and faster animations
|
||||||
|
- Mobile UI fixes
|
||||||
|
|
||||||
## [1.9.1] - 2019-11-21
|
## [1.9.1] - 2019-11-21
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed Item+ Purchasing Bug
|
- Fixed Item+ Purchasing Bug
|
||||||
|
|||||||
266
COMBOS.md
266
COMBOS.md
@ -1,142 +1,200 @@
|
|||||||
# item_info ->
|
# Spec / Skill hybrid specs #
|
||||||
|
|
||||||
combos [strike, [R R Attack]]
|
Create skills specs by combining an upgraded skills with corresponding colour specs:
|
||||||
specs [spec [bonus amount, [r g b]]
|
Strike (RR + A) can be combined with (PowerRR, SpeedRR, LifeRR)
|
||||||
|
- Strike + PowerRR -> StrikePower
|
||||||
|
- Strike + SpeedRR -> StrikeSpeed
|
||||||
|
- Strike + LifeRR -> StrikeLife
|
||||||
|
|
||||||
# Playthrough
|
Could also create SkillSpec+ by combining two together.
|
||||||
|
|
||||||
constructs join game
|
## Why Skill Specs
|
||||||
stats randomised
|
|
||||||
|
|
||||||
initial stash drops
|
- Give tools to players to make cool unique builds
|
||||||
6 skills
|
- Passive utility that you work towards
|
||||||
6 colours
|
- Specialise in a type of skill
|
||||||
6 specs
|
- Repurpose skills that you aren't using much for active use
|
||||||
|
- More layers of complexity
|
||||||
|
|
||||||
play first round
|
## Skill specs philosphy
|
||||||
basically duke it out
|
|
||||||
|
|
||||||
# Colours #
|
- Should be more interesting than just another stat "multiplier" we have that already (could be placeholder though)
|
||||||
|
- Passives should help build a theme / identity to the skills
|
||||||
|
- Specs should be numerically scalable so they can be `balanced` (also for upgraded versions think continuous vs discrete)
|
||||||
|
- While specialised should be useful for multiple skills
|
||||||
|
e.g. StrikeSpeed -> Causes your red attack skills to cast on another target on the same team for (X% damage)
|
||||||
|
A StrikeSpeed should do something for `some` other active skill that isn't strike
|
||||||
|
- They don't have to be `competely game changing` to be viable / fun / interesting
|
||||||
|
|
||||||
### Red ###
|
## Brainstorming on what kind of things skill specs could do
|
||||||
Real world concepts
|
|
||||||
Aggressive
|
|
||||||
Apply Buffs
|
|
||||||
Fast & Chaotic
|
|
||||||
|
|
||||||
### Green ###
|
- Passive
|
||||||
Healing Specialisation
|
- (Abosrb Spec) when you take damage you permanently gain X Power/Speed/Life
|
||||||
Defensive
|
- Grant you Amplify with (X% multiplier) when you KO a target
|
||||||
Purge buffs & debuffs
|
- Convert (X% of your red / blue power -> green power)
|
||||||
|
- Reduce / Increase damage taken of a certain type (Block type upgrades maybe?)
|
||||||
|
|
||||||
### Blue ###
|
- Active
|
||||||
Fantasy concepts (magical)
|
- Make a skill cast another skill (strike another guy)
|
||||||
Aggressive & Defensive
|
- Apply an effect when you cast a skill
|
||||||
Apply Debuffs
|
- Change damage / healing / speed of a skill
|
||||||
Slow & Reliable
|
|
||||||
|
|
||||||
# Classes #
|
## The BIG LIST
|
||||||
|
|
||||||
Class names to be changed
|
### Attack Base
|
||||||
====================
|
Strike
|
||||||
Pure Red `Nature`
|
Power
|
||||||
Pure Green `Non-Violence`
|
Life
|
||||||
Pure Blue `Destruction`
|
Speed (Repeat skill at X% multiplier)
|
||||||
Hybrid Red / Blue `Chaos`
|
|
||||||
Hybrid Red / Green `Purity`
|
|
||||||
Hybrid Blue / Green `Technology`
|
|
||||||
|
|
||||||
|
Chaos
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
Skills
|
Heal
|
||||||
==========
|
Power (Convert X% Red/Blue Power to GreenPower)
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
Basic Type
|
Blast
|
||||||
-------------------------------------------------------------------------
|
Power
|
||||||
Attack `Basic offensive skill - deal damage`
|
Life
|
||||||
Buff `Base ally targetted skill - increase ally speed`
|
Speed
|
||||||
Stun `Base enemy disable - disable enemy for 2 rounds`
|
|
||||||
Block `Base self targetted defensive - reduced damage taken for 2 rounds`
|
|
||||||
Debuff `Base enemy debuff - reduce enemy speed`
|
|
||||||
|
|
||||||
# Attack Base #
|
Slay
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
RR - Strike
|
Siphon
|
||||||
GG - Heal
|
Power
|
||||||
BB - Blast
|
Life
|
||||||
RG - Purify
|
Speed
|
||||||
GB - Decay
|
|
||||||
RB - Blast
|
|
||||||
|
|
||||||
# Stun Base #
|
### Stun Base
|
||||||
|
Bash
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
RR - Strangle
|
Sleep
|
||||||
GG - Break
|
Power
|
||||||
BB - Ruin
|
Life
|
||||||
RG - Banish
|
Speed
|
||||||
GB - Silence
|
|
||||||
RB - Hex
|
|
||||||
|
|
||||||
# Buff Base #
|
Ruin
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
RR - Empower
|
Link
|
||||||
GR - Triage
|
Power
|
||||||
BB - Absorb
|
Life
|
||||||
RG - Sustain
|
Speed
|
||||||
GB - Amplify
|
|
||||||
RB - Haste
|
|
||||||
|
|
||||||
# Debuff Base #
|
Banish
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
RR - Restrict
|
Break
|
||||||
GG - Purge
|
Power
|
||||||
BB - Curse
|
Life
|
||||||
RG - Slow
|
Speed
|
||||||
GB - Siphon
|
|
||||||
RB - Invert
|
|
||||||
|
|
||||||
# Block Base #
|
### Block Base
|
||||||
|
|
||||||
RR - Counter
|
Counter
|
||||||
GG - Reflect
|
Power
|
||||||
BB - Electrify
|
Life
|
||||||
RG - Intercept
|
Speed
|
||||||
GB - Life `rename?`
|
|
||||||
RB - Recharge
|
|
||||||
|
|
||||||
|
Reflect
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
## Advanced combos ##
|
Purify
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
Two ways of upgrading
|
Sustain
|
||||||
#1 -> combine more of the same for a stronger version of the same skill / spec (T2 / T3 Combos)
|
Power
|
||||||
#2 -> combine skill with two matching colour specs to change the way the skill works (Spec / Skill hybrid)
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
### T2 / T3 Combos ###
|
Electrify
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
All current specs / items can be further combo'd into T2 and T3 versions
|
Recharge
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
# 3 of same base => 1 upgraded tier #
|
### Buff Base
|
||||||
`3 x T1 Red Damage Spec => T2 Red Damage Spec`
|
|
||||||
`3 x T2 Red Damage Spec => T3 Red Damage Spec`
|
|
||||||
`3 x T1 Strike => T2 Strike`
|
|
||||||
`3 x T2 Strike => T3 Strike`
|
|
||||||
|
|
||||||
Upgraded skills will have a combination of higher damage / longer duration / reduced cooldown
|
Intercept
|
||||||
Upgraded skills use the same speed formula as previously
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
### Spec / Skill hybrid specs ###
|
Triage
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
# Strike #
|
Absorb
|
||||||
2 x Red Damage + Strike => Strike damage bonus (crit?)
|
Power (Gain X Power when you take damage)
|
||||||
2 x Red Speed + Strike => Strike reduces enemy speed
|
Life (Gain X Life when you take damage)
|
||||||
2 x Red Life + Strike => Strike reduces enemy healing (% reduction)
|
Speed (Gain X Speed when you take damage)
|
||||||
|
|
||||||
# Heal #
|
Amplify
|
||||||
2 x Green Damage + Heal => Heal target for additional 20% of caster's maximum life
|
Power
|
||||||
2 x Green Speed + Heal => Heal target gets bonus speed
|
Life
|
||||||
2 x Green Life + Heal => Heal increases target's max hp for 2 turns
|
Speed
|
||||||
|
|
||||||
etc etc
|
Haste
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
30 skills * 3 specs => 90 spec / skill hybrid specs -> might be overcomplicated
|
Hybrid
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
### Debuff Base
|
||||||
|
|
||||||
|
Purge
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
Invert
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
Restrict
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
Silence
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
Curse
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
|
|
||||||
|
Decay
|
||||||
|
Power
|
||||||
|
Life
|
||||||
|
Speed
|
||||||
75
ECONOMY.md
75
ECONOMY.md
@ -1,75 +0,0 @@
|
|||||||
# Everything costs money (gold?)
|
|
||||||
|
|
||||||
Items - Base colours / skills / specs and associated upgrades
|
|
||||||
|
|
||||||
### Sources of money
|
|
||||||
- Start with money and gain income after each battle
|
|
||||||
- Higher income from winning
|
|
||||||
|
|
||||||
- Selling items in inventory or equipped on character refunds
|
|
||||||
- Selling from inventory full refund
|
|
||||||
- Selling from charcter 50% refund
|
|
||||||
|
|
||||||
### Uses for money
|
|
||||||
|
|
||||||
- Buying items
|
|
||||||
- Rerolling vbox
|
|
||||||
|
|
||||||
### Base Costs
|
|
||||||
|
|
||||||
Base colours have a base 1 cost
|
|
||||||
Base skills have a base 2 cost
|
|
||||||
Base specs have a base 3 cost
|
|
||||||
|
|
||||||
### Actual Costs
|
|
||||||
|
|
||||||
- Costs increase as more of an item is used on constructs in the game
|
|
||||||
- The cost increases by the base cost for every 6 allocations of base item
|
|
||||||
- Allocation is based on all constructs in the game
|
|
||||||
|
|
||||||
### Example ###
|
|
||||||
|
|
||||||
Round #1
|
|
||||||
|
|
||||||
All costs are base costs
|
|
||||||
# Player #1 and Player #2 (They both bought the same things)
|
|
||||||
Construct #1 Strike (Attack + RR), (2 + 1 + 1) = (4) cost
|
|
||||||
Construct #1 Empower (Buff + RR), (2 + 1 + 1) = (4) cost
|
|
||||||
Construct #3 Attack, 2 cost
|
|
||||||
|
|
||||||
Total cost - 10
|
|
||||||
|
|
||||||
Round #2
|
|
||||||
|
|
||||||
Items used on constructs include:
|
|
||||||
|
|
||||||
Red x 8
|
|
||||||
Attack x 4
|
|
||||||
Buff x 2
|
|
||||||
|
|
||||||
The costs of red for round #2 are now (1 + 1) = 2
|
|
||||||
|
|
||||||
If they were to buy the same skill setup it would be as follows:
|
|
||||||
|
|
||||||
# Player #1 and Player #2 (They both bought the same things)
|
|
||||||
Construct #1 Strike (Attack + RR), (2 + 2 + 2) = (6) cost
|
|
||||||
Construct #1 Empower (Buff + RR), (2 + 2 + 2) = (6) cost
|
|
||||||
Construct #3 Attack, 2 cost
|
|
||||||
|
|
||||||
Total cost - 14
|
|
||||||
|
|
||||||
### Philosophy of increasing item costs
|
|
||||||
|
|
||||||
- Two games will never feel exactly the same
|
|
||||||
- Costs change over rounds to diversify skill choice and gameplay
|
|
||||||
- As optimal builds emerge the paths to reach them will change every game
|
|
||||||
- Rewarded for going (hipster) builds nobody else is trying
|
|
||||||
- Some reward for hoarding items in your inventory while they cheaper (hodl red)
|
|
||||||
|
|
||||||
### Income values
|
|
||||||
|
|
||||||
Could try with 9 base income
|
|
||||||
Income increases by 3 each round and winning bonus of 6
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
49
NODES.md
49
NODES.md
@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
# Stat Multipliers #
|
|
||||||
|
|
||||||
### Defenses ###
|
|
||||||
|
|
||||||
Rare `Increased GreenLife`
|
|
||||||
|
|
||||||
Common `Increased Evasion rating`
|
|
||||||
Common `Increased Blue Life rating`
|
|
||||||
Common `Increased RedLife rating`
|
|
||||||
Common `Increased Healing done`
|
|
||||||
Common `Increased Healing received`
|
|
||||||
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 red_life`
|
|
||||||
Uncommon `Increased % mitigation from spell shield`
|
|
||||||
Uncommon `Increased damage over time`
|
|
||||||
|
|
||||||
Rare `gain empower on KO`
|
|
||||||
Rare `cannot be restrictd`
|
|
||||||
Rare `cannot be silenced`
|
|
||||||
Rare `cannot be intercepted`
|
|
||||||
|
|
||||||
Rare `25% stun for attack`
|
|
||||||
Rare `25% hex for blast`
|
|
||||||
|
|
||||||
Rare `cooldown reduction`
|
|
||||||
Rare `effect duration`
|
|
||||||
|
|
||||||
Rare `increased phys damage, 0 spell damage`
|
|
||||||
Rare `increased spell damage, 0 phys damage`
|
|
||||||
|
|
||||||
Rare `increased phys damage, silenced`
|
|
||||||
Rare `increased spell damage, restrictd`
|
|
||||||
|
|
||||||
Rare `increased speed, increased durations`
|
|
||||||
Rare `increased speed, increased cooldowns`
|
|
||||||
|
|
||||||
# Nature - Technology - Nonviolence - Destruction - Purity - Chaos #
|
|
||||||
|
|
||||||
- Increased power
|
|
||||||
- Increased speed
|
|
||||||
- Increased stat
|
|
||||||
- ??? Related Notables
|
|
||||||
|
|
||||||
# ??? Constructs need to have a minimum of X of the construct stat to learn a skill #
|
|
||||||
@ -34,8 +34,12 @@ Player Events e.g. chatwheel
|
|||||||
Matchmaking + ELO / Leaderboard
|
Matchmaking + ELO / Leaderboard
|
||||||
Game skill private fields
|
Game skill private fields
|
||||||
|
|
||||||
|
# Phase 4 (Release -> Full Shill mode)
|
||||||
|
|
||||||
Refine artwork, icons, scaling etc
|
Refine artwork, icons, scaling etc
|
||||||
Music
|
Music
|
||||||
|
Skill Specs
|
||||||
|
Some sort viewable combat log
|
||||||
|
|
||||||
Marketing materials
|
Marketing materials
|
||||||
Videos
|
Videos
|
||||||
|
|||||||
224
SPECS.md
224
SPECS.md
@ -1,224 +0,0 @@
|
|||||||
### Specs ###
|
|
||||||
|
|
||||||
Numbers are placeholder
|
|
||||||
`Specs get a bonus dependent on the total of Red / Green / Blue in player skills & specs`
|
|
||||||
|
|
||||||
# Example to meet 5 red gem bonus from skills only
|
|
||||||
In your player Construct #1 has `Strike`, Construct #2 has `Slay` and `Heal`, Construct #3 has `Restrict`
|
|
||||||
- RR skill `Strike` contributes 2 red gems to the total red gems (2 total)
|
|
||||||
- RG skill `Slay` contributes 1 red gem to the total red gems (3 total)
|
|
||||||
- GG skill `Heal` contirubtes 0 red gems to the total red gems (3 total)
|
|
||||||
- RR skill `Restrict` contirubtes 2 red gems to the total red gems (5 total)
|
|
||||||
|
|
||||||
# Advanced specs also require a minimum number of Red / Green / Blue gems on the construct to take effect
|
|
||||||
- Tier 1 Basic specs (Damage / Health / Defense) will have no requirements
|
|
||||||
- Advanced specs will require a certain threshold of red / green / blue gems to be enabled
|
|
||||||
- Provided spec requirements are met, all specs will add gems to the construct
|
|
||||||
|
|
||||||
# Starting from scratch with a vbox
|
|
||||||
|
|
||||||
### Round 1
|
|
||||||
|
|
||||||
- Buy 4 reds (items)
|
|
||||||
- Buy two 'Attack' Skills & 1 Stun skill (items)
|
|
||||||
- Buy 1 Basic Damage Spec (item)
|
|
||||||
|
|
||||||
Combine 2 Red + 'Attack' -> Strike
|
|
||||||
Combine 2 Red + 'Basic Damage Spec' -> Red Damage
|
|
||||||
|
|
||||||
Construct #1 -> Give Strike & Red Damage Spec -> Strike + 1 x Red Damage Spec
|
|
||||||
Construct #2 -> Give Attack -> Attack
|
|
||||||
Construct #3 -> Give Stun -> Stun
|
|
||||||
|
|
||||||
Player Total (4 Red + 2 Basic gems)
|
|
||||||
|
|
||||||
### Round 2
|
|
||||||
|
|
||||||
- Buy 2 reds & 2 green & 2 blue (all available colour items)
|
|
||||||
- Buy 2 Basic Damage Spec (item)
|
|
||||||
|
|
||||||
- Construct #2 Unequip Attack
|
|
||||||
- Combine 2 Green + 'Attack' -> Heal
|
|
||||||
|
|
||||||
- Construct #3 Unequip Stun
|
|
||||||
- Combine 2 Blue + 'Stun' -> Ruin
|
|
||||||
|
|
||||||
- Combine 2 Red + 'Basic Damage Spec' -> Red Damage
|
|
||||||
|
|
||||||
Construct #1 -> Give Red Damage items -> Strike + 2 x Red Damage Spec (6R)
|
|
||||||
Construct #2 -> Give Heal item -> Heal (2G)
|
|
||||||
Construct #3 -> Give Ruin item -> Ruin (2B)
|
|
||||||
|
|
||||||
## Round 3
|
|
||||||
|
|
||||||
- Buy 4 reds
|
|
||||||
- Buy 1 Attack, 1 Stun, 1 Block (item)
|
|
||||||
- Buy 2 Basic Damage Spec (item)
|
|
||||||
|
|
||||||
- Combine 2 Red + 'Stun' -> Strangle
|
|
||||||
- Combine 2 Red + 'Block' -> Counter
|
|
||||||
|
|
||||||
Construct #1 -> Give 'Stun' & 'Strangle' -> Strike, Stun, Strangle + 2 x Red Damage Spec (10R)
|
|
||||||
Construct #2 -> 'No change' -> Heal (2G)
|
|
||||||
Construct #3 -> Give Attack item & 2 Basic Damage Spec -> Attack + Ruin + 2 x Basic Damage Spec (2B)
|
|
||||||
|
|
||||||
## Round 4
|
|
||||||
|
|
||||||
- Buy 4 reds (getting lucky with reds!)
|
|
||||||
- Buy 1 Attack, 1 Buff
|
|
||||||
|
|
||||||
- Combine 2 Red + 'Attack' -> Strike
|
|
||||||
- Combine 2 Red + 'Buff' -> Empower
|
|
||||||
|
|
||||||
- Construct #1 Unequip 2 x Red Damage spec, Equip Empower -> Strike, Stun, Strangle, Empower (8R)
|
|
||||||
- Combine 'Strike' + 2 x Red Damage spec -> 'Increased Strike Damage spec'
|
|
||||||
|
|
||||||
### Note 'Increased Strike Damage spec' requires 8R on the construct
|
|
||||||
|
|
||||||
Construct #1 Equip Increased Strike Damage spec -> Strike, Stun, Strangle, Empower + Increased Strike Damage Spec (14R)
|
|
||||||
Construct #2 -> 'No change' -> Heal
|
|
||||||
Construct #3 -> 'No change' -> Attack + Ruin + 2 x Basic Damage Spec
|
|
||||||
|
|
||||||
## Round 5
|
|
||||||
|
|
||||||
We already lost cause we went all in on 1 red construct like a noob
|
|
||||||
|
|
||||||
### Generic Specs
|
|
||||||
|
|
||||||
# Basic % GreenLife
|
|
||||||
`Base` -> 5% inc hp
|
|
||||||
`Player Bonus` -> 3 basic gems -> +5% // 6 basic gems -> +10% // 12 basic gems -> +15%
|
|
||||||
Maximum 35% inc hp
|
|
||||||
|
|
||||||
# Basic Speed
|
|
||||||
`Base` -> 5% inc speed
|
|
||||||
`Player Bonus` -> 3 basic gems -> +10% // 6 basic gems -> +15% // 12 basic gems -> +20%
|
|
||||||
Maximum 50% inc speed
|
|
||||||
|
|
||||||
# Basic Class Spec
|
|
||||||
`Base` -> +2 red, +2 green +2 blue gems on construct
|
|
||||||
# Basic Duration
|
|
||||||
|
|
||||||
### Increased Damage Combos ###
|
|
||||||
|
|
||||||
Generate by combining `Generic Spec (Basic Damage)` with respective RGB
|
|
||||||
|
|
||||||
# Red Damage (Dmg + RR)
|
|
||||||
Add 2 `red gems`
|
|
||||||
`Base` -> 10% inc red dmg
|
|
||||||
`Player Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +25%
|
|
||||||
Maximum +60% red damage
|
|
||||||
|
|
||||||
# Blue Damage (Dmg + BB) #
|
|
||||||
Add 2 `blue gems`
|
|
||||||
`Base` -> 10% inc blue dmg
|
|
||||||
`Player Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +25%
|
|
||||||
Maximum +60% blue damage
|
|
||||||
|
|
||||||
# Healing (Dmg + GG) #
|
|
||||||
Add 2 `green gems`
|
|
||||||
`Base` -> 10% inc healing
|
|
||||||
`Player Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +25%
|
|
||||||
Maximum +60% inc healing
|
|
||||||
|
|
||||||
# Red damage and healing (Dmg + RG)
|
|
||||||
Add 1 red 1 green gem
|
|
||||||
`Base` -> 5% inc red damage and 5% inc healing
|
|
||||||
`Player Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
|
||||||
Maximum +35% inc red damage and 35% inc healing
|
|
||||||
|
|
||||||
# Red and blue damage (Dmg + RB)
|
|
||||||
Add 1 red and 1 blue gem
|
|
||||||
`Base` -> 5% inc red damage and 5% inc healing
|
|
||||||
`Player Bonus` (2 red + 2 green gems) -> +5% + 5% // (5 red + 5 green gems) -> +10% + 10% % // 20 green gems -> +15% + 15%
|
|
||||||
Maximum +35% inc damage and 35% inc healing
|
|
||||||
|
|
||||||
# Blue damage and healing (Dmg + BG)
|
|
||||||
Add 1 blue and 1 green gem
|
|
||||||
`Base` -> 5% inc blue damage and 5% inc healing
|
|
||||||
`Player Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
|
||||||
Maximum +35% inc blue damage and 35% inc healing
|
|
||||||
|
|
||||||
### Increased GreenLife Combos ###
|
|
||||||
|
|
||||||
Generate by combining `Generic Spec (Basic GreenLife)` with respective RGB
|
|
||||||
|
|
||||||
# Increased % Red Life (Basic %HP + 2R)
|
|
||||||
Add 2 `red gems`
|
|
||||||
`Base` -> 10% inc red shield
|
|
||||||
`Player Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +20%
|
|
||||||
Maximum +55% inc red shield
|
|
||||||
|
|
||||||
# Increased % Red Life and GreenLife (Basic %HP + 1R1G)
|
|
||||||
Add 1 red 1 green gem
|
|
||||||
`Base` -> 5% inc red shield and 5% inc hp
|
|
||||||
`Player Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
|
||||||
Maximum +35% inc red shield and 35% inc hp
|
|
||||||
|
|
||||||
# Increased % Blue Life (Basic %HP + 2B)
|
|
||||||
Add 2 `blue gems`
|
|
||||||
`Base` -> 10% inc red shield
|
|
||||||
`Player Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +20%
|
|
||||||
Maximum +55% inc blue shield
|
|
||||||
|
|
||||||
# Increased % Blue Life and GreenLife (Basic %HP + 1B1G)
|
|
||||||
Add `1 blue and 1 green gems`
|
|
||||||
`Base` -> 5% inc red shield and 5% inc hp
|
|
||||||
`Player Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
|
||||||
Maximum +35% inc blue shield and 35% inc hp
|
|
||||||
|
|
||||||
# Increased % GreenLife (Basic %HP + 2G)
|
|
||||||
Add `2 green gems`
|
|
||||||
`Base` -> 10% inc hp
|
|
||||||
`Player Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +20%
|
|
||||||
Maximum +55% inc hp
|
|
||||||
|
|
||||||
# Increased % Blue and Red Life (Basic %HP + 1B1R)
|
|
||||||
Add `1 blue and 1 red gem`
|
|
||||||
`Base` -> 5% inc red shield and 5% inc hp
|
|
||||||
`Player Bonus` (2B + 2R gems) -> +5% + 5% // (5B + 5R gems) -> +10% + 10% % // (10B + 10R) gems -> +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)
|
|
||||||
Construct Requires `8 red gems`
|
|
||||||
Adds `6 red gems`
|
|
||||||
`Base` -> 15% increased strike damage
|
|
||||||
`Player Bonus` 15 red gems -> +15% // 20 red gems -> +20% // 30 red gems -> +30%
|
|
||||||
Maximum 80% increased strike damage
|
|
||||||
|
|
||||||
# Improved Heal (Combine Heal + Healing Spec x 2)
|
|
||||||
Construct Requires `8 green gems`
|
|
||||||
`Base` -> 15% increased heal healing
|
|
||||||
`Player Bonus` 15 green gems -> +15% // 20 green gems -> +20% // 30 green gems -> +30%
|
|
||||||
Maximum 80% increased heal healing
|
|
||||||
|
|
||||||
# Increased Blast Damage (Combine Blast + Blue Spec x 2)
|
|
||||||
Construct Requires `8 blue gems`
|
|
||||||
`Base` -> 15% increased blast damage
|
|
||||||
`Player Bonus` 15 blue gems -> +15% // 20 blue gems -> +20% // 30 blue gems -> +30%
|
|
||||||
Maximum 80% increased blast damage
|
|
||||||
|
|
||||||
# Increased Slay Damage (Combine Slay + Red Damage Spec + Healing Spec)
|
|
||||||
Construct Requires `4 red 4 green gems`
|
|
||||||
`Base` -> 15% increased slay damage
|
|
||||||
`Player Bonus` (8R + 8G) gems -> +15% // (10R + 10G) gems -> +20% // (15R + 15G) gems -> +30%
|
|
||||||
Maximum 80% increased slay damage
|
|
||||||
|
|
||||||
# Increased Banish Damage (Combine Slay + Red Damage Spec + Blue Damage Spec)
|
|
||||||
Construct Requires `4 red 4 blue gems`
|
|
||||||
`Base` -> 15% increased slay damage
|
|
||||||
`Player Bonus` (8R + 8B) gems -> +15% // (10R + 10B) gems -> +20% // (15R + 15B) gems -> +30%
|
|
||||||
Maximum 80% increased banish damage
|
|
||||||
|
|
||||||
## Other Combos
|
|
||||||
|
|
||||||
# Increased % Red Speed (Basic Speed + 2R)
|
|
||||||
Add 2 red gems
|
|
||||||
`Base` -> 15% inc red speed
|
|
||||||
`Player Bonus` 5 red gems -> +15% // 10 red gems -> +20% // 20 red gems -> +25%
|
|
||||||
Maximum 80% inc red speed
|
|
||||||
|
|
||||||
# Nature Affinity (Basic Class spec + 2R)
|
|
||||||
`Base` -> Add 10 red gems
|
|
||||||
36
WORKLOG.md
36
WORKLOG.md
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
_ntr_
|
_ntr_
|
||||||
* can't reset password without knowing password =\
|
* can't reset password without knowing password =\
|
||||||
* skip faceoff on server side
|
|
||||||
* change cooldowns to delay & recharge
|
* change cooldowns to delay & recharge
|
||||||
- delay is cooldown before skill can first be used
|
- delay is cooldown before skill can first be used
|
||||||
- recharge is cooldown after using skill
|
- recharge is cooldown after using skill
|
||||||
@ -30,14 +29,11 @@ Hexagon Set
|
|||||||
- Increase intensity for each visit
|
- Increase intensity for each visit
|
||||||
|
|
||||||
_mashy_
|
_mashy_
|
||||||
* floating combat text combat (start opposite hp and float towards it) to speed up animations
|
* rebalance
|
||||||
|
* speed specs
|
||||||
|
* life specs
|
||||||
|
|
||||||
* represent construct colours during game phase (try %bar or dots)
|
* represent construct colours during game phase (try %bar or dots)
|
||||||
* buy from preview if you have the required bases in vbox / inventory
|
|
||||||
- a "buy" becomes available under the current info / preview section
|
|
||||||
- clicking the buy automatically purchases / combine items
|
|
||||||
- could also be used to upgrade already equipped skills / specs
|
|
||||||
- e.g. an equipped white power spec could be upgraded by clicking under preview
|
|
||||||
- if this was added we could reduce inventory size to 3 and rearrange vbox (see mockup img)
|
|
||||||
|
|
||||||
_external_
|
_external_
|
||||||
* Graphics
|
* Graphics
|
||||||
@ -57,29 +53,19 @@ _tba_
|
|||||||
|
|
||||||
## SOON
|
## SOON
|
||||||
|
|
||||||
* combo rework
|
* Skill / Spec hybrids - SEE COMBOS.md
|
||||||
- reduce number of items for creating t2/t3 items from 3 -> 2
|
|
||||||
- add lost complexity by adding skill spec items
|
|
||||||
- Created by combining a skill with corresponding spec
|
|
||||||
e.g.
|
|
||||||
- Strike + PowerRR -> StrikePower (Will be the power symbol with strike text under)
|
|
||||||
- Construct does Y% more damage with Strike
|
|
||||||
- Strike + SpeedRR -> StrikeSpeed (strike has Y% more speed)
|
|
||||||
- Strike + LifeRR -> StrikeLife (Strike recharges X% of damage as red life)
|
|
||||||
|
|
||||||
- Can also work as module style passive keystones
|
|
||||||
* troll life -> dmg -> Invert life spec?
|
|
||||||
* prince of peace
|
|
||||||
* bonus healing / no damage -> Heal power spec?
|
|
||||||
* fuck magic -> Some sort of reflect spec?
|
|
||||||
* empower on ko -> Amplify + Power spec
|
|
||||||
|
|
||||||
* elo + leaderboards
|
* elo + leaderboards
|
||||||
|
|
||||||
## LATER
|
## LATER
|
||||||
|
|
||||||
* Graphical status effects instead of text
|
* Graphical status effects instead of text
|
||||||
|
|
||||||
|
* buy from preview if you have the required bases in vbox / inventory
|
||||||
|
- a "buy" becomes available under the current info / preview section
|
||||||
|
- clicking the buy automatically purchases / combine items
|
||||||
|
- could also be used to upgrade already equipped skills / specs
|
||||||
|
- e.g. an equipped white power spec could be upgraded by clicking under preview
|
||||||
|
|
||||||
* theme toasts
|
* theme toasts
|
||||||
|
|
||||||
* rework vecs into sets
|
* rework vecs into sets
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.10.0",
|
"version": "1.11.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ echo "Setting version to $VERSION"
|
|||||||
|
|
||||||
echo $VERSION | tr -d '\n' > VERSION
|
echo $VERSION | tr -d '\n' > VERSION
|
||||||
cd $MNML_PATH/server && sed -i "/^version/c\version = \"$VERSION\"" Cargo.toml
|
cd $MNML_PATH/server && sed -i "/^version/c\version = \"$VERSION\"" Cargo.toml
|
||||||
|
cd $MNML_PATH/core && sed -i "/^version/c\version = \"$VERSION\"" Cargo.toml
|
||||||
cd $MNML_PATH/ops && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/ops && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
cd $MNML_PATH/client && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/client && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
cd $MNML_PATH/acp && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
cd $MNML_PATH/acp && npm --allow-same-version --no-git-tag-version version "$VERSION"
|
||||||
|
|||||||
2684
client/assets/mnml.awards.svg
Normal file
2684
client/assets/mnml.awards.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 106 KiB |
2568
client/assets/mnml.logo.text.svg
Normal file
2568
client/assets/mnml.logo.text.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 95 KiB |
@ -3,16 +3,25 @@
|
|||||||
|
|
||||||
div {
|
div {
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
|
// display: flex;
|
||||||
|
// flex-flow: column;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
// text-transform: uppercase;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 2.5em;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 3em;
|
height: 2.5em;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
@white: #f5f5f5; // whitesmoke
|
@white: #f5f5f5; // whitesmoke
|
||||||
@purple: #9355b5; // 6lack - that far cover
|
@purple: #9355b5; // 6lack - that far cover
|
||||||
@yellow: #ffa100;
|
@yellow: #ffa100;
|
||||||
@silver: #c0c0c0;
|
@silver: #2c2c2c;
|
||||||
|
|
||||||
@black: black;
|
@black: black;
|
||||||
@gray: #222;
|
@gray: #222;
|
||||||
|
|||||||
@ -54,11 +54,7 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
&.highlight {
|
&.highlight {
|
||||||
color: black;
|
|
||||||
background: @silver;
|
background: @silver;
|
||||||
// border: 1px solid @white; (this bangs around the vbox)
|
|
||||||
|
|
||||||
// overwrite the classes on white svg elements
|
|
||||||
svg {
|
svg {
|
||||||
stroke-width: 0.75em;
|
stroke-width: 0.75em;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,25 +75,11 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
border: 0.1em solid #222;
|
border: 0.1em solid #222;
|
||||||
&:not(:last-child) {
|
|
||||||
border-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
|
|
||||||
.terms {
|
|
||||||
display: inline;
|
|
||||||
margin: 0 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
@ -108,62 +94,14 @@ section {
|
|||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
|
||||||
letter-spacing: 0.25em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
display: grid;
|
|
||||||
// grid-template-columns: repeat(4, 1fr);
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
grid-gap: 1em;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
align-items: flex-end;
|
|
||||||
button {
|
|
||||||
border-radius: 0.25em;
|
|
||||||
// height: 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.sub {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.play {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
&.rejoin {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.ready:enabled {
|
|
||||||
color: forestgreen;
|
|
||||||
border-color: forestgreen;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: forestgreen;
|
|
||||||
color: black;
|
|
||||||
border-color: forestgreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // all green
|
|
||||||
// button.ready:enabled {
|
|
||||||
// background: forestgreen;
|
|
||||||
// color: black;
|
|
||||||
// border-color: forestgreen;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// color: forestgreen;
|
|
||||||
// border-color: forestgreen;
|
|
||||||
// background: 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.panes {
|
.panes {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
letter-spacing: 0.25em;
|
letter-spacing: 0.25em;
|
||||||
@ -172,61 +110,92 @@ section {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
letter-spacing: 0.25em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
display: grid;
|
||||||
|
// grid-template-columns: repeat(4, 1fr);
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-gap: 1em;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
&.sub {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.play {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
&.rejoin {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.ready:enabled {
|
||||||
|
color: forestgreen;
|
||||||
|
border-color: forestgreen;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: forestgreen;
|
||||||
|
color: black;
|
||||||
|
border-color: forestgreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // all green
|
||||||
|
// button.ready:enabled {
|
||||||
|
// background: forestgreen;
|
||||||
|
// color: black;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
|
||||||
|
// &:hover {
|
||||||
|
// color: forestgreen;
|
||||||
|
// border-color: forestgreen;
|
||||||
|
// background: 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo {
|
|
||||||
margin-top: 1em;
|
|
||||||
|
|
||||||
display: block;
|
.login {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
|
||||||
|
.terms {
|
||||||
|
display: inline;
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
pointer-events: none;
|
padding: 0 0.5em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
grid-area: hdr;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
flex: 0 1 10%;
|
||||||
|
margin-right: 1em;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
button {
|
||||||
margin-bottom: 0.5em;
|
flex: 1;
|
||||||
|
border-top: 0;
|
||||||
div:first-child {
|
border: 0.1em solid #222;
|
||||||
padding-right: 1em;
|
&:last-child {
|
||||||
}
|
float: right;
|
||||||
}
|
|
||||||
|
|
||||||
.construct-section {
|
|
||||||
.construct-list {
|
|
||||||
height: 25em;
|
|
||||||
grid-area: unset;
|
|
||||||
|
|
||||||
.instance-construct {
|
|
||||||
// border: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.colour-info {
|
|
||||||
grid-area: vinfo;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
div {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
flex: 1;
|
|
||||||
height: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.game-demo {
|
|
||||||
.game {
|
|
||||||
height: 25em;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
|
|
||||||
.game-construct {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|||||||
@ -27,23 +27,6 @@ html body {
|
|||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mnml {
|
|
||||||
/* this is the sweet nectar to keep it full page*/
|
|
||||||
height: 100vh;
|
|
||||||
max-height: 100vh;
|
|
||||||
min-height: 100vh;
|
|
||||||
|
|
||||||
/* stops inspector going skitz*/
|
|
||||||
overflow-x: hidden;
|
|
||||||
// overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @media (min-width: 1921px) {
|
|
||||||
// html, body, #mnml {
|
|
||||||
// font-size: 16pt;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -108,11 +91,37 @@ dl {
|
|||||||
|
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
|
||||||
|
/* this is the sweet nectar to keep it full page*/
|
||||||
|
height: 100vh;
|
||||||
|
max-height: 100vh;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
|
/* stops inspector going skitz*/
|
||||||
|
overflow-x: hidden;
|
||||||
|
// overflow-y: hidden;
|
||||||
|
|
||||||
|
|
||||||
&.animations-test {
|
&.animations-test {
|
||||||
aside button {
|
aside button {
|
||||||
font-size: 50%;
|
font-size: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.front-page {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 0 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
margin: 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
@ -129,7 +138,7 @@ button, input {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: 0.5em;
|
border-radius: 0;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
padding-right: 0.1em;
|
padding-right: 0.1em;
|
||||||
padding-left: 0.1em;
|
padding-left: 0.1em;
|
||||||
@ -150,9 +159,12 @@ button, input {
|
|||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
/*colour necesary to bash skellington*/
|
/*colour necesary to bash skellington*/
|
||||||
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// &:active {
|
||||||
|
// filter: url("#noiseFilter");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@ -261,28 +273,12 @@ figure.gray {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
|
||||||
.options {
|
|
||||||
font-size: 200%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 2em;
|
|
||||||
// border-radius: 0.1em;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
.options {
|
||||||
button {
|
button {
|
||||||
&.highlight {
|
&.highlight {
|
||||||
color: @white;
|
color: @white;
|
||||||
box-shadow: inset 0px 5px 0px 0px @white;
|
box-shadow: inset 0px 5px 0px 0px @white;
|
||||||
border: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
border: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,11 +296,20 @@ li {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
height: 2em;
|
height: 4em;
|
||||||
background-image: url("../../assets/mnml.logo.trim.svg");
|
filter: url("#noiseFilter");
|
||||||
|
background-image: url("../../assets/mnml.logo.text.svg");
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: left;
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.awards {
|
||||||
|
height: 100%;
|
||||||
|
background-image: url("../../assets/mnml.awards.svg");
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.discord-btn {
|
.discord-btn {
|
||||||
@ -316,8 +321,13 @@ li {
|
|||||||
|
|
||||||
.mnni {
|
.mnni {
|
||||||
background-image: url("./../mnni.svg");
|
background-image: url("./../mnni.svg");
|
||||||
|
filter: url("#noiseFilter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .highlight {
|
||||||
|
// filter: url("#noiseFilter");
|
||||||
|
// }
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
grid-area: avatar;
|
grid-area: avatar;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
@ -328,6 +338,10 @@ li {
|
|||||||
// pointer-events: none;
|
// pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
// font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
#clipboard {
|
#clipboard {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
@ -359,4 +373,8 @@ li {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#noise {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@import 'styles.mobile.less';
|
@import 'styles.mobile.less';
|
||||||
|
|||||||
@ -7,6 +7,12 @@
|
|||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
|
&.front-page {
|
||||||
|
main {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.instance {
|
.instance {
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"vbox vbox"
|
"vbox vbox"
|
||||||
@ -164,12 +170,21 @@
|
|||||||
|
|
||||||
|
|
||||||
// portrait menu or small size vertical in landscape
|
// portrait menu or small size vertical in landscape
|
||||||
@media (max-width: 550px) and (max-height: 800px) {
|
@media (max-width: 550px) and (max-height: 800px) and (orientation: portrait) {
|
||||||
#mnml {
|
#mnml {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"main"
|
"main";
|
||||||
|
|
||||||
|
&.front-page {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
@ -264,6 +279,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-combiner {
|
.info-combiner {
|
||||||
|
max-height: 7em;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,16 +147,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.highlight {
|
&.highlight {
|
||||||
color: black;
|
|
||||||
background: @silver;
|
background: @silver;
|
||||||
// overwrite the classes on white svg elements
|
// overwrite the classes on white svg elements
|
||||||
svg {
|
svg {
|
||||||
stroke-width: 0.75em;
|
stroke-width: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.white {
|
|
||||||
stroke: black;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>@font-face {
|
||||||
<html><head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>@font-face {
|
|
||||||
font-family: octicons-anchor;
|
font-family: octicons-anchor;
|
||||||
src: url(https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.woff) format('woff');
|
src: url(https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.woff) format('woff');
|
||||||
}
|
}
|
||||||
@ -733,6 +731,24 @@ pre {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style><title>CHANGELOG</title></head><body><article class="markdown-body"><h2>
|
</style><title>CHANGELOG</title></head><body><article class="markdown-body"><h2>
|
||||||
|
<a id="user-content-1101---2019-12-04" class="anchor" href="#1101---2019-12-04" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.10.1] - 2019-12-04</h2>
|
||||||
|
<h3>
|
||||||
|
<a id="user-content-changed" class="anchor" href="#changed" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Reduced the number of items to create + and ++ versions from 3 to 2 (need 4 items total to make a ++)</li>
|
||||||
|
<li>Reduced the power of ++ skills to be closer to the power of previous + versions</li>
|
||||||
|
<li>Tweaked all values of power specs to reduce their power bonuses</li>
|
||||||
|
</ul>
|
||||||
|
<h2>
|
||||||
|
<a id="user-content-1100---2019-11-29" class="anchor" href="#1100---2019-11-29" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.10.0] - 2019-11-29</h2>
|
||||||
|
<h3>
|
||||||
|
<a id="user-content-changed-1" class="anchor" href="#changed-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Reworked the vbox layout</li>
|
||||||
|
<li>Floating combat text and faster animations</li>
|
||||||
|
<li>Mobile UI fixes</li>
|
||||||
|
</ul>
|
||||||
|
<h2>
|
||||||
<a id="user-content-191---2019-11-21" class="anchor" href="#191---2019-11-21" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.9.1] - 2019-11-21</h2>
|
<a id="user-content-191---2019-11-21" class="anchor" href="#191---2019-11-21" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.9.1] - 2019-11-21</h2>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-fixed" class="anchor" href="#fixed" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Fixed</h3>
|
<a id="user-content-fixed" class="anchor" href="#fixed" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Fixed</h3>
|
||||||
@ -742,7 +758,7 @@ pre {
|
|||||||
<h2>
|
<h2>
|
||||||
<a id="user-content-190---2019-11-21" class="anchor" href="#190---2019-11-21" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.9.0] - 2019-11-21</h2>
|
<a id="user-content-190---2019-11-21" class="anchor" href="#190---2019-11-21" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.9.0] - 2019-11-21</h2>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed" class="anchor" href="#changed" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-2" class="anchor" href="#changed-2" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>VBOX
|
<li>VBOX
|
||||||
<ul>
|
<ul>
|
||||||
@ -794,7 +810,7 @@ pre {
|
|||||||
<li>Resizing of vbox when you buy / create certain items</li>
|
<li>Resizing of vbox when you buy / create certain items</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-1" class="anchor" href="#changed-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-3" class="anchor" href="#changed-3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Automatically shows a preview of combo item when you have 3 items selected for combining</li>
|
<li>Automatically shows a preview of combo item when you have 3 items selected for combining</li>
|
||||||
<li>Only highlight the first available item slot when equipping</li>
|
<li>Only highlight the first available item slot when equipping</li>
|
||||||
@ -826,7 +842,7 @@ pre {
|
|||||||
<li>An issue where skills would not be put on cooldown after being used.</li>
|
<li>An issue where skills would not be put on cooldown after being used.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-2" class="anchor" href="#changed-2" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-4" class="anchor" href="#changed-4" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Game phase</p>
|
<p>Game phase</p>
|
||||||
@ -893,7 +909,7 @@ pre {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-3" class="anchor" href="#changed-3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-5" class="anchor" href="#changed-5" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Construct life changed</p>
|
<p>Construct life changed</p>
|
||||||
@ -979,7 +995,7 @@ pre {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-4" class="anchor" href="#changed-4" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-6" class="anchor" href="#changed-6" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Vbox phase</p>
|
<p>Vbox phase</p>
|
||||||
@ -1125,7 +1141,7 @@ pre {
|
|||||||
<li>Player width styling</li>
|
<li>Player width styling</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-5" class="anchor" href="#changed-5" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-7" class="anchor" href="#changed-7" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Improved wiggle animation</li>
|
<li>Improved wiggle animation</li>
|
||||||
<li>Intercept is now considered defensive by bots</li>
|
<li>Intercept is now considered defensive by bots</li>
|
||||||
@ -1134,7 +1150,7 @@ pre {
|
|||||||
<h2>
|
<h2>
|
||||||
<a id="user-content-164---2019-10-24" class="anchor" href="#164---2019-10-24" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.6.4] - 2019-10-24</h2>
|
<a id="user-content-164---2019-10-24" class="anchor" href="#164---2019-10-24" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.6.4] - 2019-10-24</h2>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-6" class="anchor" href="#changed-6" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-8" class="anchor" href="#changed-8" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Animations processing on client side reduced.</li>
|
<li>Animations processing on client side reduced.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -1176,7 +1192,7 @@ pre {
|
|||||||
<li>Subscriber chat!</li>
|
<li>Subscriber chat!</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-7" class="anchor" href="#changed-7" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-9" class="anchor" href="#changed-9" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Made available skill / effect information during the combat phase.</p>
|
<p>Made available skill / effect information during the combat phase.</p>
|
||||||
@ -1208,7 +1224,7 @@ pre {
|
|||||||
<a id="user-content-156---2019-10-17" class="anchor" href="#156---2019-10-17" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.5.6] - 2019-10-17</h2>
|
<a id="user-content-156---2019-10-17" class="anchor" href="#156---2019-10-17" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.5.6] - 2019-10-17</h2>
|
||||||
<p>We've updated the UI during the vbox / buy phase to give a better indication of valid actions.</p>
|
<p>We've updated the UI during the vbox / buy phase to give a better indication of valid actions.</p>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-8" class="anchor" href="#changed-8" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-10" class="anchor" href="#changed-10" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Borders for skill combo's represent the base colours.</p>
|
<p>Borders for skill combo's represent the base colours.</p>
|
||||||
@ -1234,7 +1250,7 @@ pre {
|
|||||||
<h2>
|
<h2>
|
||||||
<a id="user-content-155---2019-10-15" class="anchor" href="#155---2019-10-15" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.5.5] - 2019-10-15</h2>
|
<a id="user-content-155---2019-10-15" class="anchor" href="#155---2019-10-15" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>[1.5.5] - 2019-10-15</h2>
|
||||||
<h3>
|
<h3>
|
||||||
<a id="user-content-changed-9" class="anchor" href="#changed-9" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
<a id="user-content-changed-11" class="anchor" href="#changed-11" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Changed</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<p>Purge</p>
|
<p>Purge</p>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "1.10.0",
|
"version": "1.11.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
export const setAccount = value => ({ type: 'SET_ACCOUNT', value });
|
export const setAccount = value => ({ type: 'SET_ACCOUNT', value });
|
||||||
|
export const setAuthenticated = value => ({ type: 'SET_AUTHENTICATED', value });
|
||||||
|
|
||||||
export const setAnimating = value => ({ type: 'SET_ANIMATING', value });
|
export const setAnimating = value => ({ type: 'SET_ANIMATING', value });
|
||||||
export const setAnimCb = value => ({ type: 'SET_ANIM_CB', value });
|
|
||||||
export const setAnimFocus = value => ({ type: 'SET_ANIM_FOCUS', value });
|
export const setAnimFocus = value => ({ type: 'SET_ANIM_FOCUS', value });
|
||||||
export const setAnimSkill = value => ({ type: 'SET_ANIM_SKILL', value });
|
export const setAnimSkill = value => ({ type: 'SET_ANIM_SKILL', value });
|
||||||
export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value });
|
export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value });
|
||||||
export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value });
|
export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value });
|
||||||
export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value });
|
export const setResolution = value => ({ type: 'SET_RESOLUTION', value });
|
||||||
|
|
||||||
export const setDemo = value => ({ type: 'SET_DEMO', value });
|
|
||||||
|
|
||||||
export const setChatShow = value => ({ type: 'SET_CHAT_SHOW', value });
|
export const setChatShow = value => ({ type: 'SET_CHAT_SHOW', value });
|
||||||
export const setChatWheel = value => ({ type: 'SET_CHAT_WHEEL', value });
|
export const setChatWheel = value => ({ type: 'SET_CHAT_WHEEL', value });
|
||||||
|
|||||||
@ -4,9 +4,7 @@ const toast = require('izitoast');
|
|||||||
const eachSeries = require('async/eachSeries');
|
const eachSeries = require('async/eachSeries');
|
||||||
|
|
||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { setAnimations, clearAnimations } = require('./animations.utils');
|
||||||
const animations = require('./animations.utils');
|
|
||||||
const { removeTier } = require('./utils');
|
|
||||||
|
|
||||||
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws';
|
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws';
|
||||||
|
|
||||||
@ -20,73 +18,32 @@ function createSocket(store) {
|
|||||||
ws.send(cbor.encode(msg));
|
ws.send(cbor.encode(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendDevResolve(a, b, skill) {
|
function sendDevResolve(skill) {
|
||||||
send(['DevResolve', { a, b, skill }]);
|
send(['DevResolve', { skill }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDevResolutions(newRes) {
|
function setGame(game) {
|
||||||
const { game, account, animating } = store.getState();
|
store.dispatch(actions.setGame(game));
|
||||||
|
|
||||||
if (animating) return false;
|
|
||||||
store.dispatch(actions.setAnimating(true));
|
store.dispatch(actions.setAnimating(true));
|
||||||
|
store.dispatch(actions.setGameSkillInfo(null));
|
||||||
// stop fetching the game state til animations are done
|
// stop fetching the game state til animations are done
|
||||||
|
const newRes = game.resolutions[game.resolutions.length - 1];
|
||||||
return eachSeries(newRes, (r, cb) => {
|
return eachSeries(newRes, (r, cb) => {
|
||||||
if (!r.event) return cb();
|
// if (r.delay === 0) return cb(); // TargetKo etc
|
||||||
const timeout = animations.getTime(r.stages);
|
setAnimations(r, store);
|
||||||
const anims = animations.getObjects(r, game, account);
|
return setTimeout(cb, r.delay);
|
||||||
const text = animations.getText(r);
|
|
||||||
store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r, game)));
|
|
||||||
if (anims.animSkill) store.dispatch(actions.setAnimSkill(anims.animSkill));
|
|
||||||
|
|
||||||
if (r.stages.includes('START_SKILL') && anims.animSource) {
|
|
||||||
store.dispatch(actions.setAnimSource(anims.animSource));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.stages.includes('END_SKILL') && anims.animTarget) {
|
|
||||||
store.dispatch(actions.setAnimTarget(anims.animTarget));
|
|
||||||
if (animations.isCbAnim(anims.animSkill)) store.dispatch(actions.setAnimCb(cb));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.stages.includes('POST_SKILL') && text) {
|
|
||||||
// timeout to prevent text classes from being added too soon
|
|
||||||
if (timeout === TIMES.POST_SKILL_DURATION_MS) {
|
|
||||||
store.dispatch(actions.setAnimText(text));
|
|
||||||
} else {
|
|
||||||
setTimeout(
|
|
||||||
() => store.dispatch(actions.setAnimText(text)),
|
|
||||||
timeout - TIMES.POST_SKILL_DURATION_MS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return setTimeout(() => {
|
|
||||||
store.dispatch(actions.setAnimSkill(null));
|
|
||||||
store.dispatch(actions.setAnimSource(null));
|
|
||||||
store.dispatch(actions.setAnimTarget(null));
|
|
||||||
store.dispatch(actions.setAnimText(null));
|
|
||||||
store.dispatch(actions.setAnimFocus([]));
|
|
||||||
if (r.stages.includes('END_SKILL') && animations.isCbAnim(anims.animSkill)) return true;
|
|
||||||
return cb();
|
|
||||||
}, timeout);
|
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
// clear animation state
|
clearAnimations(store);
|
||||||
store.dispatch(actions.setAnimSkill(null));
|
|
||||||
store.dispatch(actions.setAnimSource(null));
|
|
||||||
store.dispatch(actions.setAnimTarget(null));
|
|
||||||
store.dispatch(actions.setAnimText(null));
|
|
||||||
store.dispatch(actions.setAnimating(false));
|
|
||||||
store.dispatch(actions.setGameEffectInfo(null));
|
|
||||||
|
|
||||||
// set the game state so resolutions don't fire twice
|
// set the game state so resolutions don't fire twice
|
||||||
store.dispatch(actions.setGame(game));
|
store.dispatch(actions.setGame(game));
|
||||||
|
// ws.sendGameState(game.id);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
DevResolutions: onDevResolutions,
|
GameState: setGame,
|
||||||
};
|
};
|
||||||
|
|
||||||
// decodes the cbor and
|
// decodes the cbor and
|
||||||
|
|||||||
@ -5,18 +5,7 @@ const { createStore, combineReducers } = require('redux');
|
|||||||
const reducers = require('./reducers');
|
const reducers = require('./reducers');
|
||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const createSocket = require('./animations.socket');
|
const createSocket = require('./animations.socket');
|
||||||
|
|
||||||
// const TrippyTriangle = require('./components/svgs/trippy.triangle');
|
|
||||||
// const Amplify = require('./components/svgs/amplify');
|
|
||||||
// const Hex = require('./components/svgs/hex');
|
|
||||||
const Game = require('./components/game');
|
const Game = require('./components/game');
|
||||||
const testGameBuilder = require('./test.game');
|
|
||||||
|
|
||||||
const testGame = testGameBuilder('8552e0bf-340d-4fc8-b6fc-cccccccccccc');
|
|
||||||
const testAccount = {
|
|
||||||
id: '8552e0bf-340d-4fc8-b6fc-cccccccccccc',
|
|
||||||
name: 'ntr',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Redux Store
|
// Redux Store
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
@ -24,20 +13,15 @@ const store = createStore(
|
|||||||
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
|
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const testAccount = {
|
||||||
|
id: '8552e0bf-340d-4fc8-b6fc-cccccccccccc',
|
||||||
|
name: 'ntr',
|
||||||
|
};
|
||||||
store.dispatch(actions.setAccount(testAccount));
|
store.dispatch(actions.setAccount(testAccount));
|
||||||
store.dispatch(actions.setGame(testGame));
|
|
||||||
|
|
||||||
function animationsNav(ws) {
|
function animationsNav(ws) {
|
||||||
function useSkill(skill) {
|
function useSkill(skill) {
|
||||||
const ateam = Math.round(Math.random());
|
return ws.sendDevResolve(skill);
|
||||||
const bteam = Math.round(Math.random());
|
|
||||||
const acon = Math.floor(Math.random() * 3);
|
|
||||||
const bcon = Math.floor(Math.random() * 3);
|
|
||||||
|
|
||||||
const a = testGame.players[ateam].constructs[acon].id;
|
|
||||||
const b = testGame.players[bteam].constructs[bcon].id;
|
|
||||||
|
|
||||||
return ws.sendDevResolve(a, b, skill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SKILLS.map((s, i) => (
|
return SKILLS.map((s, i) => (
|
||||||
|
|||||||
@ -1,207 +1,49 @@
|
|||||||
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { TIMES } = require('./constants');
|
||||||
const { removeTier } = require('./utils');
|
|
||||||
|
|
||||||
function none() {
|
function setAnimations(r, store) {
|
||||||
return {
|
const { focus, event: [type, variant] } = r;
|
||||||
animSource: null,
|
|
||||||
animTarget: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getObjects(resolution, game, account) {
|
if (type === 'HitAoe') {
|
||||||
if (!resolution) return none();
|
const { construct } = variant;
|
||||||
if (!resolution.target) return none();
|
const aoeFocus = focus.concat(construct);
|
||||||
|
|
||||||
const [type, event] = resolution.event;
|
store.dispatch(actions.setResolution(null));
|
||||||
if (!event || !event.skill) return none();
|
store.dispatch(actions.setAnimFocus(aoeFocus));
|
||||||
|
store.dispatch(actions.setAnimTarget(r));
|
||||||
|
|
||||||
const playerTeam = game.players.find(t => t.id === account.id);
|
return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS);
|
||||||
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
|
||||||
const otherTeam = game.players.find(t => t.id !== account.id);
|
|
||||||
const otherTeamIds = otherTeam.constructs.map(c => c.id);
|
|
||||||
const sourceIsPlayer = playerTeamIds.includes(resolution.source.id);
|
|
||||||
const targetIsPlayer = playerTeamIds.includes(resolution.target.id);
|
|
||||||
|
|
||||||
const targetting = () => {
|
|
||||||
if (type === 'AoeSkill') {
|
|
||||||
if (targetIsPlayer) return playerTeamIds;
|
|
||||||
return otherTeamIds;
|
|
||||||
}
|
|
||||||
return [resolution.target.id];
|
|
||||||
};
|
|
||||||
|
|
||||||
const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
|
|
||||||
let y = 0;
|
|
||||||
if (!sameTeam) y = targetIsPlayer ? 1 : -1;
|
|
||||||
|
|
||||||
const i = sourceIsPlayer
|
|
||||||
? playerTeamIds.findIndex(c => c === resolution.source.id)
|
|
||||||
: otherTeamIds.findIndex(c => c === resolution.source.id);
|
|
||||||
|
|
||||||
const j = targetIsPlayer
|
|
||||||
? playerTeamIds.findIndex(c => c === resolution.target.id)
|
|
||||||
: otherTeamIds.findIndex(c => c === resolution.target.id);
|
|
||||||
const x = j - i;
|
|
||||||
const direction = { x, y };
|
|
||||||
// const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;
|
|
||||||
|
|
||||||
const createSourceAnim = () => {
|
|
||||||
return {
|
|
||||||
animation: 'sourceCast',
|
|
||||||
constructId: resolution.source.id,
|
|
||||||
direction,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const skipSource = !resolution.stages.includes('START_SKILL')
|
|
||||||
|| resolution.source.id === resolution.target.id;
|
|
||||||
|
|
||||||
const animSource = skipSource
|
|
||||||
? null
|
|
||||||
: createSourceAnim();
|
|
||||||
|
|
||||||
const animTarget = {
|
|
||||||
skill: event.skill,
|
|
||||||
constructId: targetting(),
|
|
||||||
player: playerTeamIds.includes(resolution.target.id),
|
|
||||||
direction,
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
animSource,
|
|
||||||
animTarget,
|
|
||||||
animSkill: event.skill,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTime(stages) {
|
|
||||||
let time = 0;
|
|
||||||
if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
|
|
||||||
time += TIMES.SOURCE_AND_TARGET_TOTAL_DURATION;
|
|
||||||
} else {
|
|
||||||
if (stages.includes('START_SKILL')) time += TIMES.SOURCE_DURATION_MS;
|
|
||||||
if (stages.includes('END_SKILL')) time += TIMES.TARGET_DURATION_MS;
|
|
||||||
}
|
|
||||||
if (stages.includes('POST_SKILL')) time += TIMES.POST_SKILL_DURATION_MS;
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFocusTargets(resolution, game) {
|
|
||||||
if (!resolution) return [];
|
|
||||||
if (!resolution.event) return [];
|
|
||||||
const [type] = resolution.event;
|
|
||||||
const source = resolution.source.id;
|
|
||||||
const target = resolution.target.id;
|
|
||||||
|
|
||||||
if (type === 'AoeSkill') {
|
|
||||||
const targetTeam = game.players.find(t => t.constructs.find(c => c.id === target));
|
|
||||||
const targetTeamIds = targetTeam.constructs.map(c => c.id);
|
|
||||||
if (source !== target) targetTeamIds.push(source);
|
|
||||||
return targetTeamIds;
|
|
||||||
}
|
|
||||||
if (source !== target) return [source, target];
|
|
||||||
return [target];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getText(resolution) {
|
|
||||||
const nullText = { text: null, constructId: null, life: null };
|
|
||||||
if (!resolution) return nullText;
|
|
||||||
if (!resolution.stages.includes('POST_SKILL')) return nullText;
|
|
||||||
|
|
||||||
function generatePostSkill() {
|
|
||||||
const [type, event] = resolution.event;
|
|
||||||
if (type === 'Ko') {
|
|
||||||
return { text: 'KO!', css: 'ko-transition' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Disable') {
|
|
||||||
const { disable } = event;
|
|
||||||
return { text: `${disable}`, css: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Immunity') {
|
|
||||||
return { text: 'IMMUNE', css: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Damage') {
|
|
||||||
const { mitigation, colour } = event;
|
|
||||||
let { amount } = event;
|
|
||||||
let css = '';
|
|
||||||
if (colour === 'Green') {
|
|
||||||
css = 'green';
|
|
||||||
amount *= -1;
|
|
||||||
}
|
|
||||||
if (colour === 'Red') css = 'red';
|
|
||||||
if (colour === 'Blue') css = 'blue';
|
|
||||||
|
|
||||||
const mitigationText = mitigation
|
|
||||||
? `(${mitigation})`
|
|
||||||
: '';
|
|
||||||
return { text: `${amount} ${mitigationText}`, css };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Healing') {
|
|
||||||
const { amount, overhealing } = event;
|
|
||||||
return { text: `${amount} (${overhealing} OH)`, css: 'green' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Inversion') {
|
|
||||||
return { text: 'INVERT', css: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Reflection') {
|
|
||||||
return { text: 'REFLECT', css: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Effect') {
|
|
||||||
const { effect, duration, construct_effects: effects } = event;
|
|
||||||
return { text: `+ ${effect} ${duration}T`, css: '', effects };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Recharge') {
|
|
||||||
const { red, blue } = event;
|
|
||||||
if (red > 0 && blue > 0) return { text: `+${red}R +${blue}B`, css: 'rb' };
|
|
||||||
if (red > 0) return { text: `+${red}R`, css: 'red' };
|
|
||||||
if (blue > 0) return { text: `+${blue}B`, css: 'blue' };
|
|
||||||
return nullText;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Removal') {
|
|
||||||
const { effect, construct_effects: effects } = event;
|
|
||||||
if (!effect) {
|
|
||||||
return { text: 'Effect Removal', css: '', effects };
|
|
||||||
}
|
|
||||||
return { text: `-${effect}`, css: '', effects };
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { green, red, blue } = resolution.target;
|
store.dispatch(actions.setAnimFocus(focus));
|
||||||
const { text, css, effects } = generatePostSkill();
|
|
||||||
const skill = resolution.event[1] ? resolution.event[1].skill : null;
|
if (type === 'Cast') {
|
||||||
return {
|
store.dispatch(actions.setResolution(null));
|
||||||
css,
|
store.dispatch(actions.setAnimSource(r));
|
||||||
text,
|
return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS);
|
||||||
effects,
|
}
|
||||||
life: { green, red, blue },
|
|
||||||
constructId: resolution.target.id,
|
if (type === 'Hit') {
|
||||||
skill,
|
store.dispatch(actions.setResolution(null));
|
||||||
};
|
store.dispatch(actions.setAnimTarget(r));
|
||||||
|
return setTimeout(() => store.dispatch(actions.setAnimTarget(null)), TIMES.TARGET_DURATION_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.dispatch(actions.setResolution(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCbAnim(skill) {
|
function clearAnimations(store) {
|
||||||
return ['Attack', 'Blast', 'Siphon', 'SiphonTick', 'Strike', 'Chaos', 'Slay', 'Heal',
|
store.dispatch(actions.setAnimSkill(null));
|
||||||
'Buff', 'Amplify', 'Haste', 'Triage', 'TriageTick', 'Link', 'Hybrid', 'Intercept',
|
store.dispatch(actions.setAnimSource(null));
|
||||||
'Debuff', 'Curse', 'Decay', 'DecayTick', 'Purge', 'Silence', 'Restrict',
|
store.dispatch(actions.setAnimTarget(null));
|
||||||
'Stun', 'Bash', 'Absorb', 'Sleep', 'Break', 'Ruin',
|
store.dispatch(actions.setResolution(null));
|
||||||
'Block', 'Sustain', 'Electrify', 'Electrocute', 'ElectrocuteTick',
|
store.dispatch(actions.setAnimating(false));
|
||||||
'Counter', 'CounterAttack', 'Purify', 'Recharge', 'Reflect'].includes(removeTier(skill));
|
store.dispatch(actions.setGameEffectInfo(null));
|
||||||
|
store.dispatch(actions.setAnimFocus(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getFocusTargets,
|
setAnimations,
|
||||||
getObjects,
|
clearAnimations,
|
||||||
getTime,
|
|
||||||
getText,
|
|
||||||
isCbAnim,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -33,6 +33,10 @@ const ws = createSocket(events);
|
|||||||
ws.connect();
|
ws.connect();
|
||||||
events.setWs(ws);
|
events.setWs(ws);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
|
LogRocket.init('yh0dy3/mnml');
|
||||||
|
}
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
{window.Stripe
|
{window.Stripe
|
||||||
|
|||||||
@ -152,11 +152,9 @@ class AccountStatus extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section class='account top' onClick={tlClick}>
|
<section class='account top' onClick={tlClick}>
|
||||||
|
{subInfo()}
|
||||||
<div>
|
<div>
|
||||||
{subInfo()}
|
<h3>Email</h3>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="email">Email Settings:</label>
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Recovery Email</dt>
|
<dt>Recovery Email</dt>
|
||||||
<dd>{email ? email.email : 'No email set'}</dd>
|
<dd>{email ? email.email : 'No email set'}</dd>
|
||||||
@ -174,6 +172,7 @@ class AccountStatus extends Component {
|
|||||||
<button onClick={() => sendSetEmail(emailState)}>Update</button>
|
<button onClick={() => sendSetEmail(emailState)}>Update</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<h3>Password</h3>
|
||||||
<label for="current">Password:</label>
|
<label for="current">Password:</label>
|
||||||
<input
|
<input
|
||||||
class="login-input"
|
class="login-input"
|
||||||
@ -208,6 +207,7 @@ class AccountStatus extends Component {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<h3>Other</h3>
|
||||||
<figure>
|
<figure>
|
||||||
<figcaption>spawn new construct</figcaption>
|
<figcaption>spawn new construct</figcaption>
|
||||||
<button onClick={() => sendConstructSpawn()} type="submit">
|
<button onClick={() => sendConstructSpawn()} type="submit">
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const { connect } = require('preact-redux');
|
|||||||
const Amplify = require('./anims/amplify');
|
const Amplify = require('./anims/amplify');
|
||||||
const Attack = require('./anims/attack');
|
const Attack = require('./anims/attack');
|
||||||
const Absorb = require('./anims/absorb');
|
const Absorb = require('./anims/absorb');
|
||||||
|
const Absorption = require('./anims/absorption');
|
||||||
const Bash = require('./anims/bash');
|
const Bash = require('./anims/bash');
|
||||||
const Blast = require('./anims/blast');
|
const Blast = require('./anims/blast');
|
||||||
const Block = require('./anims/block');
|
const Block = require('./anims/block');
|
||||||
@ -44,8 +45,8 @@ const { removeTier } = require('../utils');
|
|||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const { animTarget } = state;
|
const { animTarget, account } = state;
|
||||||
return { animTarget };
|
return { animTarget, account };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -60,20 +61,21 @@ class ConstructAnimation extends Component {
|
|||||||
const {
|
const {
|
||||||
animTarget,
|
animTarget,
|
||||||
construct,
|
construct,
|
||||||
|
account,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (!animTarget) return false;
|
if (!animTarget) return false;
|
||||||
|
|
||||||
const {
|
const { skill, event: [, variant] } = animTarget;
|
||||||
skill,
|
const { construct: constructId, player, direction: [x, y] } = variant;
|
||||||
player,
|
|
||||||
direction,
|
const animY = y && player === account.id ? -1 : y;
|
||||||
constructId,
|
const isPlayer = player === account.id;
|
||||||
} = animTarget;
|
const direction = { x, y: animY };
|
||||||
|
|
||||||
const animSkill = removeTier(skill);
|
const animSkill = removeTier(skill);
|
||||||
if (!constructId.includes(construct.id)) return false;
|
if (!constructId.includes(construct.id)) return false;
|
||||||
|
|
||||||
|
|
||||||
// find target animation
|
// find target animation
|
||||||
const chooseAnim = () => {
|
const chooseAnim = () => {
|
||||||
switch (animSkill) {
|
switch (animSkill) {
|
||||||
@ -93,9 +95,9 @@ class ConstructAnimation extends Component {
|
|||||||
case 'Haste': return <Haste />;
|
case 'Haste': return <Haste />;
|
||||||
case 'Triage': return <Triage />;
|
case 'Triage': return <Triage />;
|
||||||
case 'TriageTick': return <TriageTick />;
|
case 'TriageTick': return <TriageTick />;
|
||||||
case 'Link': return <Link player={player} />;
|
case 'Link': return <Link player={isPlayer} />;
|
||||||
case 'Hybrid': return <Hybrid />;
|
case 'Hybrid': return <Hybrid />;
|
||||||
case 'Intercept': return <Intercept player={player} />;
|
case 'Intercept': return <Intercept player={isPlayer} />;
|
||||||
|
|
||||||
// Debuff base
|
// Debuff base
|
||||||
case 'Debuff': return <Debuff />;
|
case 'Debuff': return <Debuff />;
|
||||||
@ -112,21 +114,22 @@ class ConstructAnimation extends Component {
|
|||||||
// case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null);
|
// case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null);
|
||||||
case 'Bash': return <Bash />;
|
case 'Bash': return <Bash />;
|
||||||
case 'Absorb': return <Absorb />;
|
case 'Absorb': return <Absorb />;
|
||||||
|
case 'Absorption': return <Absorption />;
|
||||||
case 'Sleep': return <Sleep />;
|
case 'Sleep': return <Sleep />;
|
||||||
case 'Break': return <Break />;
|
case 'Break': return <Break />;
|
||||||
case 'Ruin': return <Ruin />;
|
case 'Ruin': return <Ruin />;
|
||||||
|
|
||||||
// Block Base
|
// Block Base
|
||||||
case 'Block': return <Block />;
|
case 'Block': return <Block />;
|
||||||
case 'Sustain': return <Sustain player={player} />;
|
case 'Sustain': return <Sustain player={isPlayer} />;
|
||||||
case 'Electrify': return <Electrify />;
|
case 'Electrify': return <Electrify />;
|
||||||
case 'Electrocute': return <Electrocute />;
|
case 'Electrocute': return <Electrocute />;
|
||||||
case 'ElectrocuteTick': return <Electrocute />;
|
case 'ElectrocuteTick': return <Electrocute />;
|
||||||
case 'Counter': return <Counter player={player} />;
|
case 'Counter': return <Counter player={isPlayer} />;
|
||||||
case 'CounterAttack': return <Attack direction={direction} />;
|
case 'CounterAttack': return <Attack direction={direction} />;
|
||||||
case 'Purify': return <Purify player={player} />;
|
case 'Purify': return <Purify player={isPlayer} />;
|
||||||
case 'Recharge': return <Recharge player={player} />;
|
case 'Recharge': return <Recharge player={isPlayer} />;
|
||||||
case 'Reflect': return <Refl player={player} />;
|
case 'Reflect': return <Refl player={isPlayer} />;
|
||||||
|
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// shamelessly lifted from teh anime docs
|
|
||||||
// https://animejs.com/documentation/#svgAttr
|
|
||||||
|
|
||||||
class Absorb extends Component {
|
class Absorb extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -56,7 +44,7 @@ class Absorb extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#absorb'],
|
targets: ['#absorb'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -66,8 +54,6 @@ class Absorb extends Component {
|
|||||||
targets: ['#absorb polygon'],
|
targets: ['#absorb polygon'],
|
||||||
points: '64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788',
|
points: '64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788',
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -76,8 +62,6 @@ class Absorb extends Component {
|
|||||||
strokeWidth: [2, 1],
|
strokeWidth: [2, 1],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -90,8 +74,7 @@ class Absorb extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Absorb);
|
module.exports = Absorb;
|
||||||
|
|||||||
80
client/src/components/anims/absorption.jsx
Normal file
80
client/src/components/anims/absorption.jsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { Component } = require('preact');
|
||||||
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
|
class Absorb extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.animations = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
class='skill-animation blue'
|
||||||
|
version="1.1"
|
||||||
|
id="absorb"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 128 128">
|
||||||
|
<defs>
|
||||||
|
<filter id="absorbFilter">
|
||||||
|
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<polygon
|
||||||
|
class='blue'
|
||||||
|
points="64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788"
|
||||||
|
filter="url(#absorbFilter)">
|
||||||
|
</polygon>
|
||||||
|
<polygon
|
||||||
|
class='white'
|
||||||
|
points="64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788">
|
||||||
|
</polygon>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.animations.push(anime({
|
||||||
|
targets: ['#absorb'],
|
||||||
|
opacity: [
|
||||||
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
|
],
|
||||||
|
easing: 'easeInOutSine',
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.animations.push(anime({
|
||||||
|
targets: ['#absorb polygon'],
|
||||||
|
points: '64 68.64 8.574 100 63.446 67.68 64 4 64.554 67.68 119.426 100',
|
||||||
|
easing: 'easeOutExpo',
|
||||||
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.animations.push(anime({
|
||||||
|
targets: ['#absorb polygon.white'],
|
||||||
|
strokeWidth: [2, 1],
|
||||||
|
easing: 'easeInOutSine',
|
||||||
|
direction: 'alternate',
|
||||||
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is necessary because
|
||||||
|
// skipping / timing / unmounting race conditions
|
||||||
|
// can cause the animations to cut short, this will ensure the values are reset
|
||||||
|
// because preact will recycle all these components
|
||||||
|
componentWillUnmount() {
|
||||||
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
|
this.animations[i].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Absorb;
|
||||||
@ -5,13 +5,6 @@ const { connect } = require('preact-redux');
|
|||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Amplify extends Component {
|
class Amplify extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -43,7 +36,7 @@ class Amplify extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#amplify'],
|
targets: ['#amplify'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -54,8 +47,6 @@ class Amplify extends Component {
|
|||||||
d: [{ value: altPath }],
|
d: [{ value: altPath }],
|
||||||
stroke: ['#3050f8', '#a52a2a'],
|
stroke: ['#3050f8', '#a52a2a'],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -64,8 +55,6 @@ class Amplify extends Component {
|
|||||||
baseFrequency: 0.15,
|
baseFrequency: 0.15,
|
||||||
scale: 4,
|
scale: 4,
|
||||||
easing: 'easeInOutExpo',
|
easing: 'easeInOutExpo',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -78,8 +67,7 @@ class Amplify extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Amplify);
|
module.exports = Amplify;
|
||||||
|
|||||||
@ -5,13 +5,6 @@ const anime = require('animejs').default;
|
|||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Attack extends Component {
|
class Attack extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super();
|
super();
|
||||||
@ -46,8 +39,8 @@ class Attack extends Component {
|
|||||||
y: [400, 200],
|
y: [400, 200],
|
||||||
height: [100, 10, 0],
|
height: [100, 10, 0],
|
||||||
width: [12, 5, 0],
|
width: [12, 5, 0],
|
||||||
delay: () => anime.random(TIMES.TARGET_DELAY_MS, TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 2),
|
delay: () => anime.random(0, TIMES.TARGET_DURATION_MS / 4),
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS * 5 / 4,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +52,7 @@ class Attack extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Attack);
|
module.exports = Attack;
|
||||||
|
|||||||
@ -8,7 +8,6 @@ function Banish(id, idle) {
|
|||||||
scaleY: 0,
|
scaleY: 0,
|
||||||
fill: '#fff',
|
fill: '#fff',
|
||||||
easing: 'easeOutElastic',
|
easing: 'easeOutElastic',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.45,
|
duration: TIMES.TARGET_DURATION_MS * 0.45,
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
begin: idle.pause,
|
begin: idle.pause,
|
||||||
|
|||||||
@ -5,13 +5,6 @@ const anime = require('animejs').default;
|
|||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Bash extends Component {
|
class Bash extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -54,7 +47,7 @@ class Bash extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#bash'],
|
targets: ['#bash'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -64,7 +57,6 @@ class Bash extends Component {
|
|||||||
targets: ['#bash'],
|
targets: ['#bash'],
|
||||||
scale: {
|
scale: {
|
||||||
value: 1,
|
value: 1,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeInExpo',
|
easing: 'easeInExpo',
|
||||||
},
|
},
|
||||||
@ -72,10 +64,9 @@ class Bash extends Component {
|
|||||||
value: 180,
|
value: 180,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
loop: true,
|
loop: true,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
},
|
},
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.1,
|
delay: TIMES.TARGET_DURATION_MS * 0.1,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -86,8 +77,6 @@ class Bash extends Component {
|
|||||||
scale: 10,
|
scale: 10,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -100,8 +89,7 @@ class Bash extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Bash);
|
module.exports = Bash;
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Bash extends Component {
|
class Bash extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -47,7 +39,7 @@ class Bash extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#bash'],
|
targets: ['#bash'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -57,7 +49,6 @@ class Bash extends Component {
|
|||||||
targets: ['#bash'],
|
targets: ['#bash'],
|
||||||
scale: {
|
scale: {
|
||||||
value: 1,
|
value: 1,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeInExpo',
|
easing: 'easeInExpo',
|
||||||
},
|
},
|
||||||
@ -74,7 +65,7 @@ class Bash extends Component {
|
|||||||
{ translateX: 0, translateY: 2 },
|
{ translateX: 0, translateY: 2 },
|
||||||
],
|
],
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.1,
|
delay: TIMES.TARGET_DURATION_MS * 0.1,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -90,7 +81,6 @@ class Bash extends Component {
|
|||||||
],
|
],
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -103,8 +93,7 @@ class Bash extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Bash);
|
module.exports = Bash;
|
||||||
|
|||||||
@ -1,34 +1,12 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const times = require('lodash/times');
|
const times = require('lodash/times');
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
|
||||||
return (
|
|
||||||
<circle
|
|
||||||
cx={x}
|
|
||||||
cy={y}
|
|
||||||
r={radius}
|
|
||||||
fill="url(#grad1)"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke={colour}
|
|
||||||
filter="url(#explosion)"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Blast extends Component {
|
class Blast extends Component {
|
||||||
constructor(props) {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
}
|
}
|
||||||
@ -62,7 +40,7 @@ class Blast extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#blast'],
|
targets: ['#blast'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.5, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.5, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -75,7 +53,6 @@ class Blast extends Component {
|
|||||||
`,
|
`,
|
||||||
style: { rotate: anime.random(-180, 180) },
|
style: { rotate: anime.random(-180, 180) },
|
||||||
easing: 'easeOutCubic',
|
easing: 'easeOutCubic',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -88,8 +65,7 @@ class Blast extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Blast);
|
module.exports = Blast;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Block extends Component {
|
class Block extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -38,7 +30,7 @@ class Block extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#block'],
|
targets: ['#block'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -53,8 +45,7 @@ class Block extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Block);
|
module.exports = Block;
|
||||||
|
|||||||
@ -1,20 +1,12 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
// logarithmic spiral lifted from
|
// logarithmic spiral lifted from
|
||||||
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Break extends Component {
|
class Break extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -63,7 +55,7 @@ class Break extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#break'],
|
targets: ['#break'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -74,7 +66,6 @@ class Break extends Component {
|
|||||||
rotate: 180,
|
rotate: 180,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
loop: true,
|
loop: true,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -82,7 +73,6 @@ class Break extends Component {
|
|||||||
targets: ['#break circle'],
|
targets: ['#break circle'],
|
||||||
easing: 'easeInSine',
|
easing: 'easeInSine',
|
||||||
r: 300,
|
r: 300,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -93,10 +83,8 @@ class Break extends Component {
|
|||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is necessary because
|
// this is necessary because
|
||||||
@ -107,8 +95,7 @@ class Break extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Break);
|
module.exports = Break;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Buff extends Component {
|
class Buff extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -39,7 +31,7 @@ class Buff extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#buff'],
|
targets: ['#buff'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -50,7 +42,6 @@ class Buff extends Component {
|
|||||||
points: '0,190 100,10 190,190',
|
points: '0,190 100,10 190,190',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -59,7 +50,6 @@ class Buff extends Component {
|
|||||||
points: '40,170 100,50 160,170',
|
points: '40,170 100,50 160,170',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -68,7 +58,6 @@ class Buff extends Component {
|
|||||||
points: '70,150 100,90 130,150',
|
points: '70,150 100,90 130,150',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -81,8 +70,7 @@ class Buff extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Buff);
|
module.exports = Buff;
|
||||||
|
|||||||
@ -1,26 +1,19 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
const { randomPoints } = require('../../utils');
|
const { randomPoints } = require('../../utils');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
cx={x}
|
cx={anime.random(0, 400)}
|
||||||
cy={y}
|
cy={anime.random(0, 400)}
|
||||||
r={radius}
|
r={radius}
|
||||||
fill={colour}
|
fill={colour}
|
||||||
stroke="none"
|
stroke={colour === '#a52a2a' ? 'none' : '#f5f5f5'}
|
||||||
|
stroke-width={colour === '#a52a2a' ? '0' : '0.05em'}
|
||||||
filter={colour === '#a52a2a' ? 'url(#chaosRedFilter)' : 'url(#chaosBlueFilter)'}
|
filter={colour === '#a52a2a' ? 'url(#chaosRedFilter)' : 'url(#chaosBlueFilter)'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -30,10 +23,10 @@ class Chaos extends Component {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
const points = randomPoints(20, 30, { x: 0, y: 0, width: 300, height: 100 });
|
const points = randomPoints(20, 30, { x: 0, y: 0, width: 1000, height: 1000 });
|
||||||
this.charges = points.map(coord => {
|
this.charges = points.map(coord => {
|
||||||
const colour = Math.random() >= 0.5 ? '#a52a2a' : '#3050f8';
|
const colour = Math.random() >= 0.5 ? '#a52a2a' : '#3050f8';
|
||||||
return projectile(coord[0], coord[1], 14, colour);
|
return projectile(coord[0], coord[1], '0.5em', colour);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,39 +58,12 @@ class Chaos extends Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const projectiles = document.querySelectorAll('.skill-anim circle');
|
const projectiles = document.querySelectorAll('.skill-anim circle');
|
||||||
anime.set('.skill-anim', {
|
|
||||||
translateY: -(window.innerHeight) * 0.35 * this.props.direction.y,
|
|
||||||
translateX: -(window.innerWidth) * 0.15 * this.props.direction.x,
|
|
||||||
opacity: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: '.skill-anim',
|
|
||||||
opacity: [
|
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.3 },
|
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.POST_SKILL_DURATION_MS },
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: '.skill-anim',
|
|
||||||
translateY: 0,
|
|
||||||
translateX: 0,
|
|
||||||
loop: false,
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: (TIMES.TARGET_DURATION_MS * 1 / 2),
|
|
||||||
easing: 'easeInQuad',
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#chaosRedFilter feTurbulence', '#chaosRedFilter feDisplacementMap'],
|
targets: ['#chaosRedFilter feTurbulence', '#chaosRedFilter feDisplacementMap'],
|
||||||
baseFrequency: 2,
|
baseFrequency: 2,
|
||||||
scale: 20,
|
scale: 5,
|
||||||
numOctaves: 5,
|
numOctaves: 3,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -105,13 +71,9 @@ class Chaos extends Component {
|
|||||||
targets: proj,
|
targets: proj,
|
||||||
cx: 150 + (Math.random() * 50 * (Math.random() < 0.5 ? -1 : 1)),
|
cx: 150 + (Math.random() * 50 * (Math.random() < 0.5 ? -1 : 1)),
|
||||||
cy: 200 + (Math.random() * 50 * (Math.random() < 0.5 ? -1 : 1)),
|
cy: 200 + (Math.random() * 50 * (Math.random() < 0.5 ? -1 : 1)),
|
||||||
// cx: 150,
|
duration: anime.random(TIMES.TARGET_DURATION_MS * 2 / 3, TIMES.TARGET_DURATION_MS),
|
||||||
// cy: 200,
|
opacity: 0,
|
||||||
// opacity: 0,
|
easing: 'easeInExpo',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: (TIMES.TARGET_DURATION_MS * 2 / 3),
|
|
||||||
easing: 'easeInQuad',
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,8 +81,7 @@ class Chaos extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Chaos);
|
module.exports = Chaos;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Counter extends Component {
|
class Counter extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -51,7 +43,7 @@ class Counter extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#counter'],
|
targets: ['#counter'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -60,7 +52,7 @@ class Counter extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#counter'],
|
targets: ['#counter'],
|
||||||
rotateX: 180,
|
rotateX: 180,
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 3,
|
delay: TIMES.TARGET_DURATION_MS / 3,
|
||||||
duration: TIMES.TARGET_DURATION_MS / 2,
|
duration: TIMES.TARGET_DURATION_MS / 2,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -71,8 +63,6 @@ class Counter extends Component {
|
|||||||
scale: 10,
|
scale: 10,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -85,8 +75,7 @@ class Counter extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Counter);
|
module.exports = Counter;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Curse extends Component {
|
class Curse extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -54,7 +46,7 @@ class Curse extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#curse'],
|
targets: ['#curse'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -64,7 +56,6 @@ class Curse extends Component {
|
|||||||
targets: ['#curseCircleOne', '#curseFilterOne'],
|
targets: ['#curseCircleOne', '#curseFilterOne'],
|
||||||
r: 30,
|
r: 30,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -72,7 +63,6 @@ class Curse extends Component {
|
|||||||
targets: ['#curseCircleTwo', '#curseFilterTwo'],
|
targets: ['#curseCircleTwo', '#curseFilterTwo'],
|
||||||
r: 60,
|
r: 60,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -80,7 +70,6 @@ class Curse extends Component {
|
|||||||
targets: ['#curseCircleThree', '#curseFilterThree'],
|
targets: ['#curseCircleThree', '#curseFilterThree'],
|
||||||
r: 90,
|
r: 90,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -93,8 +82,7 @@ class Curse extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Curse);
|
module.exports = Curse;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Debuff extends Component {
|
class Debuff extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -41,7 +33,7 @@ class Debuff extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#debuff'],
|
targets: ['#debuff'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -52,7 +44,6 @@ class Debuff extends Component {
|
|||||||
points: '0,190 100,10 190,190',
|
points: '0,190 100,10 190,190',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -61,7 +52,6 @@ class Debuff extends Component {
|
|||||||
points: '40,170 100,50 160,170',
|
points: '40,170 100,50 160,170',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -70,7 +60,6 @@ class Debuff extends Component {
|
|||||||
points: '70,150 100,90 130,150',
|
points: '70,150 100,90 130,150',
|
||||||
|
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -83,8 +72,7 @@ class Debuff extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Debuff);
|
module.exports = Debuff;
|
||||||
|
|||||||
@ -2,17 +2,9 @@ const preact = require('preact');
|
|||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const times = require('lodash/times');
|
const times = require('lodash/times');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Decay extends Component {
|
class Decay extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -40,7 +32,7 @@ class Decay extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#decay'],
|
targets: ['#decay'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -55,7 +47,6 @@ class Decay extends Component {
|
|||||||
rotate(${anime.random(-15, 15)})
|
rotate(${anime.random(-15, 15)})
|
||||||
`,
|
`,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -68,8 +59,7 @@ class Decay extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Decay);
|
module.exports = Decay;
|
||||||
|
|||||||
@ -1,19 +1,10 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const times = require('lodash/times');
|
const times = require('lodash/times');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Electrify extends Component {
|
class Electrify extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -57,7 +48,7 @@ class Electrify extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#electrify'],
|
targets: ['#electrify'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -109,8 +100,7 @@ class Electrify extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Electrify);
|
module.exports = Electrify;
|
||||||
|
|||||||
@ -1,19 +1,11 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const times = require('lodash/times')
|
const times = require('lodash/times')
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Electrocute extends Component {
|
class Electrocute extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -55,7 +47,7 @@ class Electrocute extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#electrify'],
|
targets: ['#electrify'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -101,8 +93,7 @@ class Electrocute extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Electrocute);
|
module.exports = Electrocute;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Haste extends Component {
|
class Haste extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -49,7 +41,7 @@ class Haste extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#haste'],
|
targets: ['#haste'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -59,7 +51,6 @@ class Haste extends Component {
|
|||||||
targets: ['#haste g'],
|
targets: ['#haste g'],
|
||||||
stroke: [COLOURS.GREEN, COLOURS.RED],
|
stroke: [COLOURS.GREEN, COLOURS.RED],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.75,
|
duration: TIMES.TARGET_DURATION_MS * 0.75,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -69,8 +60,6 @@ class Haste extends Component {
|
|||||||
scale: 10,
|
scale: 10,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -83,8 +72,7 @@ class Haste extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Haste);
|
module.exports = Haste;
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
const { randomPoints } = require('../../utils');
|
const { randomPoints } = require('../../utils');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
@ -60,7 +52,7 @@ class Heal extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#heal'],
|
targets: ['#heal'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS / 4, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS / 4, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -70,8 +62,7 @@ class Heal extends Component {
|
|||||||
targets: ['#heal circle'],
|
targets: ['#heal circle'],
|
||||||
cx: 150,
|
cx: 150,
|
||||||
cy: 200,
|
cy: 200,
|
||||||
delay: TIMES.TARGET_DELAY_MS * 4,
|
duration: TIMES.TARGET_DURATION_MS * 0.6,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.9,
|
|
||||||
easing: 'easeOutCirc',
|
easing: 'easeOutCirc',
|
||||||
direction: 'reverse',
|
direction: 'reverse',
|
||||||
}));
|
}));
|
||||||
@ -81,8 +72,7 @@ class Heal extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Heal);
|
module.exports = Heal;
|
||||||
|
|||||||
@ -1,16 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// shamelessly lifted from teh anime docs
|
// shamelessly lifted from teh anime docs
|
||||||
// https://animejs.com/documentation/#svgAttr
|
// https://animejs.com/documentation/#svgAttr
|
||||||
|
|
||||||
@ -54,7 +47,7 @@ class Hex extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#hex'],
|
targets: ['#hex'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -65,7 +58,6 @@ class Hex extends Component {
|
|||||||
points: '64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788',
|
points: '64 124.94732621931382 8.574 96.00354944613788 8.62269130211947 32.03166105954991 64 4 119.37730869788052 32.03166105954991 119.426 96.00354944613788',
|
||||||
easing: 'easeOutExpo',
|
easing: 'easeOutExpo',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -75,7 +67,6 @@ class Hex extends Component {
|
|||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -88,8 +79,7 @@ class Hex extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Hex);
|
module.exports = Hex;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Hybrid extends Component {
|
class Hybrid extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -94,12 +86,11 @@ class Hybrid extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#hybrid'],
|
targets: ['#hybrid'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
transform: {
|
transform: {
|
||||||
value: ['rotate(0)', 'rotate(360)'],
|
value: ['rotate(0)', 'rotate(360)'],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
},
|
},
|
||||||
@ -110,7 +101,6 @@ class Hybrid extends Component {
|
|||||||
r: [10, anime.random(10, 30)],
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.green-one'],
|
targets: ['#hybrid circle.green-one'],
|
||||||
cx: [50, 250, 50, 250],
|
cx: [50, 250, 50, 250],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
loop: true,
|
loop: true,
|
||||||
@ -120,7 +110,6 @@ class Hybrid extends Component {
|
|||||||
r: [10, anime.random(10, 30)],
|
r: [10, anime.random(10, 30)],
|
||||||
targets: ['#hybrid circle.green-two'],
|
targets: ['#hybrid circle.green-two'],
|
||||||
cy: [250, 50, 250, 50],
|
cy: [250, 50, 250, 50],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
loop: true,
|
loop: true,
|
||||||
@ -131,7 +120,6 @@ class Hybrid extends Component {
|
|||||||
targets: ['#hybrid circle.bluewhite-one'],
|
targets: ['#hybrid circle.bluewhite-one'],
|
||||||
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
||||||
cy: [50, 250, 50, 250],
|
cy: [50, 250, 50, 250],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
loop: true,
|
loop: true,
|
||||||
@ -142,7 +130,6 @@ class Hybrid extends Component {
|
|||||||
targets: ['#hybrid circle.bluewhite-two'],
|
targets: ['#hybrid circle.bluewhite-two'],
|
||||||
cx: [250, 50, 250, 50],
|
cx: [250, 50, 250, 50],
|
||||||
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
fill: [COLOURS.WHITE, COLOURS.BLUE],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
loop: true,
|
loop: true,
|
||||||
@ -153,8 +140,7 @@ class Hybrid extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Hybrid);
|
module.exports = Hybrid;
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -9,13 +7,6 @@ const {
|
|||||||
COLOURS,
|
COLOURS,
|
||||||
} = require('../../constants');
|
} = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Intercept extends Component {
|
class Intercept extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -47,7 +38,7 @@ class Intercept extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#intercept'],
|
targets: ['#intercept'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -61,7 +52,6 @@ class Intercept extends Component {
|
|||||||
],
|
],
|
||||||
strokeWidth: 0,
|
strokeWidth: 0,
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInCubic',
|
easing: 'easeInCubic',
|
||||||
// direction: 'reverse',
|
// direction: 'reverse',
|
||||||
@ -70,7 +60,6 @@ class Intercept extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#intercept rect'],
|
targets: ['#intercept rect'],
|
||||||
y: 96,
|
y: 96,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInCubic',
|
easing: 'easeInCubic',
|
||||||
// direction: 'reverse',
|
// direction: 'reverse',
|
||||||
@ -82,8 +71,6 @@ class Intercept extends Component {
|
|||||||
scale: 10,
|
scale: 10,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -96,8 +83,7 @@ class Intercept extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Intercept);
|
module.exports = Intercept;
|
||||||
|
|||||||
@ -6,7 +6,6 @@ function Invert(id, idle) {
|
|||||||
return anime({
|
return anime({
|
||||||
targets: [document.getElementById(id)],
|
targets: [document.getElementById(id)],
|
||||||
rotate: 180,
|
rotate: 180,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.45,
|
duration: TIMES.TARGET_DURATION_MS * 0.45,
|
||||||
easing: 'easeInOutElastic',
|
easing: 'easeInOutElastic',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Link extends Component {
|
class Link extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -68,7 +60,7 @@ class Link extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#link'],
|
targets: ['#link'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: 1000 },
|
{ value: 1, duration: 1000 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -78,7 +70,6 @@ class Link extends Component {
|
|||||||
targets: ['#link path'],
|
targets: ['#link path'],
|
||||||
strokeDashoffset: [anime.setDashoffset, 0],
|
strokeDashoffset: [anime.setDashoffset, 0],
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.8,
|
duration: TIMES.TARGET_DURATION_MS * 0.8,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -91,8 +82,7 @@ class Link extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Link);
|
module.exports = Link;
|
||||||
|
|||||||
@ -1,17 +1,8 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Purge extends Component {
|
class Purge extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -51,7 +42,7 @@ class Purge extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#purge'],
|
targets: ['#purge'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -60,7 +51,6 @@ class Purge extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#purge g'],
|
targets: ['#purge g'],
|
||||||
strokeWidth: [15, 0],
|
strokeWidth: [15, 0],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInSine',
|
easing: 'easeInSine',
|
||||||
}));
|
}));
|
||||||
@ -81,8 +71,7 @@ class Purge extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Purge);
|
module.exports = Purge;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
@ -80,7 +72,7 @@ class Purify extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#purify'],
|
targets: ['#purify'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -89,7 +81,7 @@ class Purify extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#block'],
|
targets: ['#block'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 0, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS },
|
{ value: 0, duration: TIMES.TARGET_DURATION_MS },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
}));
|
}));
|
||||||
@ -102,7 +94,6 @@ class Purify extends Component {
|
|||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
cx: 128,
|
cx: 128,
|
||||||
cy: 24,
|
cy: 24,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -115,8 +106,7 @@ class Purify extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Purify);
|
module.exports = Purify;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Recharge extends Component {
|
class Recharge extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -59,7 +51,7 @@ class Recharge extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#recharge'],
|
targets: ['#recharge'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -71,7 +63,6 @@ class Recharge extends Component {
|
|||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
direction: 'alternate',
|
direction: 'alternate',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -82,7 +73,6 @@ class Recharge extends Component {
|
|||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
|
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -95,8 +85,7 @@ class Recharge extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Recharge);
|
module.exports = Recharge;
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
const preact = require('preact');
|
|
||||||
const { Component } = require('preact');
|
|
||||||
const anime = require('animejs').default;
|
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Block extends Component {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.animations = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
class="skill-animation red"
|
|
||||||
version="1.1"
|
|
||||||
id="block"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
style={{ transform: 'rotate(180deg)' }}
|
|
||||||
viewBox="0 0 256 256">
|
|
||||||
<filter id='blockFilter'>
|
|
||||||
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"></feTurbulence>
|
|
||||||
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="15" xChannelSelector="R" yChannelSelector="G"></feDisplacementMap>
|
|
||||||
</filter>
|
|
||||||
<polygon
|
|
||||||
points='128,168 80,240 176,240'
|
|
||||||
style={{ filter: 'url("#blockFilter")' }}
|
|
||||||
id="charge"/>
|
|
||||||
<polyline
|
|
||||||
points='176,240 212,216 128,96 44,216 80,240'
|
|
||||||
style={{ filter: 'url("#blockFilter")' }}
|
|
||||||
id="charge"/>
|
|
||||||
<polyline
|
|
||||||
points='212,216 248,192 128,24 8,192 44,216'
|
|
||||||
style={{ filter: 'url("#blockFilter")' }}
|
|
||||||
id="charge"/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: ['#block'],
|
|
||||||
opacity: [
|
|
||||||
{ value: 1, delay: TIMES.TARGET_FADE_IN_DELAY, duration: TIMES.TARGET_FADE_IN_DURATION },
|
|
||||||
{ value: 0, delay: TIMES.TARGET_FADE_OUT_DELAY, duration: TIMES.FADE_OUT_DURATION },
|
|
||||||
],
|
|
||||||
easing: 'easeInOutSine',
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: ['#blockFilter feTurbulence', ' #blockFilter feDisplacementMap'],
|
|
||||||
baseFrequency: 0,
|
|
||||||
scale: 1,
|
|
||||||
easing: 'easeOutSine',
|
|
||||||
|
|
||||||
delay: TIMES.TARGET_FADE_IN_DELAY,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is necessary because
|
|
||||||
// skipping / timing / unmounting race conditions
|
|
||||||
// can cause the animations to cut short, this will ensure the values are reset
|
|
||||||
// because preact will recycle all these components
|
|
||||||
componentWillUnmount() {
|
|
||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
|
||||||
this.animations[i].reset();
|
|
||||||
}
|
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = addState(Block);
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
const preact = require('preact');
|
|
||||||
const { Component } = require('preact');
|
|
||||||
const anime = require('animejs').default;
|
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Intercept extends Component {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.animations = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
render({ player }) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
class="skill-animation red"
|
|
||||||
version="1.1"
|
|
||||||
id="intercept"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
style={{
|
|
||||||
transform: player ? 'rotate3d(1, 0, 0, 180deg)' : '',
|
|
||||||
}}
|
|
||||||
viewBox="0 0 128 128">
|
|
||||||
<filter id='interceptFilter'>
|
|
||||||
<feTurbulence type="turbulence" baseFrequency="0" numOctaves="1" result="turbulence"></feTurbulence>
|
|
||||||
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="1" xChannelSelector="R" yChannelSelector="G"></feDisplacementMap>
|
|
||||||
</filter>
|
|
||||||
<g filter="url(#interceptFilter)">
|
|
||||||
<circle cx="64" cy="128" r="48" />
|
|
||||||
<circle cx="64" cy="128" r="32" />
|
|
||||||
<circle cx="64" cy="128" r="16" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: ['#intercept'],
|
|
||||||
opacity: [
|
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
|
||||||
],
|
|
||||||
easing: 'easeInOutSine',
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: ['#intercept'],
|
|
||||||
scale: 3,
|
|
||||||
strokeWidth: 0,
|
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
|
||||||
easing: 'easeInOutCubic',
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: ['#interceptFilter feTurbulence', '#interceptFilter feDisplacementMap'],
|
|
||||||
baseFrequency: 2,
|
|
||||||
scale: 10,
|
|
||||||
numOctaves: 5,
|
|
||||||
easing: 'easeOutSine',
|
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is necessary because
|
|
||||||
// skipping / timing / unmounting race conditions
|
|
||||||
// can cause the animations to cut short, this will ensure the values are reset
|
|
||||||
// because preact will recycle all these components
|
|
||||||
componentWillUnmount() {
|
|
||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
|
||||||
this.animations[i].reset();
|
|
||||||
}
|
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = addState(Intercept);
|
|
||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Refl extends Component {
|
class Refl extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -54,7 +46,7 @@ class Refl extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#reflect'],
|
targets: ['#reflect'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -77,8 +69,7 @@ class Refl extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Refl);
|
module.exports = Refl;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Restrict extends Component {
|
class Restrict extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -42,7 +34,7 @@ class Restrict extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#restrict'],
|
targets: ['#restrict'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -52,12 +44,11 @@ class Restrict extends Component {
|
|||||||
targets: ['#restrict'],
|
targets: ['#restrict'],
|
||||||
scale: {
|
scale: {
|
||||||
value: 1,
|
value: 1,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeInExpo',
|
easing: 'easeInExpo',
|
||||||
},
|
},
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.1,
|
delay: TIMES.TARGET_DURATION_MS * 0.1,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -69,7 +60,6 @@ class Restrict extends Component {
|
|||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -78,7 +68,7 @@ class Restrict extends Component {
|
|||||||
|
|
||||||
d: 'M 124 8 L 8 124',
|
d: 'M 124 8 L 8 124',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.4,
|
delay: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -88,7 +78,7 @@ class Restrict extends Component {
|
|||||||
|
|
||||||
d: 'M 124 124 L 8 8',
|
d: 'M 124 124 L 8 8',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.4,
|
delay: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -102,8 +92,7 @@ class Restrict extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Restrict);
|
module.exports = Restrict;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Ruin extends Component {
|
class Ruin extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -75,7 +67,7 @@ class Ruin extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#ruin'],
|
targets: ['#ruin'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -86,7 +78,6 @@ class Ruin extends Component {
|
|||||||
rotate: 180,
|
rotate: 180,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
loop: true,
|
loop: true,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -99,12 +90,7 @@ class Ruin extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Ruin);
|
module.exports = Ruin;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Silence extends Component {
|
class Silence extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -47,7 +39,7 @@ class Silence extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#silence'],
|
targets: ['#silence'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -58,12 +50,11 @@ class Silence extends Component {
|
|||||||
rotate: [90, 90],
|
rotate: [90, 90],
|
||||||
scale: {
|
scale: {
|
||||||
value: 1,
|
value: 1,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeInExpo',
|
easing: 'easeInExpo',
|
||||||
},
|
},
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.1,
|
delay: TIMES.TARGET_DURATION_MS * 0.1,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -73,7 +64,7 @@ class Silence extends Component {
|
|||||||
|
|
||||||
d: 'M 124 8 L 8 124',
|
d: 'M 124 8 L 8 124',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.4,
|
delay: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -83,7 +74,7 @@ class Silence extends Component {
|
|||||||
|
|
||||||
d: 'M 124 124 L 8 8',
|
d: 'M 124 124 L 8 8',
|
||||||
|
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.4,
|
delay: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
}));
|
}));
|
||||||
@ -97,8 +88,7 @@ class Silence extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Silence);
|
module.exports = Silence;
|
||||||
|
|||||||
@ -1,19 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const duration = TIMES.TARGET_DURATION_MS;
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Siphon extends Component {
|
class Siphon extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -43,7 +33,7 @@ class Siphon extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: '.skill-anim',
|
targets: '.skill-anim',
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.3 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.3 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.POST_SKILL_DURATION_MS },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.POST_SKILL_DURATION_MS },
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
@ -51,8 +41,7 @@ class Siphon extends Component {
|
|||||||
anime({
|
anime({
|
||||||
targets: '#siphon',
|
targets: '#siphon',
|
||||||
r: 0,
|
r: 0,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
duration,
|
|
||||||
easing: 'easeInSine',
|
easing: 'easeInSine',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,8 +50,7 @@ class Siphon extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Siphon);
|
module.exports = Siphon;
|
||||||
|
|||||||
@ -1,18 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const duration = TIMES.TARGET_DURATION_MS;
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
@ -82,7 +73,7 @@ class SiphonTick extends Component {
|
|||||||
anime({
|
anime({
|
||||||
targets: '#siphon',
|
targets: '#siphon',
|
||||||
r: 600,
|
r: 600,
|
||||||
duration: duration * 2 / 3,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeInSine',
|
easing: 'easeInSine',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -92,8 +83,8 @@ class SiphonTick extends Component {
|
|||||||
targets: proj,
|
targets: proj,
|
||||||
cx: 150 + (Math.random() * 300 * (Math.random() < 0.5 ? -1 : 1)),
|
cx: 150 + (Math.random() * 300 * (Math.random() < 0.5 ? -1 : 1)),
|
||||||
cy: 150 + (Math.random() * 300 * (Math.random() < 0.5 ? -1 : 1)),
|
cy: 150 + (Math.random() * 300 * (Math.random() < 0.5 ? -1 : 1)),
|
||||||
delay: (Math.random() * duration * 1 / 2),
|
delay: (Math.random() * TIMES.TARGET_DURATION_MS * 1 / 2),
|
||||||
duration,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
easing: 'easeOutQuad',
|
easing: 'easeOutQuad',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -103,8 +94,7 @@ class SiphonTick extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(SiphonTick);
|
module.exports = SiphonTick;
|
||||||
|
|||||||
@ -1,42 +1,17 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
const times = require('lodash/times');
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
const GREEN = '#1FF01F';
|
||||||
function receiveState(state) {
|
const RED = '#a52a2a';
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
|
||||||
return (
|
|
||||||
<circle
|
|
||||||
cx={x}
|
|
||||||
cy={y}
|
|
||||||
stroke="none"
|
|
||||||
r={radius}
|
|
||||||
fill={colour}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sword(colour) {
|
|
||||||
return (
|
|
||||||
<polygon points='150,150 100,75, 150,300, 200,75' stroke="none" fill={colour} id="sword" filter="url(#slayFilter)"></polygon>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Slay extends Component {
|
class Slay extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
this.colour = '#a52a2a';
|
|
||||||
const points = new Array(30).fill(0);
|
|
||||||
this.charges = points.map(() => projectile(150, 420, 7, '#1FF01F'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -47,13 +22,16 @@ class Slay extends Component {
|
|||||||
id="slay"
|
id="slay"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 300 300">
|
viewBox="0 0 300 300">
|
||||||
<filter id="slayFilter">
|
{times(10, () => (
|
||||||
<feGaussianBlur stdDeviation="4"/>
|
<ellipse
|
||||||
<feTurbulence type="turbulence" baseFrequency="0.001" numOctaves="3" result="turbulence"/>
|
cx={anime.random(100, 200)}
|
||||||
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="1" xChannelSelector="A" yChannelSelector="A"/>
|
cy={anime.random(-60, -30)}
|
||||||
</filter>
|
stroke="none"
|
||||||
{sword(this.colour)}
|
rx={anime.random(5, 10)}
|
||||||
{this.charges}
|
ry={10}
|
||||||
|
fill={RED}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -73,73 +51,33 @@ class Slay extends Component {
|
|||||||
|
|
||||||
anime.set('#slay', {
|
anime.set('#slay', {
|
||||||
rotate,
|
rotate,
|
||||||
});
|
|
||||||
|
|
||||||
anime.set('#slay', {
|
|
||||||
translateY: -1 * (window.innerHeight) * 0.35,
|
|
||||||
translateX: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
anime.set('#slayFilter feDisplacementMap', {
|
|
||||||
scale: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
anime.set('#sword', {
|
|
||||||
fill: this.colour,
|
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.animations.push(anime({
|
anime.set('#slay ellipse',{
|
||||||
targets: '#slay',
|
fill: RED,
|
||||||
opacity: [
|
})
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
delay: TIMES.TARGET_DURATION_MS + TIMES.POST_SKILL_DURATION_MS * 0.2,
|
|
||||||
duration: TIMES.POST_SKILL_DURATION_MS * 0.3,
|
|
||||||
}],
|
|
||||||
translateY: 0,
|
|
||||||
translateX: 0,
|
|
||||||
loop: false,
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: (TIMES.TARGET_DURATION_MS * 0.5),
|
|
||||||
easing: 'easeInQuad',
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#slayFilter feTurbulence', '#slayFilter feDisplacementMap'],
|
targets: ['#slay ellipse'],
|
||||||
baseFrequency: 10,
|
cx: 150,
|
||||||
scale: 100,
|
cy: 325,
|
||||||
delay: (TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.5),
|
duration: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
duration: (TIMES.TARGET_DURATION_MS * 0.5),
|
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
||||||
easing: 'easeInQuad',
|
easing: 'easeOutQuad',
|
||||||
|
direction: 'alternate',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
setTimeout(() => anime.set('#slay ellipse',{
|
||||||
targets: '#sword',
|
fill: GREEN,
|
||||||
opacity: 0,
|
}), TIMES.TARGET_DURATION_MS * 0.5);
|
||||||
delay: (TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const projectiles = document.querySelectorAll('#slay circle');
|
|
||||||
projectiles.forEach(proj => {
|
|
||||||
this.animations.push(anime({
|
|
||||||
targets: proj,
|
|
||||||
cx: Math.random() * 250 + 25,
|
|
||||||
cy: Math.random() * 200 - 100,
|
|
||||||
delay: (TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS + TIMES.POST_SKILL_DURATION_MS * 0.2),
|
|
||||||
duration: (TIMES.POST_SKILL_DURATION_MS * 0.3),
|
|
||||||
easing: 'easeInQuad',
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Slay);
|
module.exports = Slay;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
const { randomPoints } = require('../../utils');
|
const { randomPoints } = require('../../utils');
|
||||||
@ -9,13 +8,6 @@ const { randomPoints } = require('../../utils');
|
|||||||
// logarithmic spiral lifted from
|
// logarithmic spiral lifted from
|
||||||
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
@ -81,7 +73,7 @@ class Sleep extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#sleep'],
|
targets: ['#sleep'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
}));
|
}));
|
||||||
@ -91,32 +83,21 @@ class Sleep extends Component {
|
|||||||
rotate: 180,
|
rotate: 180,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
loop: true,
|
loop: true,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
duration: TIMES.TARGET_DURATION_MS + TIMES.POST_SKILL_DURATION_MS,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#stun'],
|
targets: ['#stun'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 0, delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.8, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.8, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/* this.animations.push(anime({
|
|
||||||
targets: ['#heal'],
|
|
||||||
opacity: [
|
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.TARGET_DURATION_MS * 0.3 },
|
|
||||||
{ value: 0, delay: TIMES.POST_SKILL_DURATION_MS * 0.6, duration: TIMES.POST_SKILL_DURATION_MS * 0.4 },
|
|
||||||
],
|
|
||||||
easing: 'easeInOutSine',
|
|
||||||
}));
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#charges'],
|
targets: ['#charges'],
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
delay: anime.stagger(TIMES.TARGET_DURATION_MS * 0.015, { start: TIMES.TARGET_DELAY_MS }),
|
delay: anime.stagger(TIMES.TARGET_DURATION_MS * 0.01),
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -125,11 +106,10 @@ class Sleep extends Component {
|
|||||||
targets: ['#charges'],
|
targets: ['#charges'],
|
||||||
cx: 0,
|
cx: 0,
|
||||||
cy: 0,
|
cy: 0,
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS + TIMES.POST_SKILL_DURATION_MS * 0.75,
|
delay: TIMES.TARGET_DURATION_MS + TIMES.POST_SKILL_DURATION_MS * 0.75,
|
||||||
duration: TIMES.POST_SKILL_DURATION_MS * 0.25,
|
duration: TIMES.POST_SKILL_DURATION_MS * 0.25,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is necessary because
|
// this is necessary because
|
||||||
@ -140,8 +120,7 @@ class Sleep extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Sleep);
|
module.exports = Sleep;
|
||||||
|
|||||||
@ -1,31 +1,16 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Strike extends Component {
|
class Strike extends Component {
|
||||||
constructor(props) {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.props = props;
|
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// const { x, y } = (this.props && this.props.direction) || { x: 0, y: 0 };
|
|
||||||
// const angle = (Math.atan(y / x) * (180 / Math.PI)) + 90;
|
|
||||||
// console.log(x, -y);
|
|
||||||
// console.log(angle);
|
|
||||||
// can't get this shit to work
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
class="strike-anim"
|
class="strike-anim"
|
||||||
@ -54,8 +39,8 @@ class Strike extends Component {
|
|||||||
x: [200, 0, 200],
|
x: [200, 0, 200],
|
||||||
height: [200, 10, 0],
|
height: [200, 10, 0],
|
||||||
width: [20, 400, 0],
|
width: [20, 400, 0],
|
||||||
delay: TIMES.TARGET_DELAY_MS * 0.5,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
|
delay: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
@ -64,7 +49,7 @@ class Strike extends Component {
|
|||||||
scale: 50,
|
scale: 50,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS + (TIMES.TARGET_DURATION_MS / 3),
|
delay: TIMES.TARGET_DURATION_MS / 3,
|
||||||
duration: TIMES.TARGET_DURATION_MS / 2,
|
duration: TIMES.TARGET_DURATION_MS / 2,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -77,9 +62,7 @@ class Strike extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Strike);
|
module.exports = Strike;
|
||||||
|
|||||||
@ -1,20 +1,11 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES } = require('../../constants');
|
const { TIMES } = require('../../constants');
|
||||||
|
|
||||||
// logarithmic spiral lifted from
|
|
||||||
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
// https://upload.wikimedia.org/wikipedia/commons/5/5b/Logarithmic_spiral_(1).svg
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Stun extends Component {
|
class Stun extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -54,7 +45,7 @@ class Stun extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#stun'],
|
targets: ['#stun'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -65,7 +56,6 @@ class Stun extends Component {
|
|||||||
rotate: 180,
|
rotate: 180,
|
||||||
easing: 'linear',
|
easing: 'linear',
|
||||||
loop: true,
|
loop: true,
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -78,8 +68,7 @@ class Stun extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Stun);
|
module.exports = Stun;
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class Sustain extends Component {
|
class Sustain extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -33,17 +25,17 @@ class Sustain extends Component {
|
|||||||
</filter>
|
</filter>
|
||||||
<polyline
|
<polyline
|
||||||
id="stageOne"
|
id="stageOne"
|
||||||
points='0 0'
|
points='128,168 80,240 176,240 128,168'
|
||||||
style={{ filter: 'url("#sustainFilter")' }}
|
style={{ filter: 'url("#sustainFilter")' }}
|
||||||
/>
|
/>
|
||||||
<polyline
|
<polyline
|
||||||
id="stageTwo"
|
id="stageTwo"
|
||||||
points='0 0'
|
points='176,240 212,216 128,96 44,216 80,240'
|
||||||
style={{ filter: 'url("#sustainFilter")' }}
|
style={{ filter: 'url("#sustainFilter")' }}
|
||||||
/>
|
/>
|
||||||
<polyline
|
<polyline
|
||||||
id="stageThree"
|
id="stageThree"
|
||||||
points='0 0'
|
points='212,216 248,192 128,24 8,192 44,216'
|
||||||
style={{ filter: 'url("#sustainFilter")' }}
|
style={{ filter: 'url("#sustainFilter")' }}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
@ -54,7 +46,7 @@ class Sustain extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#sustain'],
|
targets: ['#sustain'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.8, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.8, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -62,17 +54,15 @@ class Sustain extends Component {
|
|||||||
|
|
||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#stageOne'],
|
targets: ['#stageOne'],
|
||||||
points: '128,168 80,240 176,240 128,168',
|
|
||||||
keyframes: [
|
keyframes: [
|
||||||
{
|
{
|
||||||
stroke: [COLOURS.GREEN, COLOURS.RED],
|
stroke: [COLOURS.GREEN, COLOURS.RED],
|
||||||
fill: [null, COLOURS.RED],
|
fill: [null, COLOURS.RED],
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.2,
|
delay: TIMES.TARGET_DURATION_MS * 0.2,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.6,
|
duration: TIMES.TARGET_DURATION_MS * 0.15,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -82,13 +72,11 @@ class Sustain extends Component {
|
|||||||
{
|
{
|
||||||
stroke: [COLOURS.GREEN, COLOURS.RED],
|
stroke: [COLOURS.GREEN, COLOURS.RED],
|
||||||
fill: [null, COLOURS.RED],
|
fill: [null, COLOURS.RED],
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.5,
|
delay: TIMES.TARGET_DURATION_MS * 0.35,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.6,
|
duration: TIMES.TARGET_DURATION_MS * 0.15,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
points: '176,240 212,216 128,96 44,216 80,240',
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -98,13 +86,11 @@ class Sustain extends Component {
|
|||||||
{
|
{
|
||||||
stroke: [COLOURS.GREEN, COLOURS.RED],
|
stroke: [COLOURS.GREEN, COLOURS.RED],
|
||||||
fill: [null, COLOURS.RED],
|
fill: [null, COLOURS.RED],
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.8,
|
delay: TIMES.TARGET_DURATION_MS * 0.5,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.4,
|
duration: TIMES.TARGET_DURATION_MS * 0.15,
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
points: '212,216 248,192 128,24 8,192 44,216',
|
|
||||||
delay: TIMES.TARGET_DELAY_MS,
|
|
||||||
duration: TIMES.TARGET_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -114,7 +100,7 @@ class Sustain extends Component {
|
|||||||
scale: 10,
|
scale: 10,
|
||||||
numOctaves: 5,
|
numOctaves: 5,
|
||||||
easing: 'easeOutSine',
|
easing: 'easeOutSine',
|
||||||
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 0.4,
|
delay: TIMES.TARGET_DURATION_MS * 0.55,
|
||||||
duration: TIMES.TARGET_DURATION_MS * 0.3 + TIMES.POST_SKILL_DURATION_MS,
|
duration: TIMES.TARGET_DURATION_MS * 0.3 + TIMES.POST_SKILL_DURATION_MS,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -127,8 +113,7 @@ class Sustain extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Sustain);
|
module.exports = Sustain;
|
||||||
|
|||||||
@ -6,13 +6,6 @@ const { connect } = require('preact-redux');
|
|||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
const { randomPoints } = require('../../utils');
|
const { randomPoints } = require('../../utils');
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function projectile(x, y, radius, colour) {
|
function projectile(x, y, radius, colour) {
|
||||||
return (
|
return (
|
||||||
<circle
|
<circle
|
||||||
@ -60,7 +53,7 @@ class Triage extends Component {
|
|||||||
this.animations.push(anime({
|
this.animations.push(anime({
|
||||||
targets: ['#triage'],
|
targets: ['#triage'],
|
||||||
opacity: [
|
opacity: [
|
||||||
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 1, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.6, duration: TIMES.TARGET_DURATION_MS * 0.2 },
|
||||||
],
|
],
|
||||||
easing: 'easeInOutSine',
|
easing: 'easeInOutSine',
|
||||||
@ -80,8 +73,7 @@ class Triage extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Triage);
|
module.exports = Triage;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { Component } = require('preact');
|
const { Component } = require('preact');
|
||||||
const anime = require('animejs').default;
|
const anime = require('animejs').default;
|
||||||
const { connect } = require('preact-redux');
|
|
||||||
|
|
||||||
const { TIMES, COLOURS } = require('../../constants');
|
const { TIMES, COLOURS } = require('../../constants');
|
||||||
const { randomPoints } = require('../../utils');
|
const { randomPoints } = require('../../utils');
|
||||||
@ -18,17 +17,9 @@ function projectile(x, y, radius, colour) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const { animCb } = state;
|
|
||||||
return { animCb };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
class TriageTick extends Component {
|
class TriageTick extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super();
|
super();
|
||||||
this.team = props.team;
|
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
const points = randomPoints(15, 10, { x: 0, y: 0, width: 300, height: 400 });
|
const points = randomPoints(15, 10, { x: 0, y: 0, width: 300, height: 400 });
|
||||||
this.charges = points.map(coord => projectile(coord[0], coord[1], 15, COLOURS.GREEN));
|
this.charges = points.map(coord => projectile(coord[0], coord[1], 15, COLOURS.GREEN));
|
||||||
@ -79,8 +70,7 @@ class TriageTick extends Component {
|
|||||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
this.animations[i].reset();
|
this.animations[i].reset();
|
||||||
}
|
}
|
||||||
this.props.animCb && this.props.animCb();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(TriageTick);
|
module.exports = TriageTick;
|
||||||
|
|||||||
@ -13,8 +13,8 @@ const { ConstructAnimation } = require('./animations');
|
|||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const { animSource, animTarget, animText } = state;
|
const { animating, animSource, animTarget, resolution, account } = state;
|
||||||
return { animSource, animTarget, animText };
|
return { animating, animSource, animTarget, resolution, account };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ class ConstructAvatar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClick() {
|
onClick() {
|
||||||
|
if (this.props.animating) return false;
|
||||||
return this.animations.push(wiggle(this.props.construct.id, this.idle));
|
return this.animations.push(wiggle(this.props.construct.id, this.idle));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,19 +63,24 @@ class ConstructAvatar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const { animSource, animTarget, animText, construct } = this.props;
|
const { animSource, animTarget, resolution, construct, account } = this.props;
|
||||||
// a different text object and text construct
|
// a different text object and text construct
|
||||||
if (animText && animText !== prevProps.animText && animText.constructId === construct.id) {
|
if (resolution && resolution !== prevProps.resolution && resolution.event[1].construct === construct.id) {
|
||||||
return wiggle(construct.id, this.idle);
|
const type = resolution.event[0];
|
||||||
|
// only trigger the wiggle on damage and ko events rather than spam it on everything
|
||||||
|
// also stops wiggle triggering when invert effect is applied
|
||||||
|
if (['Damage', 'Ko'].includes(type)) return wiggle(construct.id, this.idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// different source object and source construct
|
// different source object and source construct
|
||||||
if (animSource && animSource !== prevProps.animSource && animSource.constructId === construct.id) {
|
if (animSource && animSource !== prevProps.animSource && animSource.event[1].construct === construct.id) {
|
||||||
return sourceCast(animSource.constructId, animSource.direction, this.idle);
|
const { construct: constructId, player, direction: [x, y] } = animSource.event[1];
|
||||||
|
const animY = y && player === account.id ? -1 : y;
|
||||||
|
return sourceCast(constructId, { x, y: animY }, this.idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// different target object and target construct
|
// different target object and target construct
|
||||||
if (animTarget && animTarget !== prevProps.animTarget && animTarget.constructId.includes(construct.id)) {
|
if (animTarget && animTarget !== prevProps.animTarget && animTarget.event[1].construct.includes(construct.id)) {
|
||||||
switch (animTarget.skill) {
|
switch (animTarget.skill) {
|
||||||
case 'Banish': return banish(construct.id, this.idle);
|
case 'Banish': return banish(construct.id, this.idle);
|
||||||
case 'Invert': return invert(construct.id, this.idle);
|
case 'Invert': return invert(construct.id, this.idle);
|
||||||
@ -86,26 +92,23 @@ class ConstructAvatar extends Component {
|
|||||||
|
|
||||||
|
|
||||||
shouldComponentUpdate(newProps) {
|
shouldComponentUpdate(newProps) {
|
||||||
const { animSource, animTarget, animText, construct, mouseOver } = newProps;
|
const { animSource, animTarget, resolution, construct, mouseOver } = newProps;
|
||||||
if (animSource !== this.props.animSource) return true;
|
if (animSource !== this.props.animSource) return true;
|
||||||
if (animTarget !== this.props.animTarget) return true;
|
if (animTarget !== this.props.animTarget) return true;
|
||||||
if (animText !== this.props.animText) return true;
|
if (resolution !== this.props.resolution) return true;
|
||||||
if (construct !== this.props.construct) return true;
|
if (construct !== this.props.construct) return true;
|
||||||
if (mouseOver !== this.props.mouseOver) return true;
|
if (mouseOver !== this.props.mouseOver) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConstructText(props) {
|
function ConstructName(props) {
|
||||||
const { construct } = props;
|
const { construct } = props;
|
||||||
if (!construct) return false;
|
if (!construct) return false;
|
||||||
|
return <h3 class={'name'}><span>{construct.name}</span></h3>;
|
||||||
const text = construct.name;
|
|
||||||
|
|
||||||
return <h3 class={'name'}><span>{text}</span></h3>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ConstructAvatar: addState(ConstructAvatar),
|
ConstructAvatar: addState(ConstructAvatar),
|
||||||
ConstructText,
|
ConstructName,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const addState = connect(
|
|||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
ws,
|
ws,
|
||||||
|
authenticated,
|
||||||
account,
|
account,
|
||||||
game,
|
game,
|
||||||
instance,
|
instance,
|
||||||
@ -17,6 +18,7 @@ const addState = connect(
|
|||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
authenticated,
|
||||||
account,
|
account,
|
||||||
game,
|
game,
|
||||||
instance,
|
instance,
|
||||||
@ -28,6 +30,7 @@ const addState = connect(
|
|||||||
function Controls(args) {
|
function Controls(args) {
|
||||||
const {
|
const {
|
||||||
game,
|
game,
|
||||||
|
authenticated,
|
||||||
account,
|
account,
|
||||||
instance,
|
instance,
|
||||||
nav,
|
nav,
|
||||||
@ -38,6 +41,7 @@ function Controls(args) {
|
|||||||
|
|
||||||
if (game) return <GameCtrl />;
|
if (game) return <GameCtrl />;
|
||||||
if (instance) return <InstanceCtrl />;
|
if (instance) return <InstanceCtrl />;
|
||||||
|
if (!authenticated) return false;
|
||||||
if (nav === 'play' || nav === 'shop' || nav === 'reshape' || !nav) return <PlayCtrl />
|
if (nav === 'play' || nav === 'shop' || nav === 'reshape' || !nav) return <PlayCtrl />
|
||||||
if (nav === 'team' || nav === 'account') return <TeamCtrl />
|
if (nav === 'team' || nav === 'account') return <TeamCtrl />
|
||||||
|
|
||||||
|
|||||||
@ -1,190 +0,0 @@
|
|||||||
const { connect } = require('preact-redux');
|
|
||||||
const preact = require('preact');
|
|
||||||
|
|
||||||
// const actions = require('../actions');
|
|
||||||
const shapes = require('./shapes');
|
|
||||||
|
|
||||||
const { ConstructAvatar } = require('./construct');
|
|
||||||
// const { ConstructAnimation } = require('./animations');
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const {
|
|
||||||
account,
|
|
||||||
itemInfo,
|
|
||||||
demo,
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return {
|
|
||||||
account,
|
|
||||||
itemInfo,
|
|
||||||
demo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function receiveDispatch(dispatch) {
|
|
||||||
function setAnimTarget(anim) {
|
|
||||||
dispatch(actions.setAnimTarget(anim));
|
|
||||||
}
|
|
||||||
|
|
||||||
return { setAnimTarget };
|
|
||||||
} */
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
function Demo(args) {
|
|
||||||
const {
|
|
||||||
demo,
|
|
||||||
itemInfo,
|
|
||||||
account,
|
|
||||||
|
|
||||||
// setAnimTarget,
|
|
||||||
} = args;
|
|
||||||
|
|
||||||
if (!demo || !itemInfo.items.length || account) return false;
|
|
||||||
|
|
||||||
const { combiner, items, equipping, equipped, players, combo } = demo;
|
|
||||||
|
|
||||||
const vboxDemo = () => {
|
|
||||||
function stashBtn(i, j) {
|
|
||||||
if (!i) return <button disabled class='empty' > </button>;
|
|
||||||
const highlighted = combiner.indexOf(j) > -1;
|
|
||||||
const classes = `${highlighted ? 'highlight' : ''}`;
|
|
||||||
|
|
||||||
if (shapes[i]) {
|
|
||||||
return <button class={classes} key={j}>{shapes[i]()}</button>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <button class={classes}>{i}</button>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function combinerBtn() {
|
|
||||||
let text = '';
|
|
||||||
|
|
||||||
if (combiner.length < 3) {
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
if (combiner.length > i) {
|
|
||||||
text += '■ ';
|
|
||||||
} else {
|
|
||||||
text += '▫ ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
text = 'combine';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
class='vbox-btn'
|
|
||||||
disabled={combiner.length !== 3}>
|
|
||||||
{text}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stashElement() {
|
|
||||||
return (
|
|
||||||
<div class="vbox">
|
|
||||||
<div class='vbox-section'>
|
|
||||||
<h2 class='colour-info'>
|
|
||||||
VBOX PHASE {shapes.Red()} {shapes.Green()} {shapes.Blue()}
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
Combine colours with base skills and specialisations to build an array of powerful variants.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div> </div>
|
|
||||||
<div class='vbox-section'>
|
|
||||||
<div class='vbox-items'>
|
|
||||||
{items.map((i, j) => stashBtn(i, j))}
|
|
||||||
</div>
|
|
||||||
{combinerBtn()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="news vbox-demo">
|
|
||||||
{stashElement()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const vboxConstructs = () => {
|
|
||||||
const btnClass = equipping
|
|
||||||
? 'equipping empty gray'
|
|
||||||
: 'empty gray';
|
|
||||||
|
|
||||||
const constructEl = c => (
|
|
||||||
<div class="instance-construct">
|
|
||||||
<h2 class="name" >{c.name}</h2>
|
|
||||||
<ConstructAvatar construct={c} />
|
|
||||||
<div class="skills">
|
|
||||||
{equipped
|
|
||||||
? <button>{combo}</button>
|
|
||||||
: <button disabled={!equipping} class={btnClass}>SKILL</button>
|
|
||||||
}
|
|
||||||
<button disabled={!equipping} class={btnClass}>SKILL</button>
|
|
||||||
<button disabled={!equipping} class={btnClass}>SKILL</button>
|
|
||||||
</div>
|
|
||||||
<div class="specs">
|
|
||||||
</div>
|
|
||||||
<div class="stats">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section class="construct-section">
|
|
||||||
<div>
|
|
||||||
<h2>CONSTRUCTS</h2>
|
|
||||||
<p><b>Constructs</b> are the units you control. They are reset every game and their initial appearance is randomly generated.</p>
|
|
||||||
<p><b>Skills</b> and <b>Specs</b> you create in the <b>VBOX Phase</b> are equipped to your constructs to create a build.</p>
|
|
||||||
</div>
|
|
||||||
<div class='construct-list'>
|
|
||||||
{constructEl(players[0].constructs[0])}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const gameDemo = () => {
|
|
||||||
return (
|
|
||||||
<section class="game-demo">
|
|
||||||
<div>
|
|
||||||
<h2>COMBAT PHASE</h2>
|
|
||||||
<p>Battle your opponent using dynamic team builds from the VBOX phase.</p>
|
|
||||||
<p>The skills crafted can be used to damage the opponent or support your team.</p>
|
|
||||||
<p>Simultaneous turn based combat: each team picks targets for their skills during this phase.</p>
|
|
||||||
<p>The damage dealt by skills, cast order and construct life depend on your decisions in the VBOX phase.</p>
|
|
||||||
</div>
|
|
||||||
<div class="game">
|
|
||||||
<div class="game-construct">
|
|
||||||
<div class="left"></div>
|
|
||||||
<div class="right">
|
|
||||||
<ConstructAvatar construct={players[1].constructs[0]} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
<div class="game-construct">
|
|
||||||
<div class="left"></div>
|
|
||||||
<div class="right">
|
|
||||||
<ConstructAvatar construct={players[1].constructs[1]} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section class='demo news top'>
|
|
||||||
{gameDemo()}
|
|
||||||
{vboxDemo()}
|
|
||||||
{vboxConstructs()}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = addState(Demo);
|
|
||||||
85
client/src/components/front.page.jsx
Normal file
85
client/src/components/front.page.jsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// const { connect } = require('preact-redux');
|
||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
|
const { errorToast, infoToast } = require('../utils');
|
||||||
|
const actions = require('./../actions');
|
||||||
|
|
||||||
|
const VERSION = process.env.npm_package_version;
|
||||||
|
|
||||||
|
const Welcome = require('./welcome');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const {
|
||||||
|
ws,
|
||||||
|
account,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
function sendInstancePractice() {
|
||||||
|
ws.sendInstancePractice();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
sendInstancePractice,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function Play(args) {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
sendInstancePractice,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
const news = (
|
||||||
|
<div class="list">
|
||||||
|
<div class="intro">
|
||||||
|
<p> MNML is a turn-based 1v1 strategy game in an abstract setting. </p>
|
||||||
|
<p>
|
||||||
|
Build a unique team of 3 constructs from a range of skills and specialisations.<br />
|
||||||
|
Outplay your opponent across multiple rounds by adapting to an always shifting meta. <br />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="awards"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const list = () => {
|
||||||
|
return (
|
||||||
|
<div class='list play'>
|
||||||
|
<figure>
|
||||||
|
<button
|
||||||
|
class="ready"
|
||||||
|
onClick={() => sendInstancePractice()}>
|
||||||
|
Play
|
||||||
|
</button>
|
||||||
|
<figcaption>Learn MNML</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<button
|
||||||
|
class='discord-btn'
|
||||||
|
onClick={() => window.open('https://discord.gg/YJJgurM') }>
|
||||||
|
|
||||||
|
</button>
|
||||||
|
<figcaption>Join the Community</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<div class="logo"/>
|
||||||
|
<hr />
|
||||||
|
{list()}
|
||||||
|
<hr />
|
||||||
|
<Welcome />
|
||||||
|
<hr />
|
||||||
|
{news}
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Play);
|
||||||
89
client/src/components/game.construct.anim.text.jsx
Normal file
89
client/src/components/game.construct.anim.text.jsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const anime = require('animejs').default;
|
||||||
|
const reactStringReplace = require('react-string-replace');
|
||||||
|
|
||||||
|
const shapes = require('./shapes');
|
||||||
|
const { removeTier } = require('../utils');
|
||||||
|
const { TIMES } = require('./../constants');
|
||||||
|
|
||||||
|
const addState = connect(({ resolution, itemInfo }) => ({ resolution, itemInfo }));
|
||||||
|
|
||||||
|
class AnimText extends preact.Component {
|
||||||
|
shouldComponentUpdate(newProps) {
|
||||||
|
if (newProps.resolution !== this.props.resolution) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { resolution, construct } = this.props;
|
||||||
|
if (resolution && resolution !== prevProps.resolution && resolution.event[1].construct === construct.id) {
|
||||||
|
anime({
|
||||||
|
targets: '.combat-text',
|
||||||
|
top: '40%',
|
||||||
|
duration: TIMES.POST_SKILL_DURATION_MS - 500,
|
||||||
|
easing: 'easeOutQuad',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { construct, resolution, itemInfo } = this.props;
|
||||||
|
if (resolution && resolution.event[1].construct === construct.id) {
|
||||||
|
const itemSourceDescription = () => {
|
||||||
|
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(resolution.skill));
|
||||||
|
const itemSourceInfo = itemSource.length
|
||||||
|
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
|
||||||
|
: false;
|
||||||
|
const itemRegEx = /(Red|Blue|Green)/;
|
||||||
|
return reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateAnimText = () => {
|
||||||
|
const [type, event] = resolution.event;
|
||||||
|
switch (type) {
|
||||||
|
case 'Damage': {
|
||||||
|
const { amount, mitigation, colour } = event;
|
||||||
|
const mitigationText = mitigation ? `(${mitigation})` : '';
|
||||||
|
return <h1><span class={colour.toLowerCase()}>-{amount} {mitigationText} </span></h1>;
|
||||||
|
}
|
||||||
|
case 'Healing': {
|
||||||
|
const { amount, overhealing, colour } = event;
|
||||||
|
const overHealingText = overhealing ? `(${overhealing} OH)` : '';
|
||||||
|
return <h1><span class={colour.toLowerCase()}>+{amount} {overHealingText}</span></h1>;
|
||||||
|
}
|
||||||
|
case 'Effect': {
|
||||||
|
const { effect, duration } = event;
|
||||||
|
return <h1><span>+{effect} {duration}T</span></h1>;
|
||||||
|
}
|
||||||
|
case 'Removal': {
|
||||||
|
const { effect } = event;
|
||||||
|
if (!effect) return <h1><span>Effect Removal</span></h1>;
|
||||||
|
return <h1><span>-{effect}</span></h1>;
|
||||||
|
}
|
||||||
|
case 'Ko': return <h1><span>KO!</span></h1>;
|
||||||
|
case 'Reflection': return <h1><span>REFLECT</span></h1>;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We don't send inversion / disable / immune event text
|
||||||
|
/* case 'Inversion': return <h1><span>INVERT</span></h1>;
|
||||||
|
case 'Disable': {
|
||||||
|
const { disable } = event;
|
||||||
|
return <h1><span>{disable}</span></h1>;
|
||||||
|
}
|
||||||
|
case 'Immunity': return <h1><span>IMMUNE</span></h1>; */
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="combat-text">
|
||||||
|
<h2><span>{resolution.skill}</span></h2>
|
||||||
|
<span>{itemSourceDescription()}</span>
|
||||||
|
{generateAnimText()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(AnimText);
|
||||||
73
client/src/components/game.construct.effect.box.jsx
Normal file
73
client/src/components/game.construct.effect.box.jsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const reactStringReplace = require('react-string-replace');
|
||||||
|
|
||||||
|
const actions = require('../actions');
|
||||||
|
const shapes = require('./shapes');
|
||||||
|
const { INFO } = require('./../constants');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
({ resolution, itemInfo, gameSkillInfo }) => ({ resolution, itemInfo, gameSkillInfo }),
|
||||||
|
|
||||||
|
function receiveDispatch(dispatch) {
|
||||||
|
function setGameEffectInfo(info) {
|
||||||
|
dispatch(actions.setGameEffectInfo(info));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { setGameEffectInfo };
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
class GameConstructEffects extends preact.Component {
|
||||||
|
shouldComponentUpdate(newProps) {
|
||||||
|
if (newProps.resolution && newProps.resolution !== this.props.resolution) {
|
||||||
|
const [type, info] = newProps.resolution.event;
|
||||||
|
if (info.construct === this.props.construct.id
|
||||||
|
&& (type === 'Effect' || type === 'Removal')) return true;
|
||||||
|
}
|
||||||
|
if (newProps.construct !== this.props.construct) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
resolution,
|
||||||
|
construct,
|
||||||
|
gameSkillInfo,
|
||||||
|
setGameEffectInfo,
|
||||||
|
itemInfo,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
function hoverInfo(e, info) {
|
||||||
|
e.stopPropagation();
|
||||||
|
return setGameEffectInfo(info);
|
||||||
|
}
|
||||||
|
if (gameSkillInfo && gameSkillInfo.constructId === construct.id) {
|
||||||
|
const fullInfo = itemInfo.items.find(k => k.item === gameSkillInfo.skill) || INFO[gameSkillInfo.skill];
|
||||||
|
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
|
||||||
|
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
|
||||||
|
const speed = <span> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </span>;
|
||||||
|
return (
|
||||||
|
<div class="skill-description">
|
||||||
|
<h2><span> {gameSkillInfo.skill} </span></h2>
|
||||||
|
<span>{infoDescription} </span> <br />
|
||||||
|
{speed}
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
const effects = resolution ? resolution.event[1].display.effects : construct.effects;
|
||||||
|
|
||||||
|
const renderEffects = effects.length
|
||||||
|
? effects.map(c =>
|
||||||
|
<div key={c.effect}>
|
||||||
|
<span key={c.effect} onMouseOver={e => hoverInfo(e, c)}
|
||||||
|
onMouseOut={e => hoverInfo(e, null)}> {c.effect} - {c.duration}T
|
||||||
|
</span>
|
||||||
|
</div>)
|
||||||
|
: null;
|
||||||
|
return (<div class="effects"> {renderEffects} </div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(GameConstructEffects);
|
||||||
@ -1,95 +1,23 @@
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
const anime = require('animejs').default;
|
|
||||||
const range = require('lodash/range');
|
const range = require('lodash/range');
|
||||||
const reactStringReplace = require('react-string-replace');
|
|
||||||
|
|
||||||
const { STATS, removeTier } = require('../utils');
|
const { ConstructAvatar, ConstructName } = require('./construct');
|
||||||
const { ConstructAvatar, ConstructText } = require('./construct');
|
|
||||||
const shapes = require('./shapes');
|
|
||||||
const { INFO, TIMES } = require('./../constants');
|
|
||||||
const actions = require('../actions');
|
|
||||||
|
|
||||||
const SkillBtn = require('./skill.btn');
|
const SkillBtn = require('./game.construct.skill.btn');
|
||||||
|
const ConstructAnimationText = require('./game.construct.anim.text');
|
||||||
const addStateText = connect(({ animText, itemInfo }) => ({ animText, itemInfo }));
|
const ConstructLife = require('./game.construct.life');
|
||||||
|
const ConstructEffectBox = require('./game.construct.effect.box');
|
||||||
class combatText extends preact.Component {
|
|
||||||
shouldComponentUpdate(newProps) {
|
|
||||||
if (newProps.animText !== this.props.animText) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const { animText, construct } = this.props;
|
|
||||||
if (animText && animText !== prevProps.animText && animText.constructId === construct.id) {
|
|
||||||
anime({
|
|
||||||
targets: '.combat-text',
|
|
||||||
top: '40%',
|
|
||||||
duration: TIMES.POST_SKILL_DURATION_MS - 500,
|
|
||||||
easing: 'easeOutQuad',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render(props) {
|
|
||||||
const { construct, animText, itemInfo } = props;
|
|
||||||
if (animText && animText.constructId === construct.id) {
|
|
||||||
const itemSourceDescription = () => {
|
|
||||||
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.skill));
|
|
||||||
const itemSourceInfo = itemSource.length
|
|
||||||
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
|
|
||||||
: false;
|
|
||||||
const itemRegEx = /(Red|Blue|Green)/;
|
|
||||||
return reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
|
|
||||||
};
|
|
||||||
|
|
||||||
const animationTextHtml = () => {
|
|
||||||
// monkaW hack to make red / blue recharge work nicely
|
|
||||||
if (animText.css === 'rb') {
|
|
||||||
const text = animText.text.split(' ');
|
|
||||||
return (
|
|
||||||
<h1>
|
|
||||||
<span class="red">{text[0]}</span>
|
|
||||||
<span class="blue">{text[1]}</span>
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<h1 class={animText.css}>
|
|
||||||
<span>{animText.text}</span>
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="combat-text">
|
|
||||||
<h2><span>{animText.skill}</span></h2>
|
|
||||||
<span>{itemSourceDescription()}</span>
|
|
||||||
{animationTextHtml()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ConstructAnimationText = addStateText(combatText);
|
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
ws,
|
ws,
|
||||||
game,
|
game,
|
||||||
account,
|
|
||||||
activeSkill,
|
activeSkill,
|
||||||
animFocus,
|
animFocus,
|
||||||
animating,
|
resolution,
|
||||||
animText,
|
|
||||||
gameSkillInfo,
|
|
||||||
itemInfo,
|
|
||||||
tutorialGame,
|
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function selectSkillTarget(targetConstructId) {
|
function selectSkillTarget(targetConstructId) {
|
||||||
@ -100,65 +28,23 @@ const addState = connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
game,
|
|
||||||
account,
|
|
||||||
animating,
|
|
||||||
animFocus,
|
|
||||||
animText,
|
|
||||||
activeSkill,
|
activeSkill,
|
||||||
|
animFocus,
|
||||||
|
resolution,
|
||||||
selectSkillTarget,
|
selectSkillTarget,
|
||||||
gameSkillInfo,
|
|
||||||
itemInfo,
|
|
||||||
tutorialGame,
|
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
function receiveDispatch(dispatch) {
|
|
||||||
function setGameEffectInfo(info) {
|
|
||||||
dispatch(actions.setGameEffectInfo(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTutorialGameClear(activeSkill, tutorialGame) {
|
|
||||||
if (activeSkill && tutorialGame) dispatch(actions.setTutorialGame(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
return { setGameEffectInfo, setTutorialGameClear };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const eventClasses = (animating, animFocus, construct, postSkill) => {
|
|
||||||
if (!animating) return '';
|
|
||||||
if (!postSkill) {
|
|
||||||
if (animFocus.includes(construct.id)) return '';
|
|
||||||
return 'unfocus';
|
|
||||||
}
|
|
||||||
if (postSkill.constructId !== construct.id) {
|
|
||||||
if (animFocus.includes(construct.id)) return '';
|
|
||||||
return 'unfocus';
|
|
||||||
}
|
|
||||||
if (postSkill.effects) construct.effects = postSkill.effects;
|
|
||||||
construct.green_life.value = postSkill.life.green;
|
|
||||||
construct.red_life.value = postSkill.life.red;
|
|
||||||
construct.blue_life.value = postSkill.life.blue;
|
|
||||||
return postSkill.css;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GameConstruct extends preact.Component {
|
class GameConstruct extends preact.Component {
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.resolvedLength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(newProps) {
|
shouldComponentUpdate(newProps) {
|
||||||
if (newProps.activeSkill !== this.props.activeSkill) return true;
|
if (newProps.activeSkill !== this.props.activeSkill) return true;
|
||||||
if (newProps.animFocus !== this.props.animFocus) return true;
|
if (newProps.animFocus !== this.props.animFocus) return true;
|
||||||
if (newProps.animText !== this.props.animText) return true;
|
|
||||||
if (newProps.animating !== this.props.animating) return true;
|
|
||||||
if (newProps.construct !== this.props.construct) return true;
|
if (newProps.construct !== this.props.construct) return true;
|
||||||
if (newProps.player !== this.props.player) return true;
|
if (newProps.resolution && newProps.resolution !== this.props.resolution) {
|
||||||
if (newProps.tutorialGame !== this.props.tutorialGame) return true;
|
const [type, variant] = newProps.resolution.event;
|
||||||
if (newProps.gameSkillInfo !== this.props.gameSkillInfo) return true;
|
if (variant.construct === this.props.construct.id && type === 'Ko') return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,84 +53,46 @@ class GameConstruct extends preact.Component {
|
|||||||
// Changing state variables
|
// Changing state variables
|
||||||
activeSkill,
|
activeSkill,
|
||||||
animFocus,
|
animFocus,
|
||||||
animText,
|
resolution,
|
||||||
animating,
|
selectSkillTarget,
|
||||||
construct,
|
construct,
|
||||||
player,
|
player,
|
||||||
tutorialGame,
|
|
||||||
gameSkillInfo,
|
|
||||||
// Constants
|
|
||||||
i,
|
|
||||||
itemInfo,
|
|
||||||
// Functions
|
|
||||||
selectSkillTarget,
|
|
||||||
setTutorialGameClear,
|
|
||||||
setGameEffectInfo,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const koEvent = animText ? animText.text === 'KO!' && animText.constructId === construct.id : false;
|
// construct green_life comes from game state and won't update during animations
|
||||||
const ko = construct.green_life.value === 0 && !koEvent ? 'ko' : '';
|
// treat the construct as ko for the remainder of the anims if ko event occurs
|
||||||
const classes = eventClasses(animating, animFocus, construct, animText);
|
const ko = construct.green_life.value === 0 || this.ko ? 'ko' : '';
|
||||||
const cssClass = ['ko-transition', 'unfocus'].includes(classes) ? classes : null;
|
const koEvent = () => {
|
||||||
|
if (resolution) {
|
||||||
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
const [type, variant] = resolution.event;
|
||||||
<div key={j} alt={STATS[s].stat}>
|
if (variant.construct === construct.id && type === 'Ko') {
|
||||||
{shapes[s]()}
|
this.ko = true;
|
||||||
<div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
|
return 'ko-transition';
|
||||||
<div class="value" >{construct[STATS[s].stat].value}</div>
|
}
|
||||||
</div>
|
|
||||||
));
|
|
||||||
|
|
||||||
const skills = range(0, 3)
|
|
||||||
.map(j => <SkillBtn key={j} construct={construct} i={j} j={i} animating={animating} />);
|
|
||||||
|
|
||||||
let crypSkills = <div></div>;
|
|
||||||
if (player) crypSkills = (<div class="skills"> {skills} </div>);
|
|
||||||
|
|
||||||
function hoverInfo(e, info) {
|
|
||||||
e.stopPropagation();
|
|
||||||
return setGameEffectInfo(info);
|
|
||||||
}
|
|
||||||
const effectBox = () => {
|
|
||||||
if (gameSkillInfo && gameSkillInfo.constructId === construct.id) {
|
|
||||||
const fullInfo = itemInfo.items.find(k => k.item === gameSkillInfo.skill) || INFO[gameSkillInfo.skill];
|
|
||||||
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
|
|
||||||
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
|
|
||||||
const speed = <span> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </span>;
|
|
||||||
return (
|
|
||||||
<div class="skill-description">
|
|
||||||
<h2><span> {gameSkillInfo.skill} </span></h2>
|
|
||||||
<span>{infoDescription} </span> <br />
|
|
||||||
{speed}
|
|
||||||
</div>);
|
|
||||||
}
|
}
|
||||||
const effects = construct.effects.length
|
return '';
|
||||||
? construct.effects.map(c =>
|
|
||||||
<div key={c.effect}>
|
|
||||||
<span key={c.effect} onMouseOver={e => hoverInfo(e, c)}
|
|
||||||
onMouseOut={e => hoverInfo(e, null)}> {c.effect} - {c.duration}T
|
|
||||||
</span>
|
|
||||||
</div>)
|
|
||||||
: null;
|
|
||||||
return (<div class="effects"> {effects} </div>);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unfocus = animFocus && !animFocus.includes(construct.id) ? 'unfocus' : '';
|
||||||
|
|
||||||
|
const crypSkills = player
|
||||||
|
? <div class="skills"> {range(0, 3).map(j => <SkillBtn key={j} construct={construct} i={j} />)} </div>
|
||||||
|
: <div></div>;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => selectSkillTarget(construct.id)}
|
||||||
selectSkillTarget(construct.id);
|
|
||||||
setTutorialGameClear(activeSkill, tutorialGame);
|
|
||||||
}}
|
|
||||||
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
||||||
class={`game-construct ${ko} ${cssClass}`}>
|
class={`game-construct ${ko} ${koEvent()} ${unfocus}`}>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
{crypSkills}
|
{crypSkills}
|
||||||
{effectBox()}
|
<ConstructEffectBox construct={construct} />
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="stats"> {stats} </div>
|
<ConstructLife construct={construct} />
|
||||||
<ConstructAvatar construct={construct} />
|
<ConstructAvatar construct={construct} />
|
||||||
<ConstructText construct={construct} />
|
<ConstructName construct={construct} />
|
||||||
<ConstructAnimationText construct={construct} />
|
<ConstructAnimationText construct={construct} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
49
client/src/components/game.construct.life.jsx
Normal file
49
client/src/components/game.construct.life.jsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
|
const shapes = require('./shapes');
|
||||||
|
|
||||||
|
const addState = connect(({ resolution }) => ({ resolution }));
|
||||||
|
|
||||||
|
class GameConstructLife extends preact.Component {
|
||||||
|
shouldComponentUpdate(newProps) {
|
||||||
|
if (newProps.resolution && newProps.resolution !== this.props.resolution) {
|
||||||
|
const [type, variant] = newProps.resolution.event;
|
||||||
|
if (variant.construct === this.props.construct.id
|
||||||
|
&& (type === 'Damage' || type === 'Healing')) return true;
|
||||||
|
}
|
||||||
|
if (newProps.construct !== this.props.construct) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { construct, resolution } = this.props;
|
||||||
|
const lifeBars = (redLife, greenLife, blueLife) => {
|
||||||
|
return (
|
||||||
|
<div class="stats">
|
||||||
|
<div>
|
||||||
|
{shapes.RedLife()}
|
||||||
|
<div class="max" >{redLife} / {construct.red_life.max}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{shapes.GreenLife()}
|
||||||
|
<div class="max" >{greenLife} / {construct.green_life.max}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{shapes.BlueLife()}
|
||||||
|
<div class="max" >{blueLife} / {construct.blue_life.max}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (resolution) {
|
||||||
|
const { red, blue, green } = resolution.event[1].display;
|
||||||
|
return lifeBars(red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lifeBars(construct.red_life.value, construct.green_life.value, construct.blue_life.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(GameConstructLife);
|
||||||
@ -10,11 +10,13 @@ const addState = connect(
|
|||||||
const {
|
const {
|
||||||
activeSkill,
|
activeSkill,
|
||||||
game,
|
game,
|
||||||
|
animating,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activeSkill,
|
activeSkill,
|
||||||
game,
|
game,
|
||||||
|
animating,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -8,6 +8,7 @@ const addState = connect(
|
|||||||
const {
|
const {
|
||||||
ws,
|
ws,
|
||||||
account,
|
account,
|
||||||
|
authenticated,
|
||||||
nav,
|
nav,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ const addState = connect(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
|
authenticated,
|
||||||
nav,
|
nav,
|
||||||
|
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
@ -48,6 +50,7 @@ const addState = connect(
|
|||||||
function Header(args) {
|
function Header(args) {
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
|
authenticated,
|
||||||
nav,
|
nav,
|
||||||
|
|
||||||
sendAccountStates,
|
sendAccountStates,
|
||||||
@ -56,6 +59,8 @@ function Header(args) {
|
|||||||
|
|
||||||
if (!account) return false;
|
if (!account) return false;
|
||||||
|
|
||||||
|
if (!authenticated) return false;
|
||||||
|
|
||||||
function navTo(p) {
|
function navTo(p) {
|
||||||
return setNav(p);
|
return setNav(p);
|
||||||
}
|
}
|
||||||
@ -68,11 +73,6 @@ function Header(args) {
|
|||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<button
|
|
||||||
onClick={() => navTo('play')}
|
|
||||||
class='logo login-btn'>
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
onClick={() => navTo('play')}
|
onClick={() => navTo('play')}
|
||||||
class={`login-btn ${nav === 'play' ? 'highlight' : ''}`}>
|
class={`login-btn ${nav === 'play' ? 'highlight' : ''}`}>
|
||||||
|
|||||||
@ -23,6 +23,7 @@ const addState = connect(
|
|||||||
function Top(args) {
|
function Top(args) {
|
||||||
const {
|
const {
|
||||||
nav,
|
nav,
|
||||||
|
authenticated,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
if (nav === 'account') return <AccountTop />;
|
if (nav === 'account') return <AccountTop />;
|
||||||
|
|||||||
@ -4,27 +4,38 @@ const { connect } = require('preact-redux');
|
|||||||
const Main = require('./main');
|
const Main = require('./main');
|
||||||
// const Nav = require('./nav');
|
// const Nav = require('./nav');
|
||||||
const Controls = require('./controls');
|
const Controls = require('./controls');
|
||||||
|
const FrontPage = require('./front.page');
|
||||||
|
const Noise = require('./noise');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
({ game, instance }) => ({ game, instance })
|
({ game, instance, authenticated }) => ({ game, instance, authenticated })
|
||||||
);
|
);
|
||||||
|
|
||||||
function Mnml(args) {
|
function Mnml(args) {
|
||||||
const {
|
const {
|
||||||
game,
|
game,
|
||||||
instance,
|
instance,
|
||||||
|
authenticated,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
const rotateClass = (game || instance) && window.innerHeight < 900 && window.innerWidth < window.innerHeight
|
const rotateClass = (game || instance) && window.innerHeight < 900 && window.innerWidth < window.innerHeight
|
||||||
? 'show'
|
? 'show'
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
if (!authenticated && !instance && !game) return (
|
||||||
|
<div id="mnml" class='front-page'>
|
||||||
|
<Noise />
|
||||||
|
<FrontPage />
|
||||||
|
<div id="rotate" class={rotateClass} ></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="mnml">
|
<div id="mnml">
|
||||||
<Main />
|
<Main />
|
||||||
<Controls />
|
<Controls />
|
||||||
<div id="rotate" class={rotateClass} >
|
<Noise />
|
||||||
</div>
|
<div id="rotate" class={rotateClass} ></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
75
client/src/components/noise.jsx
Normal file
75
client/src/components/noise.jsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { Component } = require('preact');
|
||||||
|
const anime = require('animejs').default;
|
||||||
|
|
||||||
|
class Noise extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.animations = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
id="noise"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 400 400">
|
||||||
|
<filter id='noiseFilter'>
|
||||||
|
<feTurbulence type="turbulence" baseFrequency="0.2" numOctaves="2" result="turbulence"></feTurbulence>
|
||||||
|
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="2" xChannelSelector="R" yChannelSelector="G"></feDisplacementMap>
|
||||||
|
</filter>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.animations.push(anime({
|
||||||
|
targets: ['#noiseFilter feTurbulence', '#noiseFilter feDisplacementMap'],
|
||||||
|
easing: 'linear',
|
||||||
|
loop: true,
|
||||||
|
keyframes: [
|
||||||
|
{
|
||||||
|
baseFrequency: 0.5,
|
||||||
|
duration: () => anime.random(1000, 2000),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.animations.push(anime({
|
||||||
|
targets: ['#noiseFilter feDisplacementMap'],
|
||||||
|
easing: 'linear',
|
||||||
|
loop: true,
|
||||||
|
keyframes: [
|
||||||
|
{
|
||||||
|
scale: 2,
|
||||||
|
duration: () => anime.random(2000, 5000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scale: 4,
|
||||||
|
duration: () => anime.random(150, 250),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scale: 2,
|
||||||
|
duration: () => anime.random(100, 150),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scale: 4,
|
||||||
|
duration: () => anime.random(150, 250),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is necessary because
|
||||||
|
// skipping / timing / unmounting race conditions
|
||||||
|
// can cause the animations to cut short, this will ensure the values are reset
|
||||||
|
// because preact will recycle all these components
|
||||||
|
componentWillUnmount() {
|
||||||
|
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||||
|
this.animations[i].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Noise;
|
||||||
@ -6,11 +6,11 @@ const reactStringReplace = require('react-string-replace');
|
|||||||
const throttle = require('lodash/throttle');
|
const throttle = require('lodash/throttle');
|
||||||
|
|
||||||
const shapes = require('./shapes');
|
const shapes = require('./shapes');
|
||||||
const { effectInfo, removeTier } = require('../utils');
|
const { effectInfo } = require('../utils');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
({ game, account, animSkill, animating, itemInfo, gameEffectInfo, tutorialGame }) =>
|
({ game, account, animating, itemInfo, gameEffectInfo, tutorialGame }) =>
|
||||||
({ game, account, animSkill, animating, itemInfo, gameEffectInfo, tutorialGame })
|
({ game, account, animating, itemInfo, gameEffectInfo, tutorialGame })
|
||||||
);
|
);
|
||||||
|
|
||||||
class TargetSvg extends Component {
|
class TargetSvg extends Component {
|
||||||
@ -31,7 +31,6 @@ class TargetSvg extends Component {
|
|||||||
if (newProps.game !== this.props.game) return true;
|
if (newProps.game !== this.props.game) return true;
|
||||||
if (newProps.account !== this.props.account) return true;
|
if (newProps.account !== this.props.account) return true;
|
||||||
if (newProps.animating !== this.props.animating) return true;
|
if (newProps.animating !== this.props.animating) return true;
|
||||||
if (newProps.animSkill !== this.props.animSkill) return true;
|
|
||||||
if (newProps.gameEffectInfo !== this.props.gameEffectInfo) return true;
|
if (newProps.gameEffectInfo !== this.props.gameEffectInfo) return true;
|
||||||
if (newProps.tutorialGame !== this.props.tutorialGame) return true;
|
if (newProps.tutorialGame !== this.props.tutorialGame) return true;
|
||||||
if (newState.width !== this.state.width) return true;
|
if (newState.width !== this.state.width) return true;
|
||||||
@ -44,12 +43,9 @@ class TargetSvg extends Component {
|
|||||||
// Changing State Variables
|
// Changing State Variables
|
||||||
account,
|
account,
|
||||||
animating,
|
animating,
|
||||||
animSkill,
|
|
||||||
game,
|
game,
|
||||||
gameEffectInfo,
|
gameEffectInfo,
|
||||||
tutorialGame,
|
tutorialGame,
|
||||||
// Static
|
|
||||||
itemInfo,
|
|
||||||
} = props;
|
} = props;
|
||||||
const { width, height } = state;
|
const { width, height } = state;
|
||||||
|
|
||||||
@ -87,14 +83,14 @@ class TargetSvg extends Component {
|
|||||||
const otherTeam = game.players.find(t => t.id !== account.id);
|
const otherTeam = game.players.find(t => t.id !== account.id);
|
||||||
|
|
||||||
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
||||||
const outgoing = game.stack.filter(stack => playerTeamIds.includes(stack.source_construct_id));
|
const outgoing = game.stack.filter(stack => stack.player === account.id);
|
||||||
|
|
||||||
function getPath(cast) {
|
function getPath(cast) {
|
||||||
const source = playerTeam.constructs.findIndex(c => c.id === cast.source_construct_id);
|
const source = playerTeam.constructs.findIndex(c => c.id === cast.source);
|
||||||
const defensive = playerTeamIds.includes(cast.target_construct_id);
|
const defensive = playerTeamIds.includes(cast.target);
|
||||||
const target = defensive
|
const target = defensive
|
||||||
? playerTeam.constructs.findIndex(c => c.id === cast.target_construct_id)
|
? playerTeam.constructs.findIndex(c => c.id === cast.target)
|
||||||
: otherTeam.constructs.findIndex(c => c.id === cast.target_construct_id);
|
: otherTeam.constructs.findIndex(c => c.id === cast.target);
|
||||||
|
|
||||||
const skillNumber = window.innerWidth <= 800 // mobile styling trigger
|
const skillNumber = window.innerWidth <= 800 // mobile styling trigger
|
||||||
? playerTeam.constructs[source].skills.findIndex(s => s.skill === cast.skill)
|
? playerTeam.constructs[source].skills.findIndex(s => s.skill === cast.skill)
|
||||||
|
|||||||
@ -71,7 +71,6 @@ class Combos extends preact.Component {
|
|||||||
<div class="combos">
|
<div class="combos">
|
||||||
<div class="combo-header">
|
<div class="combo-header">
|
||||||
<h2>COMBOS</h2>
|
<h2>COMBOS</h2>
|
||||||
Combine colours and items.
|
|
||||||
</div>
|
</div>
|
||||||
<div class="combo-list"
|
<div class="combo-list"
|
||||||
onMouseOver={e => e.stopPropagation()}
|
onMouseOver={e => e.stopPropagation()}
|
||||||
|
|||||||
@ -5,10 +5,9 @@ const Login = require('./welcome.login');
|
|||||||
const Register = require('./welcome.register');
|
const Register = require('./welcome.register');
|
||||||
const Help = require('./welcome.help');
|
const Help = require('./welcome.help');
|
||||||
// const About = require('./welcome.about');
|
// const About = require('./welcome.about');
|
||||||
const Demo = require('./demo');
|
|
||||||
|
|
||||||
function Welcome() {
|
function Welcome() {
|
||||||
const page = this.state.page || 'register';
|
const page = this.state.page || 'login';
|
||||||
|
|
||||||
const pageEl = () => {
|
const pageEl = () => {
|
||||||
if (page === 'login') return <Login />;
|
if (page === 'login') return <Login />;
|
||||||
@ -17,65 +16,32 @@ function Welcome() {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const news = (
|
const form = <div>{pageEl()}</div>;
|
||||||
<div class="news">
|
|
||||||
<p> Welcome to mnml.</p>
|
|
||||||
|
|
||||||
<p> MNML is a turn-based 1v1 strategy game in an abstract setting. </p>
|
|
||||||
<p>
|
|
||||||
Build a unique team of 3 constructs from a range of skills and specialisations.<br />
|
|
||||||
Outplay your opponent in multiple rounds by adapting to an always shifting meta. <br />
|
|
||||||
Simple rules, complex interactions and unique mechanics.<br />
|
|
||||||
</p>
|
|
||||||
<p> Free to play, no pay to win. Register to start playing.<br /></p>
|
|
||||||
|
|
||||||
<a href='https://www.youtube.com/watch?v=VtZLlkpJuS8'>Tutorial Playthrough on YouTube</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const main = (['login', 'register', 'help'].includes(page))
|
|
||||||
? <section>{news}{pageEl()}</section>
|
|
||||||
: <Demo />;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main class="menu welcome">
|
<header>
|
||||||
<header>
|
<div class="options">
|
||||||
<div class="options">
|
<button
|
||||||
<button
|
class={`login-btn ${page === 'login' ? 'highlight' : ''}`}
|
||||||
onClick={() => this.setState({ page: 'login' })}
|
disabled={page === 'login'}
|
||||||
class='logo login-btn'>
|
onClick={() => this.setState({ page: 'login' })}>
|
||||||
|
Login
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class={`login-btn ${page === 'login' ? 'highlight' : ''}`}
|
class={`login-btn ${page === 'register' ? 'highlight' : ''}`}
|
||||||
disabled={page === 'login'}
|
disabled={page === 'register'}
|
||||||
onClick={() => this.setState({ page: 'login' })}>
|
onClick={() => this.setState({ page: 'register' })}>
|
||||||
Login
|
Register
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class={`login-btn ${page === 'register' ? 'highlight' : ''}`}
|
class={`login-btn ${page === 'help' ? 'highlight' : ''}`}
|
||||||
disabled={page === 'register'}
|
disabled={page === 'help'}
|
||||||
onClick={() => this.setState({ page: 'register' })}>
|
onClick={() => this.setState({ page: 'help' })}>
|
||||||
Register
|
Help
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
class={`login-btn ${page === 'info' ? 'highlight' : ''}`}
|
|
||||||
disabled={page === 'info'}
|
|
||||||
onClick={() => this.setState({ page: 'info' })}>
|
|
||||||
Info
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class={`login-btn ${page === 'help' ? 'highlight' : ''}`}
|
|
||||||
disabled={page === 'help'}
|
|
||||||
onClick={() => this.setState({ page: 'help' })}>
|
|
||||||
Help
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div class="top">
|
|
||||||
{main}
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
{form}
|
||||||
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,7 @@ const eachSeries = require('async/eachSeries');
|
|||||||
const sample = require('lodash/sample');
|
const sample = require('lodash/sample');
|
||||||
|
|
||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { setAnimations, clearAnimations } = require('./animations.utils');
|
||||||
const animations = require('./animations.utils');
|
|
||||||
const { infoToast, errorToast } = require('./utils');
|
const { infoToast, errorToast } = require('./utils');
|
||||||
const { tutorialVbox } = require('./tutorial.utils');
|
const { tutorialVbox } = require('./tutorial.utils');
|
||||||
|
|
||||||
@ -28,10 +27,13 @@ function registerEvents(store) {
|
|||||||
|
|
||||||
function clearTutorial() {
|
function clearTutorial() {
|
||||||
store.dispatch(actions.setTutorial(null));
|
store.dispatch(actions.setTutorial(null));
|
||||||
localStorage.setItem('tutorial-complete', true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clearTutorialGame() {
|
||||||
|
store.dispatch(actions.setTutorialGame(null));
|
||||||
|
}
|
||||||
|
|
||||||
function setPing(ping) {
|
function setPing(ping) {
|
||||||
store.dispatch(actions.setPing(ping));
|
store.dispatch(actions.setPing(ping));
|
||||||
}
|
}
|
||||||
@ -73,67 +75,23 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setGame(game) {
|
function setGame(game) {
|
||||||
const { game: currentGame, account, ws, animating } = store.getState();
|
const { game: currentGame, ws, animating } = store.getState();
|
||||||
|
|
||||||
if (animating) return false;
|
if (animating) return false;
|
||||||
|
|
||||||
if (game && currentGame) {
|
if (game && currentGame) {
|
||||||
if (game.resolved.length !== currentGame.resolved.length) {
|
if (game.resolutions.length !== currentGame.resolutions.length) {
|
||||||
store.dispatch(actions.setAnimating(true));
|
store.dispatch(actions.setAnimating(true));
|
||||||
store.dispatch(actions.setGameSkillInfo(null));
|
store.dispatch(actions.setGameSkillInfo(null));
|
||||||
// stop fetching the game state til animations are done
|
// stop fetching the game state til animations are done
|
||||||
const newRes = game.resolved.slice(currentGame.resolved.length);
|
const newRes = game.resolutions[game.resolutions.length - 1];
|
||||||
return eachSeries(newRes, (r, cb) => {
|
return eachSeries(newRes, (r, cb) => {
|
||||||
if (!r.event) return cb();
|
if (r.delay === 0) return cb(); // TargetKo etc
|
||||||
let timeout = animations.getTime(r.stages);
|
setAnimations(r, store);
|
||||||
const anims = animations.getObjects(r, game, account);
|
return setTimeout(cb, r.delay);
|
||||||
const text = animations.getText(r);
|
|
||||||
store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r, game)));
|
|
||||||
if (anims.animSkill) store.dispatch(actions.setAnimSkill(anims.animSkill));
|
|
||||||
|
|
||||||
if (r.stages.includes('START_SKILL') && anims.animSource) {
|
|
||||||
store.dispatch(actions.setAnimSource(anims.animSource));
|
|
||||||
store.dispatch(actions.setAnimText(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.stages.includes('END_SKILL') && anims.animTarget) {
|
|
||||||
store.dispatch(actions.setAnimTarget(anims.animTarget));
|
|
||||||
store.dispatch(actions.setAnimText(null));
|
|
||||||
if (animations.isCbAnim(anims.animSkill)) store.dispatch(actions.setAnimCb(cb));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.stages.includes('POST_SKILL') && text) {
|
|
||||||
// timeout to prevent text classes from being added too soon
|
|
||||||
if (timeout === TIMES.POST_SKILL_DURATION_MS) {
|
|
||||||
store.dispatch(actions.setAnimText(text));
|
|
||||||
} else {
|
|
||||||
setTimeout(
|
|
||||||
() => store.dispatch(actions.setAnimText(text)),
|
|
||||||
timeout - TIMES.POST_SKILL_DURATION_MS - 700
|
|
||||||
);
|
|
||||||
timeout -= 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return setTimeout(() => {
|
|
||||||
store.dispatch(actions.setAnimSkill(null));
|
|
||||||
store.dispatch(actions.setAnimSource(null));
|
|
||||||
store.dispatch(actions.setAnimTarget(null));
|
|
||||||
// store.dispatch(actions.setAnimText(null));
|
|
||||||
store.dispatch(actions.setAnimFocus([]));
|
|
||||||
if (r.stages.includes('END_SKILL') && animations.isCbAnim(anims.animSkill)) return true;
|
|
||||||
return cb();
|
|
||||||
}, timeout);
|
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
// clear animation state
|
clearAnimations(store);
|
||||||
store.dispatch(actions.setAnimSkill(null));
|
|
||||||
store.dispatch(actions.setAnimSource(null));
|
|
||||||
store.dispatch(actions.setAnimTarget(null));
|
|
||||||
store.dispatch(actions.setAnimText(null));
|
|
||||||
store.dispatch(actions.setAnimating(false));
|
|
||||||
store.dispatch(actions.setGameEffectInfo(null));
|
|
||||||
|
|
||||||
// set the game state so resolutions don't fire twice
|
// set the game state so resolutions don't fire twice
|
||||||
store.dispatch(actions.setGame(game));
|
store.dispatch(actions.setGame(game));
|
||||||
ws.sendGameState(game.id);
|
ws.sendGameState(game.id);
|
||||||
@ -146,16 +104,21 @@ function registerEvents(store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setAccount(account) {
|
function setAccount(account) {
|
||||||
if (account && process.env.NODE_ENV !== 'development') {
|
store.dispatch(actions.setAccount(account));
|
||||||
LogRocket.init('yh0dy3/mnml');
|
}
|
||||||
LogRocket.identify(account.id, account);
|
|
||||||
|
|
||||||
if (window.Notification) {
|
function setAuthenticated(account) {
|
||||||
window.Notification.requestPermission();
|
if (account && window.Notification) {
|
||||||
}
|
window.Notification.requestPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
|
LogRocket.identify(account.id, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(actions.setAccount(account));
|
store.dispatch(actions.setAccount(account));
|
||||||
|
store.dispatch(actions.setTutorial(null));
|
||||||
|
store.dispatch(actions.setAuthenticated(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setEmail(email) {
|
function setEmail(email) {
|
||||||
@ -220,23 +183,14 @@ function registerEvents(store) {
|
|||||||
const player = v.players.find(p => p.id === account.id);
|
const player = v.players.find(p => p.id === account.id);
|
||||||
store.dispatch(actions.setPlayer(player));
|
store.dispatch(actions.setPlayer(player));
|
||||||
|
|
||||||
const skip = v.time_control === 'Practice' && v.phase === 'Lobby';
|
if (tutorial) tutorialVbox(player, store, tutorial);
|
||||||
if (skip) {
|
|
||||||
ws.sendInstanceReady(v.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v.phase === 'Finished') {
|
if (v.phase === 'Finished') {
|
||||||
ws.sendAccountInstances();
|
ws.sendAccountInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
// instance.mobile.less hides info at @media 1000
|
|
||||||
if (localStorage.getItem('tutorial-complete') || window.innerWidth <= 1100) {
|
|
||||||
store.dispatch(actions.setTutorial(null));
|
|
||||||
} else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) {
|
|
||||||
tutorialVbox(player, store, tutorial);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return store.dispatch(actions.setInstance(v));
|
return store.dispatch(actions.setInstance(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,94 +206,6 @@ function registerEvents(store) {
|
|||||||
return store.dispatch(actions.setItemInfo(v));
|
return store.dispatch(actions.setItemInfo(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDemo(d) {
|
|
||||||
|
|
||||||
const vboxDemo = {
|
|
||||||
players: d,
|
|
||||||
combiner: [],
|
|
||||||
equipped: false,
|
|
||||||
equipping: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const startDemo = () => {
|
|
||||||
const { account, itemInfo } = store.getState();
|
|
||||||
if (account) return false;
|
|
||||||
if (!itemInfo || itemInfo.items.length === 0) return setTimeout(startDemo, 500);
|
|
||||||
store.dispatch(actions.setAnimTarget(null));
|
|
||||||
const bases = ['Attack', 'Stun', 'Buff', 'Debuff', 'Block'];
|
|
||||||
const combo = sample(itemInfo.combos.filter(i => bases.some(b => i.components.includes(b))));
|
|
||||||
vboxDemo.combo = combo.item;
|
|
||||||
vboxDemo.items = combo.components;
|
|
||||||
store.dispatch(actions.setDemo(vboxDemo));
|
|
||||||
|
|
||||||
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0] }))), 500);
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0, 1] }))), 1000);
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0, 1, 2] }))), 1500);
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [], items: [vboxDemo.combo, '', ''] }))), 2500);
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0], items: [vboxDemo.combo, '', ''], equipping: true }))), 3000);
|
|
||||||
setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 4000);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
return store.dispatch(actions.setAnimTarget({
|
|
||||||
skill: sample(itemInfo.items.filter(i => i.skill)).item,
|
|
||||||
constructId: d[1].constructs[0].id,
|
|
||||||
player: false,
|
|
||||||
direction: 0,
|
|
||||||
}));
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
return store.dispatch(actions.setAnimTarget({
|
|
||||||
skill: sample(itemInfo.items.filter(i => i.skill)).item,
|
|
||||||
constructId: d[1].constructs[1].id,
|
|
||||||
player: true,
|
|
||||||
direction: 0,
|
|
||||||
}));
|
|
||||||
}, 3000);
|
|
||||||
|
|
||||||
return setTimeout(startDemo, 5000);
|
|
||||||
};
|
|
||||||
|
|
||||||
startDemo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// store.subscribe(setInfo);
|
|
||||||
// store.on('SET_INFO', setInfo);
|
|
||||||
|
|
||||||
// events.on('SET_PLAYER', setInstance);
|
|
||||||
|
|
||||||
// events.on('SEND_SKILL', function skillActive(gameId, constructId, targetConstructId, skill) {
|
|
||||||
// ws.sendGameSkill(gameId, constructId, targetConstructId, skill);
|
|
||||||
// setConstructStatusUpdate(constructId, skill, targetConstructId);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// events.on('CONSTRUCT_ACTIVE', function constructActiveCb(construct) {
|
|
||||||
// for (let i = 0; i < constructs.length; i += 1) {
|
|
||||||
// if (constructs[i].id === construct.id) constructs[i].active = !constructs[i].active;
|
|
||||||
// }
|
|
||||||
// return setConstructs(constructs);
|
|
||||||
// });
|
|
||||||
|
|
||||||
/* function errorPrompt(type) {
|
|
||||||
const message = errMessages[type];
|
|
||||||
const OK_BUTTON = '<button type="submit">OK</button>';
|
|
||||||
toast.error({
|
|
||||||
theme: 'dark',
|
|
||||||
color: 'black',
|
|
||||||
timeout: false,
|
|
||||||
drag: false,
|
|
||||||
position: 'center',
|
|
||||||
maxWidth: window.innerWidth / 2,
|
|
||||||
close: false,
|
|
||||||
buttons: [
|
|
||||||
[OK_BUTTON, (instance, thisToast) => instance.hide({ transitionOut: 'fadeOut' }, thisToast)],
|
|
||||||
],
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
} */
|
|
||||||
// setup / localstorage
|
|
||||||
|
|
||||||
function urlHashChange() {
|
function urlHashChange() {
|
||||||
const { ws } = store.getState();
|
const { ws } = store.getState();
|
||||||
const cmds = querystring.parse(location.hash);
|
const cmds = querystring.parse(location.hash);
|
||||||
@ -348,6 +214,11 @@ function registerEvents(store) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startTutorial() {
|
||||||
|
store.dispatch(actions.setTutorial(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('hashchange', urlHashChange, false);
|
window.addEventListener('hashchange', urlHashChange, false);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -356,12 +227,13 @@ function registerEvents(store) {
|
|||||||
clearInstance,
|
clearInstance,
|
||||||
clearMtxActive,
|
clearMtxActive,
|
||||||
clearTutorial,
|
clearTutorial,
|
||||||
|
clearTutorialGame,
|
||||||
setAccount,
|
setAccount,
|
||||||
|
setAuthenticated,
|
||||||
setAccountInstances,
|
setAccountInstances,
|
||||||
setActiveItem,
|
setActiveItem,
|
||||||
setActiveSkill,
|
setActiveSkill,
|
||||||
setChatWheel,
|
setChatWheel,
|
||||||
setDemo,
|
|
||||||
setConstructList,
|
setConstructList,
|
||||||
setNewConstruct,
|
setNewConstruct,
|
||||||
setGame,
|
setGame,
|
||||||
@ -377,6 +249,8 @@ function registerEvents(store) {
|
|||||||
setSubscription,
|
setSubscription,
|
||||||
setWs,
|
setWs,
|
||||||
|
|
||||||
|
startTutorial,
|
||||||
|
|
||||||
urlHashChange,
|
urlHashChange,
|
||||||
|
|
||||||
notify,
|
notify,
|
||||||
|
|||||||
@ -10,18 +10,16 @@ function createReducer(defaultState, actionType) {
|
|||||||
/* eslint-disable key-spacing */
|
/* eslint-disable key-spacing */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
account: createReducer(null, 'SET_ACCOUNT'),
|
account: createReducer(null, 'SET_ACCOUNT'),
|
||||||
|
authenticated: createReducer(null, 'SET_AUTHENTICATED'),
|
||||||
activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
|
activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
|
||||||
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'),
|
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'),
|
||||||
|
|
||||||
animating: createReducer(false, 'SET_ANIMATING'),
|
animating: createReducer(false, 'SET_ANIMATING'),
|
||||||
animCb: createReducer(null, 'SET_ANIM_CB'),
|
|
||||||
animSkill: createReducer(null, 'SET_ANIM_SKILL'),
|
|
||||||
animSource: createReducer(null, 'SET_ANIM_SOURCE'),
|
animSource: createReducer(null, 'SET_ANIM_SOURCE'),
|
||||||
animFocus: createReducer(null, 'SET_ANIM_FOCUS'),
|
animFocus: createReducer(null, 'SET_ANIM_FOCUS'),
|
||||||
animTarget: createReducer(null, 'SET_ANIM_TARGET'),
|
animTarget: createReducer(null, 'SET_ANIM_TARGET'),
|
||||||
animText: createReducer(null, 'SET_ANIM_TEXT'),
|
|
||||||
|
|
||||||
demo: createReducer(null, 'SET_DEMO'),
|
resolution: createReducer(null, 'SET_RESOLUTION'),
|
||||||
|
|
||||||
chatShow: createReducer(null, 'SET_CHAT_SHOW'),
|
chatShow: createReducer(null, 'SET_CHAT_SHOW'),
|
||||||
chatWheel: createReducer([], 'SET_CHAT_WHEEL'),
|
chatWheel: createReducer([], 'SET_CHAT_WHEEL'),
|
||||||
|
|||||||
@ -129,6 +129,7 @@ function createSocket(events) {
|
|||||||
{ game_id: gameId, construct_id: constructId, target_construct_id: targetConstructId, skill },
|
{ game_id: gameId, construct_id: constructId, target_construct_id: targetConstructId, skill },
|
||||||
]);
|
]);
|
||||||
events.setActiveSkill(null);
|
events.setActiveSkill(null);
|
||||||
|
events.clearTutorialGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendGameSkillClear(gameId) {
|
function sendGameSkillClear(gameId) {
|
||||||
@ -255,10 +256,6 @@ function createSocket(events) {
|
|||||||
events.setItemInfo(info);
|
events.setItemInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDemo(v) {
|
|
||||||
events.setDemo(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
let pongTimeout;
|
let pongTimeout;
|
||||||
function onPong() {
|
function onPong() {
|
||||||
events.setPing(Date.now() - ping);
|
events.setPing(Date.now() - ping);
|
||||||
@ -273,6 +270,7 @@ function createSocket(events) {
|
|||||||
// this object wraps the reply types to a function
|
// this object wraps the reply types to a function
|
||||||
const handlers = {
|
const handlers = {
|
||||||
AccountState: onAccount,
|
AccountState: onAccount,
|
||||||
|
AccountAuthenticated: account => events.setAuthenticated(account),
|
||||||
AccountConstructs: onAccountConstructs,
|
AccountConstructs: onAccountConstructs,
|
||||||
AccountTeam: onAccountTeam,
|
AccountTeam: onAccountTeam,
|
||||||
AccountInstances: onAccountInstances,
|
AccountInstances: onAccountInstances,
|
||||||
@ -284,7 +282,6 @@ function createSocket(events) {
|
|||||||
InstanceState: onInstanceState,
|
InstanceState: onInstanceState,
|
||||||
ItemInfo: onItemInfo,
|
ItemInfo: onItemInfo,
|
||||||
Pong: onPong,
|
Pong: onPong,
|
||||||
Demo: onDemo,
|
|
||||||
|
|
||||||
// QueueRequested: () => events.notify('PVP queue request received.'),
|
// QueueRequested: () => events.notify('PVP queue request received.'),
|
||||||
QueueRequested: () => true,
|
QueueRequested: () => true,
|
||||||
@ -303,6 +300,8 @@ function createSocket(events) {
|
|||||||
ChatWheel: wheel => events.setChatWheel(wheel),
|
ChatWheel: wheel => events.setChatWheel(wheel),
|
||||||
// Joining: () => events.notify('Searching for instance...'),
|
// Joining: () => events.notify('Searching for instance...'),
|
||||||
|
|
||||||
|
StartTutorial: () => events.startTutorial(),
|
||||||
|
|
||||||
Processing: () => true,
|
Processing: () => true,
|
||||||
Error: errHandler,
|
Error: errHandler,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -115,8 +115,9 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (tutorial === 1) {
|
if (tutorial === 1) {
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h1>Welcome to MNML</h1>
|
||||||
<p> Welcome to the vbox phase tutorial.</p>
|
<p> This is the <b>VBOX Phase</b> tutorial.</p>
|
||||||
|
<p> In the <b>VBOX Phase</b> you customise your constructs' skills and specialisations. </p>
|
||||||
<p> Colours are used to create powerful combinations with base items. </p>
|
<p> Colours are used to create powerful combinations with base items. </p>
|
||||||
<p> Buy the two colours from the store to continue. </p>
|
<p> Buy the two colours from the store to continue. </p>
|
||||||
</div>
|
</div>
|
||||||
@ -126,9 +127,9 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (tutorial === 2) {
|
if (tutorial === 2) {
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Combining Items</h2>
|
||||||
<p> You start the game with the base <b>Attack</b> skill item. </p>
|
<p> You start the game with the base <b>Attack</b> skill item. </p>
|
||||||
<p> Highlight all three items then click combine.</p>
|
<p> Highlight the <b>Attack</b> and the two <b> colours</b> then click <b> combine</b> </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -137,11 +138,11 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
const constructOne = instance.players[0].constructs[0].name;
|
const constructOne = instance.players[0].constructs[0].name;
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Equipping Items</h2>
|
||||||
<p> The first construct on your team is <b>{constructOne}</b>. </p>
|
<p> The first construct on your team is <b>{constructOne}</b>. </p>
|
||||||
<p> Skill items can be equipped to your constructs to be used in the combat phase. </p>
|
<p> Skill items can be equipped to your constructs to be used in the combat phase. </p>
|
||||||
<p> Click your new skill from the stash. <br />
|
<p> Click your new skill from the stash. <br />
|
||||||
Once selected click the flashing <b>SKILL</b> slot to equip the skill. </p>
|
Once selected click the flashing <b>SKILL</b> slot or the construct img to equip the skill. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -149,7 +150,7 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (tutorial === 4) {
|
if (tutorial === 4) {
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Specialisations</h2>
|
||||||
<p> You can also buy specialisation items for your constructs. <br />
|
<p> You can also buy specialisation items for your constructs. <br />
|
||||||
Specialisation items increase stats including power, speed and life. </p>
|
Specialisation items increase stats including power, speed and life. </p>
|
||||||
<p> Buy the specialisation item from the store to continue. </p>
|
<p> Buy the specialisation item from the store to continue. </p>
|
||||||
@ -160,11 +161,12 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (tutorial === 5) {
|
if (tutorial === 5) {
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Specialisations</h2>
|
||||||
<p> Equipping specialisation items will increase the stats of your constructs.</p>
|
<p> Equipping specialisation items will increase the stats of your constructs.</p>
|
||||||
<p> These can also be combined with colours for further specialisation. </p>
|
<p> These can also be combined with colours for further specialisation. </p>
|
||||||
<p> Click the specialisation item in the stash.<br />
|
<p> Click the specialisation item in the stash.<br />
|
||||||
Once selected click the flashing <b>SPEC</b> slot to equip the specialisation. </p>
|
Once selected click the flashing <b>SPEC</b> slot to equip the specialisation. </p>
|
||||||
|
<p> <b>PRO TIP:</b> while selecting an item in the shop, click on your construct to buy and equip in one step. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -174,11 +176,12 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
const constructThree = instance.players[0].constructs[2].name;
|
const constructThree = instance.players[0].constructs[2].name;
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Skills</h2>
|
||||||
<p> You have now created a construct with an upgraded skill and base spec. </p>
|
<p> You have now created a construct with an upgraded skill and base spec. </p>
|
||||||
<p> The goal is to create three powerful constructs for combat. </p>
|
<p> The goal is to create three powerful constructs for combat. </p>
|
||||||
<p> Equip your other constructs <b>{constructTwo}</b> and <b>{constructThree}</b> with the Attack skill. <br />
|
<p> Equip your other constructs <b>{constructTwo}</b> and <b>{constructThree}</b> with the Attack skill. <br />
|
||||||
Ensure each construct has a single skill to continue. </p>
|
Ensure each construct has a single skill to continue. </p>
|
||||||
|
<p> <b>PRO TIP:</b> Select a skill or spec on a construct and click another construct to swap it. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -186,7 +189,7 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
if (tutorial === 7) {
|
if (tutorial === 7) {
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>Economy</h2>
|
||||||
<p> Each round you start with 30 bits and a store full of different skills, specs and colours. </p>
|
<p> Each round you start with 30 bits and a store full of different skills, specs and colours. </p>
|
||||||
<p> Bits are your currency for buying items. <br />
|
<p> Bits are your currency for buying items. <br />
|
||||||
You can refill the store by pressing the refill button for 2b. <br />
|
You can refill the store by pressing the refill button for 2b. <br />
|
||||||
@ -203,22 +206,22 @@ function tutorialStage(tutorial, clearTutorial, instance) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='info-item'>
|
<div class='info-item'>
|
||||||
<h2>Tutorial</h2>
|
<h2>GLHF</h2>
|
||||||
<p>That completes the VBOX Tutorial.</p>
|
<p>That completes the VBOX Tutorial.</p>
|
||||||
<p>Press <b>READY</b> to progress to the <b>GAME PHASE</b> <br />
|
<p>Press the green <b>READY</b> button in the bottom right to progress to the <b>GAME PHASE</b> <br />
|
||||||
You can continue creating new items to upgrade your constructs further. </p>
|
or continue creating new items to upgrade your constructs further. </p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const classes = tutorial === 8 ? 'focus' : '';
|
const exitTutorial = tutorial === 8 ?
|
||||||
const text = tutorial === 8 ? 'Continue' : 'Skip Tutorial'
|
<button
|
||||||
const exitTutorial = <button
|
class='focus'
|
||||||
class={classes}
|
onClick={e => e.stopPropagation()}
|
||||||
onClick={e => e.stopPropagation()}
|
onMouseDown={exit}> Continue </button>
|
||||||
onMouseDown={exit}> {text} </button>;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='tutorial'>
|
<div class='tutorial'>
|
||||||
|
|||||||
@ -240,28 +240,16 @@ function convertItem(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function effectInfo(i) {
|
function effectInfo(i) {
|
||||||
|
// FIX ME
|
||||||
const hybridBlast = 25;
|
const hybridBlast = 25;
|
||||||
const hasteStrike = 30;
|
const hasteStrike = 30;
|
||||||
function multiplier(s) { // Update later to use server info in future
|
function multiplier(s) { // Update later to use server info in future
|
||||||
if (s === 'CounterAttack') return 120;
|
if (s === 'CounterAttack') return 115;
|
||||||
if (s === 'CounterAttack+') return 160;
|
if (s === 'CounterAttack+') return 130;
|
||||||
if (s === 'CounterAttack++') return 230;
|
if (s === 'CounterAttack++') return 160;
|
||||||
|
if (s === 'Electrocute') return 80;
|
||||||
if (s === 'DecayTick') return 33;
|
if (s === 'Electrocute+') return 90;
|
||||||
if (s === 'DecayTick+') return 45;
|
if (s === 'Electrocute++') return 100;
|
||||||
if (s === 'DecayTick++') return 70;
|
|
||||||
|
|
||||||
if (s === 'SiphonTick') return 25;
|
|
||||||
if (s === 'SiphonTick+') return 30;
|
|
||||||
if (s === 'SiphonTick++') return 40;
|
|
||||||
|
|
||||||
if (s === 'TriageTick') return 75;
|
|
||||||
if (s === 'TriageTick+') return 110;
|
|
||||||
if (s === 'TriageTick++') return 140;
|
|
||||||
|
|
||||||
if (s === 'Electrocute' || s === 'ElectrocuteTick') return 80;
|
|
||||||
if (s === 'Electrocute+' || s === 'ElectrocuteTick+') return 100;
|
|
||||||
if (s === 'Electrocute++' || s === 'ElectrocuteTick++') return 130;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +274,13 @@ function effectInfo(i) {
|
|||||||
case 'Vulnerable': return `Construct will take ${i.meta[1] - 100}% increased red damage`;
|
case 'Vulnerable': return `Construct will take ${i.meta[1] - 100}% increased red damage`;
|
||||||
case 'Silence': return 'Disable construct from casting any blue skills';
|
case 'Silence': return 'Disable construct from casting any blue skills';
|
||||||
case 'Wither': return `Construct will take ${100 - i.meta[1]}% reduced healing`; //
|
case 'Wither': return `Construct will take ${100 - i.meta[1]}% reduced healing`; //
|
||||||
case 'Decay': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower as blue damage each turn.`; //
|
case 'Decay': return `Construct will take ${i.meta[1].amount} blue damage each turn.`; //
|
||||||
case 'Electric': return `Attacks against this construct will apply Electrocute dealing ${multiplier(i.meta[1])}% of construct BluePower as blue damage each turn.`;
|
case 'Electric': return `Attacks against this construct will apply Electrocute dealing ${multiplier(i.meta[1])}% of construct BluePower as blue damage each turn.`;
|
||||||
case 'Electrocute': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower as blue damage each turn.`;
|
case 'Electrocute': return `Construct will take ${i.meta[1].amount} blue damage each turn.`;
|
||||||
case 'Absorb': return 'If construct takes damage, Absorption will be applied increasing RedPower and BluePower based on damage taken.';
|
case 'Absorb': return 'If construct takes damage, Absorption will be applied increasing RedPower and BluePower based on damage taken.';
|
||||||
case 'Absorption': return `Increasing construct RedPower and BluePower by ${i.meta[1]}`;
|
case 'Absorption': return `Increasing construct RedPower and BluePower by ${i.meta[1]}`;
|
||||||
case 'Triage': return `Construct will be healed for ${multiplier(i.tick.skill)}% of caster's GreenPower each turn.`;
|
case 'Triage': return `Construct will be healed for ${i.meta[1].amount} green life each turn.`;
|
||||||
case 'Siphon': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower + GreenPower as blue damage each turn, healing the caster.`;
|
case 'Siphon': return `Construct will take ${i.meta[1].amount} blue damage each turn, healing the caster.`;
|
||||||
|
|
||||||
default: return 'Missing Effect Text';
|
default: return 'Missing Effect Text';
|
||||||
}
|
}
|
||||||
|
|||||||
3
core/.cargo/config
Executable file
3
core/.cargo/config
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
[target.x86_64-pc-windows-msvc.gnu]
|
||||||
|
rustc-link-search = ["C:\\Program Files\\PostgreSQL\\pg96\\lib"]
|
||||||
|
|
||||||
4
core/.gitignore
vendored
Normal file
4
core/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
target/
|
||||||
|
Cargo.lock
|
||||||
|
log/
|
||||||
|
.env
|
||||||
13
core/Cargo.toml
Normal file
13
core/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "mnml_core"
|
||||||
|
version = "1.11.0"
|
||||||
|
authors = ["ntr <ntr@smokestack.io>", "mashy <mashy@mnml.gg>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
failure = "0.1"
|
||||||
|
log = "0.4"
|
||||||
|
rand = "0.6"
|
||||||
|
serde = "1"
|
||||||
|
serde_derive = "1"
|
||||||
|
uuid = { version = "0.5", features = ["serde", "v4"] }
|
||||||
5
core/fixme.md
Normal file
5
core/fixme.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# FIXME
|
||||||
|
game ready not auto starting resolve phase
|
||||||
|
|
||||||
|
remove big header and move to rhs of news pane
|
||||||
|
add big logo w/ noise when you mouseover stuff etc
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,9 @@
|
|||||||
use construct::{Stat, EffectMeta};
|
use construct::{Stat, EffectMeta};
|
||||||
|
use game::{Colour};
|
||||||
use skill::{Skill};
|
use skill::{Skill};
|
||||||
use util::{IntPct};
|
use util::{IntPct};
|
||||||
|
|
||||||
pub type Cooldown = Option<u8>;
|
pub type Cooldown = Option<usize>;
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
pub enum Effect {
|
pub enum Effect {
|
||||||
@ -41,10 +42,17 @@ pub enum Effect {
|
|||||||
|
|
||||||
// effects over time
|
// effects over time
|
||||||
Triage,
|
Triage,
|
||||||
Decay,
|
Triaged, // immunity
|
||||||
Regen,
|
|
||||||
Siphon,
|
|
||||||
|
|
||||||
|
Decay,
|
||||||
|
Decayed, // immunity
|
||||||
|
|
||||||
|
Siphon,
|
||||||
|
Siphoned, // immunity
|
||||||
|
|
||||||
|
Countered,
|
||||||
|
|
||||||
|
// Regen,
|
||||||
// Airborne,
|
// Airborne,
|
||||||
// Boost
|
// Boost
|
||||||
// Bleed,
|
// Bleed,
|
||||||
@ -66,18 +74,42 @@ impl Effect {
|
|||||||
pub fn immune(&self, skill: Skill) -> bool {
|
pub fn immune(&self, skill: Skill) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Effect::Banish => true,
|
Effect::Banish => true,
|
||||||
Effect::Sustain => [
|
|
||||||
Skill::Stun,
|
// these provide immunity for the ticks
|
||||||
Skill::Silence,
|
// the base skills will still resolve
|
||||||
Skill::SilencePlus,
|
// but they have early return checks
|
||||||
Skill::SilencePlusPlus,
|
// to ensure the effect is reapplied but damage is not
|
||||||
Skill::Ruin,
|
Effect::Siphoned => [
|
||||||
Skill::RuinPlus,
|
Skill::SiphonTick,
|
||||||
Skill::RuinPlusPlus,
|
|
||||||
Skill::Restrict,
|
|
||||||
Skill::RestrictPlus,
|
|
||||||
Skill::RestrictPlusPlus
|
|
||||||
].contains(&skill),
|
].contains(&skill),
|
||||||
|
|
||||||
|
Effect::Decayed => [
|
||||||
|
Skill::DecayTick,
|
||||||
|
].contains(&skill),
|
||||||
|
|
||||||
|
Effect::Triaged => [
|
||||||
|
Skill::TriageTick,
|
||||||
|
].contains(&skill),
|
||||||
|
|
||||||
|
Effect::Countered => [
|
||||||
|
Skill::CounterAttack,
|
||||||
|
Skill::CounterAttackPlus,
|
||||||
|
Skill::CounterAttackPlusPlus,
|
||||||
|
].contains(&skill),
|
||||||
|
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hidden effects are used generally for immunities
|
||||||
|
// they are not displayed on client
|
||||||
|
// and not included in counts
|
||||||
|
pub fn hidden(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Effect::Siphoned => true,
|
||||||
|
Effect::Decayed => true,
|
||||||
|
Effect::Triaged => true,
|
||||||
|
Effect::Countered => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +133,7 @@ impl Effect {
|
|||||||
pub fn modifications(&self) -> Vec<Stat> {
|
pub fn modifications(&self) -> Vec<Stat> {
|
||||||
match self {
|
match self {
|
||||||
// Bases
|
// Bases
|
||||||
Effect::Block => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
Effect::Block => vec![Stat::RedDamageReceived, Stat::BlueDamageReceived],
|
||||||
Effect::Buff => vec![Stat::BluePower, Stat::RedPower, Stat::Speed],
|
Effect::Buff => vec![Stat::BluePower, Stat::RedPower, Stat::Speed],
|
||||||
Effect::Slow => vec![Stat::Speed],
|
Effect::Slow => vec![Stat::Speed],
|
||||||
|
|
||||||
@ -111,10 +143,10 @@ impl Effect {
|
|||||||
Effect::Hybrid => vec![Stat::GreenPower],
|
Effect::Hybrid => vec![Stat::GreenPower],
|
||||||
|
|
||||||
// Damage taken changes
|
// Damage taken changes
|
||||||
Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken],
|
Effect::Curse => vec![Stat::RedDamageReceived, Stat::BlueDamageReceived],
|
||||||
Effect::Pure => vec![Stat::GreenDamageTaken], // increased green taken
|
Effect::Pure => vec![Stat::GreenHealingReceived], // increased green taken
|
||||||
Effect::Vulnerable => vec![Stat::RedDamageTaken],
|
Effect::Vulnerable => vec![Stat::RedDamageReceived],
|
||||||
Effect::Wither => vec![Stat::GreenDamageTaken], // reduced green taken
|
Effect::Wither => vec![Stat::GreenHealingReceived], // reduced green taken
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
Effect::Haste => vec![Stat::Speed],
|
Effect::Haste => vec![Stat::Speed],
|
||||||
@ -123,7 +155,7 @@ impl Effect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(&self, value: u64, meta: Option<EffectMeta>) -> u64 {
|
pub fn apply(&self, value: usize, meta: Option<EffectMeta>) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Effect::Amplify |
|
Effect::Amplify |
|
||||||
Effect::Vulnerable |
|
Effect::Vulnerable |
|
||||||
@ -154,7 +186,10 @@ impl Effect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn colour(&self) -> Option<Colour> {
|
// Old colour matching system for buffs / debuffs
|
||||||
|
// Had issues as some effects will be considered as both a buff and debuff e.g. invert,
|
||||||
|
// Ended up being confusing with mismatch skills that have red / blue e.g. amplify, haste, hybrid
|
||||||
|
/* pub fn colour(&self) -> Option<Colour> {
|
||||||
match self {
|
match self {
|
||||||
// physical
|
// physical
|
||||||
Effect::Stun => Some(Colour::Red),
|
Effect::Stun => Some(Colour::Red),
|
||||||
@ -192,18 +227,14 @@ impl Effect {
|
|||||||
// effects over time
|
// effects over time
|
||||||
Effect::Triage => Some(Colour::Green),
|
Effect::Triage => Some(Colour::Green),
|
||||||
Effect::Decay => Some(Colour::Blue),
|
Effect::Decay => Some(Colour::Blue),
|
||||||
Effect::Regen => Some(Colour::Green),
|
|
||||||
Effect::Siphon => Some(Colour::Blue),
|
Effect::Siphon => Some(Colour::Blue),
|
||||||
Effect::Pure => Some(Colour::Green),
|
Effect::Pure => Some(Colour::Green),
|
||||||
|
|
||||||
|
Effect::Triaged => None,
|
||||||
|
Effect::Decayed => None,
|
||||||
|
Effect::Siphoned => None,
|
||||||
|
Effect::Countered => None,
|
||||||
Effect::Ko => None,
|
Effect::Ko => None,
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
|
||||||
pub enum Colour {
|
|
||||||
Red,
|
|
||||||
Blue,
|
|
||||||
Green,
|
|
||||||
}
|
}
|
||||||
2514
core/src/game.rs
Normal file
2514
core/src/game.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,8 @@
|
|||||||
use std::fs::File;
|
|
||||||
use std::collections::{HashMap};
|
use std::collections::{HashMap};
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use serde_cbor::{from_slice, to_vec};
|
|
||||||
|
|
||||||
use postgres::transaction::Transaction;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
|
||||||
@ -14,16 +10,11 @@ use failure::err_msg;
|
|||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
|
|
||||||
use account::Account;
|
use player::{Player, Score};
|
||||||
|
use game::{Game};
|
||||||
|
use item::{Item};
|
||||||
use vbox;
|
use vbox;
|
||||||
|
|
||||||
use player::{Player, Score, player_create};
|
|
||||||
|
|
||||||
use mob::{bot_player, instance_mobs};
|
|
||||||
use game::{Game, Phase, game_get, game_write, game_update};
|
|
||||||
use item::{Item};
|
|
||||||
use rpc::{RpcMessage};
|
|
||||||
use img;
|
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
enum InstancePhase {
|
enum InstancePhase {
|
||||||
@ -107,14 +98,14 @@ pub struct Instance {
|
|||||||
time_control: TimeControl,
|
time_control: TimeControl,
|
||||||
|
|
||||||
phase: InstancePhase,
|
phase: InstancePhase,
|
||||||
phase_end: Option<DateTime<Utc>>,
|
pub phase_end: Option<DateTime<Utc>>,
|
||||||
phase_start: DateTime<Utc>,
|
pub phase_start: DateTime<Utc>,
|
||||||
|
|
||||||
winner: Option<Uuid>,
|
winner: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
fn new() -> Instance {
|
pub fn new() -> Instance {
|
||||||
Instance {
|
Instance {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
players: vec![],
|
players: vec![],
|
||||||
@ -152,8 +143,8 @@ impl Instance {
|
|||||||
.collect::<Vec<Uuid>>()
|
.collect::<Vec<Uuid>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// time out lobbies that have been open too long
|
||||||
pub fn upkeep(mut self) -> (Instance, Option<Game>) {
|
pub fn upkeep(mut self) -> (Instance, Option<Game>) {
|
||||||
// time out lobbies that have been open too long
|
|
||||||
if self.phase == InstancePhase::Lobby && self.phase_timed_out() {
|
if self.phase == InstancePhase::Lobby && self.phase_timed_out() {
|
||||||
self.finish();
|
self.finish();
|
||||||
return (self, None);
|
return (self, None);
|
||||||
@ -178,7 +169,7 @@ impl Instance {
|
|||||||
(self, new_game)
|
(self, new_game)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_name(mut self, name: String) -> Result<Instance, Error> {
|
pub fn set_name(mut self, name: String) -> Result<Instance, Error> {
|
||||||
if name.len() == 0 {
|
if name.len() == 0 {
|
||||||
return Err(err_msg("name must have a length"));
|
return Err(err_msg("name must have a length"));
|
||||||
}
|
}
|
||||||
@ -187,12 +178,12 @@ impl Instance {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_time_control(mut self, tc: TimeControl) -> Instance {
|
pub fn set_time_control(mut self, tc: TimeControl) -> Instance {
|
||||||
self.time_control = tc;
|
self.time_control = tc;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_player(&mut self, player: Player) -> Result<&mut Instance, Error> {
|
pub fn add_player(&mut self, player: Player) -> Result<&mut Instance, Error> {
|
||||||
if self.players.len() >= self.max_players {
|
if self.players.len() >= self.max_players {
|
||||||
return Err(err_msg("game full"))
|
return Err(err_msg("game full"))
|
||||||
}
|
}
|
||||||
@ -206,7 +197,7 @@ impl Instance {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn player_ready(&mut self, player_id: Uuid) -> Result<Option<Game>, Error> {
|
pub fn player_ready(&mut self, player_id: Uuid) -> Result<Option<Game>, Error> {
|
||||||
if ![InstancePhase::InProgress, InstancePhase::Lobby].contains(&self.phase) {
|
if ![InstancePhase::InProgress, InstancePhase::Lobby].contains(&self.phase) {
|
||||||
return Err(err_msg("instance not in start or vbox phase"));
|
return Err(err_msg("instance not in start or vbox phase"));
|
||||||
}
|
}
|
||||||
@ -308,7 +299,7 @@ impl Instance {
|
|||||||
self.next_round()
|
self.next_round()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_round(&mut self) -> &mut Instance {
|
pub fn next_round(&mut self) -> &mut Instance {
|
||||||
if self.finish_condition() {
|
if self.finish_condition() {
|
||||||
return self.finish();
|
return self.finish();
|
||||||
}
|
}
|
||||||
@ -350,7 +341,7 @@ impl Instance {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finished(&self) -> bool {
|
pub fn finished(&self) -> bool {
|
||||||
self.phase == InstancePhase::Finished
|
self.phase == InstancePhase::Finished
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +369,7 @@ impl Instance {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_game_id(&self) -> Option<Uuid> {
|
pub fn current_game_id(&self) -> Option<Uuid> {
|
||||||
if self.phase != InstancePhase::InProgress {
|
if self.phase != InstancePhase::InProgress {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -394,7 +385,7 @@ impl Instance {
|
|||||||
return current_round.game_id;
|
return current_round.game_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn game_finished(&mut self, game: &Game) -> Result<&mut Instance, Error> {
|
pub fn game_finished(&mut self, game: &Game) -> Result<&mut Instance, Error> {
|
||||||
{
|
{
|
||||||
let current_round = self.rounds
|
let current_round = self.rounds
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -436,14 +427,14 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PLAYER ACTIONS
|
// PLAYER ACTIONS
|
||||||
fn account_player(&mut self, account: Uuid) -> Result<&mut Player, Error> {
|
pub fn account_player(&mut self, account: Uuid) -> Result<&mut Player, Error> {
|
||||||
self.players
|
self.players
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|p| p.id == account)
|
.find(|p| p.id == account)
|
||||||
.ok_or(err_msg("account not in instance"))
|
.ok_or(err_msg("account not in instance"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn account_opponent(&mut self, account: Uuid) -> Result<&mut Player, Error> {
|
pub fn account_opponent(&mut self, account: Uuid) -> Result<&mut Player, Error> {
|
||||||
self.players
|
self.players
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|p| p.id != account)
|
.find(|p| p.id != account)
|
||||||
@ -501,334 +492,18 @@ impl Instance {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vbox_unequip(mut self, account: Uuid, target: Item, construct_id: Uuid, target_construct_id: Option<Uuid>) -> Result<Instance, Error> {
|
pub fn vbox_unequip(mut self, account: Uuid, target: Item, construct_id: Uuid, target_construct: Option<Uuid>) -> Result<Instance, Error> {
|
||||||
self.vbox_action_allowed(account)?;
|
self.vbox_action_allowed(account)?;
|
||||||
self.account_player(account)?
|
self.account_player(account)?
|
||||||
.vbox_unequip(target, construct_id, target_construct_id)?;
|
.vbox_unequip(target, construct_id, target_construct)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instance_create(tx: &mut Transaction, instance: Instance) -> Result<Instance, Error> {
|
|
||||||
let instance_bytes = to_vec(&instance)?;
|
|
||||||
|
|
||||||
let query = "
|
|
||||||
INSERT INTO instances (id, data, upkeep)
|
|
||||||
VALUES ($1, $2, $3)
|
|
||||||
RETURNING id;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[&instance.id, &instance_bytes, &instance.phase_end])?;
|
|
||||||
|
|
||||||
result.iter().next().ok_or(format_err!("no instances written"))?;
|
|
||||||
|
|
||||||
return Ok(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_update(tx: &mut Transaction, instance: Instance) -> Result<Instance, Error> {
|
|
||||||
let instance_bytes = to_vec(&instance)?;
|
|
||||||
|
|
||||||
let query = "
|
|
||||||
UPDATE instances
|
|
||||||
SET data = $1, finished = $2, upkeep = $3, updated_at = now()
|
|
||||||
WHERE id = $4
|
|
||||||
RETURNING id, data;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[&instance_bytes, &instance.finished(), &instance.phase_end, &instance.id])?;
|
|
||||||
|
|
||||||
result.iter().next().ok_or(err_msg("no instance row returned"))?;
|
|
||||||
|
|
||||||
trace!("{:?} wrote instance", instance.id);
|
|
||||||
|
|
||||||
if instance.finished() {
|
|
||||||
info!("finished id={:?}", instance.id);
|
|
||||||
|
|
||||||
match instance_json_file_write(&instance) {
|
|
||||||
Ok(dest) => info!("wrote dest={:?}", dest),
|
|
||||||
Err(e) => error!("json write error={:?}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn instance_json_file_write(g: &Instance) -> Result<String, Error> {
|
|
||||||
let dest = format!("/var/lib/mnml/data/instances/{}.mnml.instance.json", g.id);
|
|
||||||
serde_json::to_writer(File::create(&dest)?, g)?;
|
|
||||||
Ok(dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_get(tx: &mut Transaction, instance_id: Uuid) -> Result<Instance, Error> {
|
|
||||||
let query = "
|
|
||||||
SELECT *
|
|
||||||
FROM instances
|
|
||||||
WHERE id = $1
|
|
||||||
FOR UPDATE;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[&instance_id])?;
|
|
||||||
|
|
||||||
let returned = match result.iter().next() {
|
|
||||||
Some(row) => row,
|
|
||||||
None => return Err(err_msg("instance not found")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let instance_bytes: Vec<u8> = returned.get("data");
|
|
||||||
let instance = from_slice::<Instance>(&instance_bytes)?;
|
|
||||||
|
|
||||||
return Ok(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_delete(tx: &mut Transaction, id: Uuid) -> Result<(), Error> {
|
|
||||||
let query = "
|
|
||||||
DELETE
|
|
||||||
FROM instances
|
|
||||||
WHERE id = $1;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.execute(query, &[&id])?;
|
|
||||||
|
|
||||||
if result != 1 {
|
|
||||||
return Err(format_err!("unable to delete instance {:?}", id));
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("instance deleted {:?}", id);
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _instance_list(tx: &mut Transaction) -> Result<Vec<Instance>, Error> {
|
|
||||||
let query = "
|
|
||||||
SELECT data, id
|
|
||||||
FROM instances
|
|
||||||
AND finished = false;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[])?;
|
|
||||||
|
|
||||||
let mut list = vec![];
|
|
||||||
|
|
||||||
for row in result.into_iter() {
|
|
||||||
let bytes: Vec<u8> = row.get(0);
|
|
||||||
let id = row.get(1);
|
|
||||||
|
|
||||||
match from_slice::<Instance>(&bytes) {
|
|
||||||
Ok(i) => list.push(i),
|
|
||||||
Err(_e) => {
|
|
||||||
instance_delete(tx, id)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instances_need_upkeep(tx: &mut Transaction) -> Result<Vec<Instance>, Error> {
|
|
||||||
let query = "
|
|
||||||
SELECT data, id
|
|
||||||
FROM instances
|
|
||||||
WHERE finished = false
|
|
||||||
AND upkeep < now()
|
|
||||||
FOR UPDATE;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[])?;
|
|
||||||
|
|
||||||
let mut list = vec![];
|
|
||||||
|
|
||||||
for row in result.into_iter() {
|
|
||||||
let bytes: Vec<u8> = row.get(0);
|
|
||||||
let id = row.get(1);
|
|
||||||
|
|
||||||
match from_slice::<Instance>(&bytes) {
|
|
||||||
Ok(i) => list.push(i),
|
|
||||||
Err(_e) => {
|
|
||||||
instance_delete(tx, id)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
// timed out instances with no time control
|
|
||||||
pub fn instances_idle(tx: &mut Transaction) -> Result<Vec<Instance>, Error> {
|
|
||||||
let query = "
|
|
||||||
SELECT data, id
|
|
||||||
FROM instances
|
|
||||||
WHERE finished = false
|
|
||||||
AND updated_at < now() - interval '1 hour'
|
|
||||||
FOR UPDATE;
|
|
||||||
";
|
|
||||||
|
|
||||||
let result = tx
|
|
||||||
.query(query, &[])?;
|
|
||||||
|
|
||||||
let mut list = vec![];
|
|
||||||
|
|
||||||
for row in result.into_iter() {
|
|
||||||
let bytes: Vec<u8> = row.get(0);
|
|
||||||
let id = row.get(1);
|
|
||||||
|
|
||||||
match from_slice::<Instance>(&bytes) {
|
|
||||||
Ok(i) => list.push(i),
|
|
||||||
Err(_e) => {
|
|
||||||
instance_delete(tx, id)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn instance_practice(tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
|
||||||
let bot = bot_player();
|
|
||||||
let bot_id = bot.id;
|
|
||||||
|
|
||||||
// generate bot imgs for the client to see
|
|
||||||
for c in bot.constructs.iter() {
|
|
||||||
img::shapes_write(c.img)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut instance = Instance::new()
|
|
||||||
.set_time_control(TimeControl::Practice)
|
|
||||||
.set_name(bot.name.clone())?;
|
|
||||||
|
|
||||||
let player = Player::from_account(tx, account)?;
|
|
||||||
|
|
||||||
instance.add_player(player.clone())?;
|
|
||||||
instance.add_player(bot)?;
|
|
||||||
instance.player_ready(bot_id)?;
|
|
||||||
|
|
||||||
instance = instance_create(tx, instance)?;
|
|
||||||
player_create(tx, player, instance.id, account)?;
|
|
||||||
|
|
||||||
Ok(instance)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pvp(tx: &mut Transaction, a: &Account, b: &Account) -> Result<Instance, Error> {
|
|
||||||
let mut instance = Instance::new()
|
|
||||||
// TODO generate nice game names
|
|
||||||
.set_name("PVP".to_string())?;
|
|
||||||
|
|
||||||
instance = instance_create(tx, instance)?;
|
|
||||||
|
|
||||||
for account in [a, b].iter() {
|
|
||||||
let acc_p = Player::from_account(tx, &account)?;
|
|
||||||
let player = player_create(tx, acc_p, instance.id, account)?;
|
|
||||||
instance.add_player(player)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance_update(tx, instance)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_abandon(tx: &mut Transaction, account: &Account, instance_id: Uuid) -> Result<RpcMessage, Error> {
|
|
||||||
let mut instance = instance_get(tx, instance_id)?;
|
|
||||||
|
|
||||||
if let Some(game_id) = instance.current_game_id() {
|
|
||||||
let mut game = game_get(tx, game_id)?;
|
|
||||||
game.player_by_id(account.id)?.forfeit();
|
|
||||||
game = game.start(); // actually finishes it...
|
|
||||||
game_update(tx, &game)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.account_player(account.id)?.set_lose();
|
|
||||||
instance.account_opponent(account.id)?.set_win();
|
|
||||||
instance.next_round();
|
|
||||||
|
|
||||||
Ok(RpcMessage::InstanceState(instance_update(tx, instance)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_ready(tx: &mut Transaction, account: &Account, instance_id: Uuid) -> Result<RpcMessage, Error> {
|
|
||||||
let mut instance = instance_get(tx, instance_id)?;
|
|
||||||
let player_id = instance.account_player(account.id)?.id;
|
|
||||||
|
|
||||||
if let Some(game) = instance.player_ready(player_id)? {
|
|
||||||
game_write(tx, &game)?;
|
|
||||||
|
|
||||||
// ensures cleanup for warden etc is done
|
|
||||||
game_update(tx, &game)?;
|
|
||||||
|
|
||||||
instance_update(tx, instance)?;
|
|
||||||
return Ok(RpcMessage::GameState(game));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RpcMessage::InstanceState(instance_update(tx, instance)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_state(tx: &mut Transaction, instance_id: Uuid) -> Result<RpcMessage, Error> {
|
|
||||||
let instance = instance_get(tx, instance_id)?;
|
|
||||||
|
|
||||||
if let Some(game_id) = instance.current_game_id() {
|
|
||||||
let game = game_get(tx, game_id)?;
|
|
||||||
|
|
||||||
// return the game until it's finished
|
|
||||||
if game.phase != Phase::Finished {
|
|
||||||
return Ok(RpcMessage::GameState(game))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RpcMessage::InstanceState(instance))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_game_finished(tx: &mut Transaction, game: &Game, instance_id: Uuid) -> Result<(), Error> {
|
|
||||||
let mut instance = instance_get(tx, instance_id)?;
|
|
||||||
instance.game_finished(game)?;
|
|
||||||
// info!("{:?}", instance_get(tx, instance_id)?);
|
|
||||||
|
|
||||||
instance_update(tx, instance)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bot_instance() -> Instance {
|
|
||||||
let mut instance = Instance::new();
|
|
||||||
|
|
||||||
let bot_player = bot_player();
|
|
||||||
let bot = bot_player.id;
|
|
||||||
instance.add_player(bot_player).unwrap();
|
|
||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
|
||||||
let constructs = instance_mobs(player_account);
|
|
||||||
let player = Player::new(player_account, &"test".to_string(), constructs).set_bot(true);
|
|
||||||
|
|
||||||
instance.add_player(player).expect("could not add player");
|
|
||||||
instance.player_ready(player_account).unwrap();
|
|
||||||
instance.player_ready(bot).unwrap();
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn demo() -> Result<Vec<Player>, Error> {
|
|
||||||
let bot = bot_player();
|
|
||||||
|
|
||||||
// generate bot imgs for the client to see
|
|
||||||
for c in bot.constructs.iter() {
|
|
||||||
img::shapes_write(c.img)?;
|
|
||||||
};
|
|
||||||
|
|
||||||
let bot2 = bot_player();
|
|
||||||
|
|
||||||
// generate bot imgs for the client to see
|
|
||||||
for c in bot2.constructs.iter() {
|
|
||||||
img::shapes_write(c.img)?;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Ok(vec![bot, bot2])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use mob::{bot_player, instance_mobs};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn instance_pve_test() {
|
fn instance_pve_test() {
|
||||||
@ -854,7 +529,7 @@ mod tests {
|
|||||||
let _instance = Instance::new();
|
let _instance = Instance::new();
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let _player = Player::new(player_account, &"test".to_string(), constructs).set_bot(true);
|
let _player = Player::new(player_account, None, &"test".to_string(), constructs).set_bot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -865,7 +540,7 @@ mod tests {
|
|||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let player = Player::new(player_account, &"a".to_string(), constructs);
|
let player = Player::new(player_account, None, &"a".to_string(), constructs);
|
||||||
let a_id = player.id;
|
let a_id = player.id;
|
||||||
|
|
||||||
instance.add_player(player).expect("could not add player");
|
instance.add_player(player).expect("could not add player");
|
||||||
@ -873,7 +548,7 @@ mod tests {
|
|||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let player = Player::new(player_account, &"b".to_string(), constructs);
|
let player = Player::new(player_account, None, &"b".to_string(), constructs);
|
||||||
let b_id = player.id;
|
let b_id = player.id;
|
||||||
|
|
||||||
instance.add_player(player).expect("could not add player");
|
instance.add_player(player).expect("could not add player");
|
||||||
@ -902,7 +577,7 @@ mod tests {
|
|||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let player = Player::new(player_account, &"a".to_string(), constructs);
|
let player = Player::new(player_account, None, &"a".to_string(), constructs);
|
||||||
let a_id = player.id;
|
let a_id = player.id;
|
||||||
|
|
||||||
instance.add_player(player).expect("could not add player");
|
instance.add_player(player).expect("could not add player");
|
||||||
@ -910,7 +585,7 @@ mod tests {
|
|||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let player = Player::new(player_account, &"b".to_string(), constructs);
|
let player = Player::new(player_account, None, &"b".to_string(), constructs);
|
||||||
let b_id = player.id;
|
let b_id = player.id;
|
||||||
instance.add_player(player).expect("could not add player");
|
instance.add_player(player).expect("could not add player");
|
||||||
|
|
||||||
@ -942,7 +617,7 @@ mod tests {
|
|||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let player = Player::new(player_account, &"a".to_string(), constructs);
|
let player = Player::new(player_account, None, &"a".to_string(), constructs);
|
||||||
let _a_id = player.id;
|
let _a_id = player.id;
|
||||||
|
|
||||||
instance.add_player(player).expect("could not add player");
|
instance.add_player(player).expect("could not add player");
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user