add tab window to KL (#280)

* KL: init draft interface

* KL: fix images

* KL: put icons

* added score in local

* KL: divisors

* KL: add lateral buttons

* KL: background

* KL: init hero portraits

* KL: add lateral header buttons

* KL: minor styles fixes

* KL: add real keys in card user

* KL: fix negative margin

* KL: ready button

* KL: interface functionality

* KL: fix draft height problems

* KL: port the remaing parts from cardplayer

* KL: remove order of card users in interface

* KL: add bottom buttons on draft interface

* KL: add a little animation

* KL: draw filter interface

* KL: add filters prop to game

* KL: fix height and overflow

* KL: init filter functionality

* KL: fix filter reversing

* added role and b64 images to heroes

* BoardBuilder: change mouse cursor do 32x32

* KL: fix name bug

* KL: allow game to init

* KL: fix board position in html

* KL: set initial player pos in canvas board

* KL: undo scrollbar

* KL: add functional role filter

* KL: fix initial positons in canvas board

* KL: players now choose initial coordinates ingame

* show bases

* fix allies choosing same coord

* draw indicators to player know where clicked in base

* fix indicatos for users know base location

* add delay before game start

* refactor code

* remove actions when not in preparation moment

* fix arena board

* fix automatic coord choose

* fix lava board

* show skill description

* change cursor in buttons which does not work yet

* draw top of interface

* draw user hud interface

* add skills hud interface

* add cast list interface

* clean draw play code

* improve cross browser

* fix ap bars positioning

* fix ap bars positioning 2snd part

* animate ready button

* KL: delete draft for draft interface file

* KL: shows turns left to player come back to life

* KL: do ready button animation

* KL: add light indicator in card player if player is ready

* KL: add hover in header buttons

* KL: let skill lits all have same width

* KL: init tab window creation

* KL: add pressed tab buttons in tab window

* KL: finnish add skill tab in tab window

* KL: put table in stats tab

* KL: start organize play's draw files

* KL: fix some identation

* KL: end stats tab tables

* Kind: remove + sign in word show

* KL: change row qtt to 10

* KL: implement tab shadow

* KL: init recap tab

* KL: put order in draft skills tab on user card

* Merge branch 'master' into rheidner/interface

* KL: fix life_bar in recap graph

* KL: end recap tab

* KL: fix recap heals

Co-authored-by: Derenash <eyer.derenash@gmail.com>
This commit is contained in:
Rheidner Achiles 2021-08-19 10:50:50 -03:00 committed by GitHub
parent eedb46ba88
commit 57887f5520
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 2103 additions and 1011 deletions

View File

@ -9,13 +9,13 @@ type App.KL.Game.State.Local {
room: String
tab: Maybe<String>
page: String // page in draft -> heroes or users for now
score: Maybe<String>
info: Hexagonal.Axial
preview: App.KL.Game.Cast.Preview
mouse: Pair<U32, U32>
screen_size: Pair<U32, U32>
filter: App.KL.Game.Phase.Draft.Filter
hud: App.KL.Game.State.Local.hud // HUD controls
hud: App.KL.Game.Controls.Hud // HUD controls
draft: App.KL.Game.Controls.Draft // draft page controls
)
}
@ -26,8 +26,9 @@ App.KL.Game.State.Local.init(user: String, room: String, screen_size: Pair<U32,
let info = Hexagonal.Axial.new(0,0)
let page = "heroes"
let filter = App.KL.Game.Phase.Draft.Filter.default
let hud = App.KL.Game.State.Local.hud.new(none)
App.KL.Game.State.Local.new(user, room, tab, page, none, info, preview, mouse, screen_size, filter, hud)
let hud = App.KL.Game.Controls.Hud.initial
let draft = App.KL.Game.Controls.Draft.initial
App.KL.Game.State.Local.new(user, room, tab, page, info, preview, mouse, screen_size, filter, hud, draft)
// Global State
// ============

View File

@ -0,0 +1,56 @@
// BUTTON ANIMATION
// ==========================
type App.KL.Game.Assets.ButtonAnimation {
new(frames: List<String>, init_loop: Nat, seconds_per_frame: Nat)
}
type App.KL.Game.Assets.ButtonAnimation.Button { // animation and actual frame
new(animation: App.KL.Game.Assets.ButtonAnimation, frame: Nat)
}
App.KL.Game.Assets.ButtonAnimation.Button.get_img(
button: App.KL.Game.Assets.ButtonAnimation.Button
): Maybe<String>
App.KL.Game.Assets.ButtonAnimation.get(button@animation, button@frame)
App.KL.Game.Assets.ButtonAnimation.get(
animation: App.KL.Game.Assets.ButtonAnimation,
frame: Nat
): Maybe<String>
let index = Nat.div(frame, animation@seconds_per_frame)
List.get!(index, animation@frames)
App.KL.Game.Assets.ButtonAnimation.get_limit(
animation: App.KL.Game.Assets.ButtonAnimation
): Nat
(List.length!(animation@frames) * animation@seconds_per_frame) - 1
// BUTTON CLICK
// ==========================
type App.KL.Game.Assets.ButtonClick.Image {
new(
normal: String,
hover: String,
click: String
)
}
type App.KL.Game.Assets.ButtonClick {
new(image: App.KL.Game.Assets.ButtonClick.Image, hovered: Bool, clicked: Bool)
}
App.KL.Game.Assets.ButtonClick.generate(
image: App.KL.Game.Assets.ButtonClick.Image
): App.KL.Game.Assets.ButtonClick
App.KL.Game.Assets.ButtonClick.new(image, false, false)
App.KL.Game.Assets.ButtonClick.get_img(
button: App.KL.Game.Assets.ButtonClick
): String
if button@clicked then
button@image@click
else
if button@hovered then
button@image@hover
else
button@image@normal

View File

@ -0,0 +1,100 @@
// Draft controls
type App.KL.Game.Controls.Draft {
new(
// ready button controls
main_button: App.KL.Game.Assets.ButtonAnimation.Button
main_button_hovered: Bool
// header button controls
header: Map<App.KL.Game.Assets.ButtonClick> // id -> (img, state, action)
)
}
App.KL.Game.Controls.Draft.initial: App.KL.Game.Controls.Draft
App.KL.Game.Controls.Draft.new(
// ready button
App.KL.Game.Assets.ButtonAnimation.Button.new(App.KL.Game.Phase.Draft.Assets.main_button.ready, 0)
false
// header buttons
App.KL.Game.Controls.Draft.header.buttons
)
// default when mouse_move/mouse_down is not active
App.KL.Game.Controls.Draft.default(
ready: Bool,
controls: App.KL.Game.Controls.Draft
): App.KL.Game.Controls.Draft
let main_button =
if ready then
controls@main_button@animation <- App.KL.Game.Phase.Draft.Assets.main_button.waiting
else
controls@main_button@animation <- App.KL.Game.Phase.Draft.Assets.main_button.ready
let main_button_hovered = false
let header.buttons = App.KL.Game.Controls.Draft.header.buttons
App.KL.Game.Controls.Draft.new(main_button, main_button_hovered, header.buttons)
// HEADER BUTTONS
App.KL.Game.Controls.Draft.header.buttons: Map<App.KL.Game.Assets.ButtonClick>
{
"exit": App.KL.Game.Assets.ButtonClick.generate(exit_button),
"help": App.KL.Game.Assets.ButtonClick.generate(help_button),
"friend": App.KL.Game.Assets.ButtonClick.generate(friend_button),
"collection": App.KL.Game.Assets.ButtonClick.generate(collection_button),
"store": App.KL.Game.Assets.ButtonClick.generate(store_button),
"config": App.KL.Game.Assets.ButtonClick.generate(config_button),
}
App.KL.Game.Controls.Draft.header.update(
event_id: String
controls: App.KL.Game.Controls.Draft
): App.KL.Game.Controls.Draft
let buttons = controls@header
let button = buttons{event_id}
case button {
none: controls
some:
let buttons = buttons{event_id} <- button.value@hovered <- true
controls@header <- buttons
}
// assets
exit_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABdUlEQVR42u3bOwrCQBAG4LmAhZWViFjYWIsQewsrvYSNhbU3sPcwHsebREZYCMEkM65Zd/7MwBDBGPI5m908NjRdHEvOeXEq1+MzZBJHDLSYXKO+T4aMhZqoJDqU6oEIpU+BBqWmQIJSW6BAqSsQoCQJ61CSRh/IVCcKjuwb6c1VkNvtTbQ9r2SuSG0LSI6s7mDTZ4hKBlB9aQKp2Vled7W7JxlGfl5JyZ2CAOTekZddlTbb8ZiuZNdYxhmqB3vGk6pHzWac3DyepSZ4/eTImEoEoAb6F2RMVoG8HM32ojSLlAIhkNJmrm22XyNje8Y6UnMsa6FZVFLzO/5DtFCTSC00S2QVIM1BINuO6yyRkqGkDoRDaoBJkE1DzbcdjxZosnfVAk0PIZoTCHNI01chkMhBXE+GoSD7OwO/gGrT5LOQ7JE5TCnzh7COdKQjHelIRzrSJxD6VNBBTOqFn54NP9Ee/pUJ+JdfqsDD8gKV8MA3Eh3I+QLLm7B2ywCYiwAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABdklEQVR42u3bOwrCQBAG4LmAtZVYeAILwRPY2AmWIngSb6LgEWxsbTyHN4mMsBAWk8xkdd35MwNDBGPI52x289jQZLapOBe7c7UdnyCTOFKgu+k16ftsyFSoiUqiQykORCh9CjQoNQUSlNoCBUpdgQAlSViHkjR+gcx1ouDIXyO9uQpyv7mLtueVLBWpbQHZkfUdbPoMUckAipcmkJqd5XVXh0eWYeTrlZTcKQhA7h152VVpsx2P6Up2jWWcoXqwZzy5etRixsnl7VlpgtfPjkypRABqoH9BpmQdyMvRdC1Ks0gpEAIpbebaZtsbmdozxkjNsayFFlFJze/4D9FCTSK10CKRdYA0B4FsO66LREqGkhgIh9QAsyCbhpq+HY8WaLJ31QJNDyGaEwhzSNNXIZDIQVxPhqGg+DsD34Bq0+SzkOKRJUwp84ewjnSkIx3pSEc60icQ+lTQQUzqhZ+eDT/RHv6VCfiXX+rA4/wClfDANxIdyPkCvEaIRmHpIP4AAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABeElEQVR42u3bTWrDMBAF4LlASRdeFQJtfIvs0kUXgXTRkhu0y95/6UQFBWGcekZqZM3LEwwOxA7+MrJ+bFnW/ccQ43n1BhkSSgl087gv+r4ashTqIpPoUBkXRKhMFTSoXCtIUPmroEBlriBARVO8Q0VbboGsNVAg8tZIVlfN8U/vqt9jJltFWmtAdWR6gtc+Q2QygsZbF0jLyYZ9++6zSjfy75nU3Cm4AM+tY9jOZdptw+M6k3N9WYiYPdgRT4S9bL+G4+FHHWF/V9U1Ai3QxZC51S0Fhu1Dt1OFq0ymSC0QAqmt5jnVtgmk5VrOgWYjS5r/FGk5LvwhOdDFM2lF5kCbQ6YAbdwFcu66bg6p6UrGQDikFeiu4ckB1pmFTHQ1pUjrCMhlF2Id4rlCuh27lkyhOJ9cGhm7Aug7A9pO3/V8MhfKR3et3ePhUy0iiSSSSCKJJJILCLkUlIt6uTz7zhbaw78ykQJf+2+YgAdekMjAXyTq64RpnAA97jWvD4vjZQAAAABJRU5ErkJggg=="
)
help_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABCklEQVR42u3aMQrCMBTG8V7AwclJRBycXEXoEdy6eAQXB2cHz+VxvEm0QrE8bGi0ryYv/8Bbsv36kRfSpJivKlfXsjy67fSUVBUhAyhQoECBAn1XObuQqGloO+FgaIppBkFBggQJEiRIkCBBgswVubvdnRz1nBnkJ6AGtDlyjY70AbUSHR0pMZPF/lUSbwLZBjZlDimBppBtlJw3h/Q1pOQbT99mZAopu2pX0kkjtVOMDqkB/AtS3l+YRPbdUpJEdt1AaSG/ug/R7q5ax6zoGo9ZZBZJZrEmTXVX/tZZQ/pebGSX5JAfgyRZkyBBggSpiTT/UhIgQIAAAQ4FrNbnpArgr8DD5ho/8DkeXVaVqCOK3UcAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABCklEQVR42u3aMQrCMBTG8V7A2Uk6eAIHQc/gJjj2Lq6eQsEjOOhxvEm0QrE8bGi0ryYv/8Bbsv36kRfSpJjNt66uZXVyu+kxqSpCBlCgQIECBfquqryQqGloO+FgaIppBkFBggQJEiRIkCBBgswVubrdnRz1nBnkJ6AGtDlyjY70AbUSHR0pMZNy8yqJN4FsA5syh5RAU8g2Ss6bQ/oaUvKNp28zMoWUXbUr6aSR2ilGh9QA/gUp7y9MIvtuKUkiu26gtJBf3Ydod1etY1Z0jccsMosks1iTprorf+usIX0vNrJLcsiPQZKsSZAgQYLURJp/KQkQIECAAIcC7hfnpArgr8DD+ho/8DkePipsipfxmJwAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABDUlEQVR42u3asQuCUBDHcdeGqME1KCTaG9uCaGsx+g/aIuj/XwwD63WUWHl67/oKv+Ut8vF851NfMsnyosp0tDWfwXh5T/LJARQoUKBAgT6SpXsqCrQOGgPya2hsyBAKEiRIkCBBggQJUgU5Wx2Lw+78lHLMDfIVUAvaC7IOqAHtBSkxw3R9i8S7QIbAKu6QEugKGaLkuDtkXUOKvvE0bUaukLKrtgk0g9Ssoklk20CQ2sjw/8W7R4qrSrpDyj9QYXfVeM0qz2duTrq9XTUryZz0gjQzJ/laBzKiFc/fV7KNi0ElmZMgQYIE2cW2M/cbCAECBAiwM2C+uJhPiAX4K3AzP9kHxrRMk2m6WrsCMWlsRLvaUcQAAAAASUVORK5CYII="
)
friend_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABY0lEQVR42u3avwrCMBAG8L6Ag5OTiDi46CpC3R2cdPERXBycHdwcnFx8GB/H93CoHPTKEZK0gf7J2S/wYVtF+HHtJRiT8eyQUabpKVsNz6qShAxAAQXUm3R0RUUBBRRQQBOtyCAokEACCaQKZBPrUyDbRMaCQyWBrBG5fn8yOehcBVLCXMc2oIQOJjs9jcd8NYEM4vB1On5+70WivV0Jtti+rLcsDwmU0OiQhJAV4xBws3kUUI6rimZUV9JXRQlzpRMkVcu8Rjj5LPK5bDaqkCHd1dZFVSJ986Q5bah/JqssAGzVjLK7hkbOh2Y16bp6JCNcz6ZEykSPlHOjbxlX9pnOkTxFhCzGzQbUFLDV7vq3SNtKxwXxDRXIMkSV96NH1jGABLLFxuNbp5ZFTXftBbLLnyex4QMkkEACif1JVBJIIPvxB0IAAQQwKLbtQVQQwBy4n19ayXF5q+V7ogXWFQDz8QO+5KRoOZ+bkAAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABZElEQVR42u3aPQrCQBAF4FzA2kpSeAILQS9gYxewFMGT2FhYeQQFj2ChrY3n8B4WkYFMGJbdTRbys2PewsMkivAxyezimkymWU6Zb6/5ZnxRlSRkAAoooN5s0zsqCiiggAKaaEUGQYEEEkggVSDbWJ8C2SUyFhwqCWSDyMXzk8tB5yqQEuY6tgEldJSu9TQe89UEMojD1+n4/D2WifZ2Jdhq/7besjwkUEKjQxJCVoxDwF32KqEcVxXNqK6kr4oS5kovSKqWeY1w8lnkc9lsVCFDuquti6pE+uZJc9pQ/0zWWQDYqhlldw2NnA/NatJ19UhGuJ5NiZSJHinnRt8yruozvSN5ighZjJsNqC1gp931b5G2lY4L4hsqkFWIOu9Hj2xiAAlkh43Ht06tipruOghknz9PYsMHSCCBBBL7k6gkkEAO4w+EAAIIYFBs24OoIIAF8DC7dZLT8tHI90QLbCoAFuMHWxM4Ge0gYCEAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABcElEQVR42u3asWvCQBQG8Kwdig5OhYJt6D/g2M1SHAJ2qDi410mE/v9L9A3veH3cXXKpJveSL/BBjDr8+HKX06R4Lr9rynK2MZGH+cqlSNkABRTQaF7nFRoFFFBAAS0sITtDrSElFEgggZwQ8lbrUyCHQg6NQ5N9Il/ef+r99uxCr00jNVYDJfRxsc4fKUG0HwIyiMPHab/6PbhkP/H4TlduTQIl1AySgeVi9wcaalEnO6Q8JXnfAZ++HJQSa1HCQsm+STnZmENSW/oY4fTY9M2iZpvUs2vosmFqTKYsBiTU16a52dUXeT3UbdJx80hGhMamRMqYQIaWcBLZ9BkTTcYQhLwH8OZIvmSMGtk0u4YQDIm9b35MtkGaGJMxQNsACWSPl5DYOrUpZlY8k0BO5l7IEP/BokkggQQSSNyfRJNAjhuZ/NjZ6B8gBBBAANN+pnluD6LBNsCP8thbPt9Onb8rsdkC/xMA9WZtqZYMvG4XiCypA5Cd7OYAAAAASUVORK5CYII="
)
config_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABLElEQVR42u3aMQ6CMBTGcS7g4ORkjHFwcjUmHMGNhSO4ODg7eC6P401QhsbatECx1L76b/ISSRj8+fWRB1IsN1XT1ro8Nfv5WVQVPgsoUKBAgQJ9V7m4kmjWUD1hb6jENL2gIEGCBAkSJEiQIEH21OH+aNRqP2eH1IFTQaMjzdRcK0S66pYrOnLsEpWkKzW9xCNNRHs8Wx0/ynaO2CRtQBdUBLIrQfPc0IlGQ9r60AbUobb+BJnqdvVBJr9dVZ8N/dIm0NW/SSKHpONzkWIYSAmZzVinhuVYA/qo/0NCJdk32bgmIVHbtW+Ec416om+aXbNrdo8/pgD+tCd5WgdSELLrjY2/SzLkj0GS9CRIkCBBTonM/k1JgAABAgQYClhtL6IK4LfAendLH/haT4qjWTLT5E5NAAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABLElEQVR42u3aMQ6CMBTGcS7g7GQYPIGDiZ7BzcSRu7hyCk08goMex5ugDI21aYFiqX313+QlkjD48+sjD6RYLPdNW+vq3BzmJ1FV+CygQIECBQr0XVV5JdGsoXrC3lCJaXpBQYIECRIkSJAgQYLsqc390ajVfs4OqQOngkZHmqm5Voh01S1XdOTYJSpJV2p6iUeaiPZ4Vu4+ynaO2CRtQBdUBLIrQfPc0IlGQ9r60AbUobb+BJnqdvVBJr9dVZ8N/dIm0NW/SSKHpONzkWIYSAmZzVinhuVYA/qo/0NCJdk32bgmIVHbtW+Ec416om+aXbNrdo8/pgD+tCd5WgdSELLrjY2/SzLkj0GS9CRIkCBBTonM/k1JgAABAgQYCnhcXUQVwG+B9faWPvC1npxoBWlAW1gmAAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABMElEQVR42u3avQrCMBSG4a4OokNXQSni7ugmiJtLxTtwE8H7XyoRqjEk/W+T077CAaUFfXp65DMmWiVpltd6cQ6+Zsv9t6I6D6BAgQIFCvRXSXylo0CLoBKQjaHSkDoUJEiQIEGCBAnSL3JzuGe3y/NT6vnokDqwD6gXpNk1E2g71gbtBelClZV4pOqUXuKRJkK9nsfHv7KdI7aTNqALKgJZ1EHz3C47OijSNoc2oA61zSfIUG/XOsjgb9d8zqp+aBPomt8gkVW6U+dLijBArCOgN0eqf6DKko0rCTV9Py+dLItwrqgn+kezK7uObvmjL+AkFrK8zSRLkiCFIc0dG5PuZBcXg04ykyBBggQ5xLaz0W8gBAgQIMDBgOnuFXzpWIBtgaftI3ygpJhmVtW09gbwLZ8j7DojNAAAAABJRU5ErkJggg=="
)
collection_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABeElEQVR42u2aOwrCQBRF3YCFlZWIWFjZipDswEobl2BjYW1h745cjjuJDCQQYiTzeb+J98EDi0TmzL0zbz6ZLNanyuWquFS72VU8i/k9+t1JSMSApjSOMtlBrSRAAToAWpZPM3Dt+QGKAhSgtutqMGiOagaBAvLfIPvGnvY617SSVJ0Du0pCclpaZExqdwrsGgtpaYcCJSkgszsHgpLGlIs+LUhRcv96VxTh/sekXakAU0DZITnCFCS1ikNq/poTWCE5w4ySgGSGFCshULKO6fLwlVlB9gFQpSpke5sV0mhXFjggXXvUFwNNgxsL+thVXcmuXX3HVvf3KCFj1M8GMiYAqQHJsdXyhWxWPSJ1knLTbKJOSiwITB5kcQDiBB2QgZDWrgNUjyRhV0DS3LdkCdkGY4O0dOchZleuWda3M4eeS4aMVVXSDeJfSkpbXf1TUG7g0X7rGrSH5AJ0jYCCFgEt1Uwo2AU8bm7eed4+gp7nSFZACwnAOj5HZMzcC1c1fgAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABeElEQVR42u2aOwrCQBRF3YC1laRwBRaCrsEuYBnciq2rUHAJFtq6E3cSGUggxEjm834T74MHFonMmXtn3nwyW67K2uWmutaHxUU8q+Ie/e4sJGJAUxpHmeygVhKgAB0BPZYvM3Dd+QGKAhSgtutqMGiOagaBAvLfIIfGnvY617SSVJ0Du0pCclpaZExqdwrsGgtpaYcCJSkgszsHgpLGlIs+LUhRcvt81xTh/sekXakAU0DZITnCFCS1imNq/poTWCE5w4ySgGSGFCshULKJebH/yqwghwCoUhWyu80KabQrCxyQrj3qi4G2wa0FfeyqrmTfrr5jq/97kpAx6mcDGROA1IDk2Gr5QrarHpE6SblpNlEnJRYEJg+yOABxgg7IQEhr1wGqR5KwKyBp7luyhOyCsUFauvMQsyvXLOvbmWPPJUPGqirpBvEvJaWtrv4pKDfwZL91DdpDcgG6RkBBi4CWaiYU7AOe1jfvPO8eQc9zJCughQRgEx9tODcZ+LwMMgAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABd0lEQVR42u2avwrCMBDGXR1EBydBUIsv4OimiJsOim+gk/j+o9KhUmrFXHJ/cvUrfOAQpb98l1zuTG9anJ6VZsO9uorxmTS+P1q91aM8MaDUl+OUKqilAApQAuhicoSjAAWoY1DNvJoM6sHNaFBvkHVQQMZAtq09q3OuCydTJwfhagEpEdKqa9JqUhCuqZC5VChwkgvSsg8EJ1Mg25ybr6/Py+GRrPJ3qFGk4iQXYCyoCiQnYKWsILldjHFTHFIC8JebzT2hk5B/4eTfQaqkkJCXHYw3H3LlZBsAl1xClmnBFWS9zAoJ12pcNTGh38nGydC11fzcSUjKhuUOMkaAtICUKLWyTCGcRXN2eVLqQJBlj8cKsBONLHTQAUmEzOnCkllLEuEKSJ5d1jVkHUwM0vrfKpNwldplQyfz2zg2yFhXpaOBfO2M86akRqibAmpea8kCsNMOlu7BQQAyA26LW7B2yztpPJfqsKKAVgJg8/FUOjUVelp7AS1k8rRAMJo4AAAAAElFTkSuQmCC"
)
store_button: App.KL.Game.Assets.ButtonClick.Image
App.KL.Game.Assets.ButtonClick.Image.new(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABp0lEQVR42u2aPW7DMAyFc4EOnTIVRZOhyAWKAskNMqUn6NalQ+fcoDfqcXoTtxoECIJimxJ/RPsRIJAYTqwPj6IomZuH/dsQ/On4Mbzcf7ryDcUACtCFgh63V7GBpv9d8xwo2gMoZ4RA0ZLtDu8IXW4/nb5tQSOkZIY1VdRryAKSCtlzCENJKInEA0j1GhdKAtLIX39+h2jhsxnknHlTM7dSQHNIqcSSwt09nn2F6xxVUxXDd3eQc7xWRXHIfA5xGFVFcUhuq1FRFTIMrsZbVVQN11bIWhVVEk++plHWx5aMqgYZBpUPNAUoOVdGZYUcUyYOrFShTEFyqagSrmNqSq2LopAlVcfUlJ6LqhVPrmbMnKX7uDKqCWRNcRB/23pIpla75mpKVTfmkFTn2tGo70KiolGp1NPrXR1/UF+13Tq+qDnW6HY/uQrIW2HZdbi2JqCp626PJKeKARwuAxKQ/iAp9awbyJYindSZRenjCff08oodL2FbIa2UzJ9rpiR3D12zkotvCV0tYGmu9dasBAUBuATAUr+5ly5lsoKX5y9XDsBVAP7bH6xXMpCUBsQjAAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABp0lEQVR42u2aPWoDMRCFfQHXqYwhqVK6CPgO6QwpjXOU3CSBHCGNW98kN9lEhUAIeXdHmh/N7hsYsJe1Vx9vNBppZ7N7Og3BX85fw9vDpyvfUAygAF0o6Hn/IzbQ9L9rngNFewDljBAoWrLH53eELrdfTjdb0AgpmWFNFfUasoCkQvYcwlASSiLxAFK9xoWSgDTy4/V3iBY+m0HOmTc1cysFNIeUSiwp3Hb/6itc56iaqhi+u4Oc47UqikPmc4jDqCqKQ3JbjYqqkGFwNd6qomq4tkLWqqiSePI1jbI+tmRUNcgwqHygKUDJuTIqK+SYMnFgpQplCpJLRZVwHVNTal0UhSypOqam9FxUrXhyNWPmLN3HlVFNIGuKg/jb1kMytdo1V1OqujGHpDrXjkZ9FxIVjUqlnl7v6viD+qrt3vFFzbFGt/vJVUDeC8uuw7U1AU1dd3skOVUM4HAZkID0B0mpZ91AthTppM4sSh9PuKeXV+x4CdsKaaVk/lwzJbl76JqVXHxL6GoBS3Ott2YlKAjAJQCW+s29dCmTFfw4fLtyAK4C8N/+AMf42RSlpqo6AAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAABACAYAAACgNd+MAAABnklEQVR42u2aPQvCMBCGXR1EBydB8GMQV0c3FzcdKu4OroL/f1EqREKIbS693CX1LRxoEZuHJ7lckwzm6+plYjE+Zh/Dye4bA8oFUID2FHQ9vSRrtP3foc+B0dxAu/YQGG27Vtsbui53rGZnfdDUGVbVaEld1gUFJAUyxy4MkzCJxANI8RoXJnOFXO7vr+vp8Yn6c+8gbcAsIEPGDXXKseFG00PZ3dUHb1usvxcJ2WY1xqIIpDuGOIJiUQSSG5BqURyyblxMdLEo3l27QsZYFEs87pxGmTZiM6ooZN0ot6E2gC84Mqo4pM9mCCSHRVbIpi7YZDPFvKgyJptsphyLSSF9Vl2bJnP6fseRUVXKOtdmqupGvXZ1bVKrm9hFMnFIahS7MmCMGlN22Pe53mhUIH8tX1CXNcRNUrbaioXs0l3b7hcL6UsuKZKO6vJHWzGAFXRAAhKQ2UKG1LPFQcYU6WRIczKLstehvcWOTVguSC2T5rnqJjnO0LEeO+v9kdC/BfSNtRwOK8EgAPsMWG2e2YcNC8C/ACzp/dCN0GrtDQGWlhKAoUJ2AAAAAElFTkSuQmCC"
)

View File

@ -0,0 +1,50 @@
// HUD controls
type App.KL.Game.Controls.Hud {
new(
skill: Maybe<App.KL.Game.Skill>
// tab
tab_active: Bool
tab_which: App.KL.Game.Controls.Hud.Tab
)
}
type App.KL.Game.Controls.Hud.Tab.Label {
new(image: String, content: DOM)
}
App.KL.Game.Controls.Hud.initial: App.KL.Game.Controls.Hud
let skill = none
let tab_active = false
let tab_which = App.KL.Game.Controls.Hud.Tab.stats
App.KL.Game.Controls.Hud.new(
skill,
tab_active,
tab_which,
)
type App.KL.Game.Controls.Hud.Tab {
stats
skills
recap
}
App.KL.Game.Controls.Hud.Tab.show(
tab: App.KL.Game.Controls.Hud.Tab
): String
case tab {
stats: "stats"
skills: "skills"
recap: "recap"
}
App.KL.Game.Controls.Hud.Tab.eql(
a: App.KL.Game.Controls.Hud.Tab
b: App.KL.Game.Controls.Hud.Tab
): Bool
case a b {
stats stats: true
recap recap: true
skills skills: true
} default false

View File

@ -11,7 +11,7 @@ type App.KL.Game.Hero {
role: Maybe<App.KL.Game.Hero.Role>
description: String
)
}
}
type App.KL.Game.Hero.Draw.Pose {
idle

View File

@ -0,0 +1,13 @@
// background
// =====================
App.KL.Game.Phase.Draft.Assets.background.hexagons.1: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAAB2CAYAAAA6Ceb5AAABkklEQVR42u3cQQ7CIBAFUK7iGTyS9z+DxqXGhUULf+BN0qVN4VEYZNLWCsXlers/ryayQN4vPRMGAigcBFA4CKBwEEDhIIDCQQCBAQMGDBgwYAQYMGDAgAEDRoABAwYMGDBgAAECBAgQIECABCBAgMCAAQNGgAEDBgwYMGDAgAEDBgwYMGDAgHnpJDChICMeHsgPb8gZjQHyxynrH40DcmIH9/weyMBF/Zv7AZmYZX26P5CgtHcWRsn9iI0iGDBgwIABAwYMGDBgwIABAwYMGDBgwIDp66TVUWZV9MQDzTwoGzkITxsUKx0tjxyEw97aysUYIwfhtGl1h8ZWGETdD196egiedrsfvvSCGpyolEmzpfY2wzbDYMCAAQMGDBgwYMCAAQMGDBgwYMCAAaOipyCK79ccGABADrwhjpbDp6ytizEqrCFblS9VXNR3qOgpnWXtUNGzRNq7chtLbxSbAAMGDBgwYMAIMGDAgAEDBgwYMGDAgCkOs/rf/oCA1AECEgYEJAwISBgQkDAgIJun2TPjAUCEMu6iz3bYAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.background.hexagons.2: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEkAAAB3CAYAAABPA20BAAABk0lEQVR42u3c4W2DMBAGUFbJDB2p+8/QqpEiVVXaQrB9/syzxM/47AeGyMexbVq/dnt7//g6Vo/ZZKAjBl4Rs8tZ7DHwiphDLvEWA6+IWbL+X/l9RcwpAu3pryLmlGfhWf8VMSMeq494FTFPdVBxv4uKCQkSJEiQIEGCBAkSJEiQIC2DZKtkEqzvOD+P6XF6d/wXTi+smL3uIzitsGKyJmdwXsWKyb+1xNmLFZPJ7YnzG1bcOwEVx5bSAEGCBAkSJEiQIEGCBAkSJEiQIMGBAwcOHDhw/N+BBAkSJEiQIEGCBAkSJEiQIEGaC6l5bclKrxl3O0ErvLA+7GpOLH0oW/oJRTTT3CdnLMea9qEyQ2FfzBO4siw15u9KVbExJEiQIEGCBAkSJEiQIEGCBKkCyVbJThybbgeunEtv347OekQlAkZPNiqlNHrZRCUnR9+Ao9LcsR/GHBnzKp91jRswJEiQIEGCBAkSJEiQIEGCFL91EVmAM2rw0Ti9J7MUTuvJLY1zdrKXwjk6+Uvj/IcBx7K6t0/BHTiwPEdP2QAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Draft.Assets.background.hexagons.3: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAA0CAYAAAA0c0BmAAAAzklEQVR42u3Zyw2EMAxFUbcyNVAS/dcwIxZsEEjBY798fC1liZ3DP46ZMz7b/j2GCUNe81pQMYGzxnV0O6sZE3hCpqHfJoyYQCsyDP1vAs/xXqQbHX1rtOSLQjajsx/6u/xZyEe0+nWuAt6i1d/KnmCwYMGCBQsWLFiwYMFWxZZZ4qkX712RqrbMUMishtvQyKhW6lRIb5N8amTr9sdSyBJXcrgfgx4BFixYsGDBggULFixYsGtj1WgbKUogs9A2U5RAetG2UpRAZm+vvIkfiSZdjv2Z6aMAAAAASUVORK5CYII="
App.KL.Game.Phase.Draft.Assets.background.hexagons.4: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAB2CAYAAABMM1RyAAAB4ElEQVR42u3cQW7CMBAF0Fylqx6gN+kVeoHefwNiQVWloBCSPxPqZylLPPYjUYxn8DS9UPt8/z5drknLwM4vMiFY0EWwoItgQRfBgi6CHR66CnZYaMCAAQMGDBgwYMCAAQMGDBgwYMCAAQNubm8fX6fLZcM9DFt1Rw8Pm4IGG4IGG4IGG4IGG4IeZj1bidsZEzBgwIABAwYMGDBgwIABAwYMGDDgbe26dVg54ert0ZaY9za/k4O4TvJ3rPSk5zHiMR9N3+w5iDnsrVh7T3qpz91jPpuA3DKIJdgE9No+NsfcK4X+zKC3xFo76a1Qqz+fKgJ55LHbM9bSpPd+1Bf7qypjuvXiSMaaTzr9svrTf1chXhL2HnTLkrILuOMLbflRBBgwYMCAAQMGDBgwYMCAAQMGDBjwS21XHiID3vG/4fSGe2cGvDyzkczFHQG6LTeXzCYfAbotu5yshzgCdFt9RLKi5wjQbRU+FW/kTui2GrXKdeVIa+iW5qwfwIABAwYMGDBgwIABAwYMGDBgwIABNzcnZxfBVt3Rw8OmoMGGoMGGoMGGoMGGoIdZzzpMCTBgwIABAwYMGDBgwIABAwYMGDDgNZP97ydnDwE9LGwaAmwIBmwICmwIGmwIGqxVwU87A1dxGgh2jQzNAAAAAElFTkSuQmCC"

View File

@ -0,0 +1,7 @@
// bottom buttons
// =====================
App.KL.Game.Phase.Draft.Assets.bottom.list_button: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAATCAYAAAAeVmTJAAABHklEQVR42u2Uuw3CMBRF3TEATZoUNBQgKhChRaJgC5QVGAIkClpK1mALVmAI+sCLuObG8bMcCIgCS0eRHfv6yD9j7mW62BXZ4VzMTheL1AHa9teiEaEstMvcBhJtC8SKWInRcFMxk3raX5dk42MrIE+yeeWlXkp0eysrgM4YILwrgBzOhojMbSU0AZ9IzPa4AppITYI7uYMhwtvmA+fAN97Nf0lCkEmwlC444NrY1iU0virxXwk8MB9biU4yt/BVAqGryXK+sYDn8Eq4naS+TJ8E34XHCyhfHgN82ep2TJLcgoB8sC3hN98HBNAfIIez1e3QRNzQJoQEahL8AzKfwJ2jIgF439xDxLcgBPfT8nhOg8KNGjEi/D8m0/xKuQG23r4JXV13wgAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Draft.Assets.bottom.chat_buttom: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAATCAYAAADxlA/3AAABEklEQVR42u2VMQrCQBBFt/MANmlS2FgoVoraChbeQnIFD6FgYWvpNbyFV/AQ9tFZ+MvPuLMmEkHEwA/s7sz/j0yibrrcl7PjpZyfr0GyhrB3uJWNlPLCvmQ7ubUdXhfCA4yG2wqRrPP+xms2PrUi+Ik3P3FZu25vHcJRiGLRu6HohQ97A0KyPYAVHoV4NKYeuZzrfguiAsAFsWYO5znGZEHoUTQCENUJh/4Avwmgf0hafQk72SKIPxetVxBybvVyxhOALpD1Kk+LQ1N1Me/oCCZZEYTmYrDzsgB0OOp1H3tHR2BBaEOWhKfOU+EVAN4EyCekMwIAxHPSLwz+TtkkJq6z/DjTycUblupA8HkdT/cN1x3Wm8bj6iLFvgAAAABJRU5ErkJggg=="

View File

@ -0,0 +1,37 @@
// ASSETS
// user and allies card
// =====================
App.KL.Game.Phase.Draft.Assets.card.button: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAAsUlEQVR42mNgAAIzl67/5tPP/7fY8QCM+778x4ph8iC1ID0MpGjGaYiudhuKAIhvbjwfKwbJIVsorBj/nwFEwDTLqhXh1AzDIDUwQ+AGwDSDMMgWfBimDqQHxQCYJDEGwLwySA0gZAhOA9glHOEYZhA6RlaDYQCyAg/ZIqwY2QKsXjCRSARjXAbA5DG8ABOAGZKo1Y4VI2sG0XADkA2BSWLDyPIwfeAMBeMgBxI+jKwZAA9Tzqish/WQAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.card.divisor: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAACCAYAAADsDAqEAAAAGUlEQVR42mNgl3D8P4od/zM4qOX/H8X5/wFLCtMnRwvN3AAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Draft.Assets.card.name_divisor: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAABCAYAAAChQ5zUAAAAKklEQVR42mPQlgz7z82j9R9Eg7CZSxcGjYzbZT/AaWpgZDORMTa3ILsVAD4KYiEWiGpBAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.card.attr_bar(i: Nat, j: Nat): String
case Nat.cmp(j, i) {
ltn: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAADCAYAAABBCiV2AAAAGElEQVR42mN4nf3/PyHMQJSiyRmv/hPCACSbVe0aeuODAAAAAElFTkSuQmCC"
eql: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAADCAYAAABBCiV2AAAAGElEQVR42mPo+/L/PyHMQJSiyRmv/hPCAAScWQUsjAs3AAAAAElFTkSuQmCC"
gtn: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAADCAYAAABBCiV2AAAAGElEQVR42mPg5tH6TwgzEKXIzKXrPyEMAKotKJyhzZc5AAAAAElFTkSuQmCC"
}
App.KL.Game.Phase.Draft.Assets.card.attr_icons: Map<String>
{
"damage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAAATUlEQVR42mNgAIK+L///W+x48J8BCwCJg+QxBNA14BKHS8BMgbFx2ciArhDFelwaCCpEVoRuA0ETcdqA7DlsiuGexBk82IIPb/CgaQAAVVyucYmp1skAAAAASUVORK5CYII=" // offensive
"resistance": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAALCAYAAACtWacbAAAAQ0lEQVR42mNgQAIWOx787/vy/z+IZkAHMEl0DFeMLoFVjChFMKsYsACcVmLjYzgcWRGGL7H5jmAwYA0rgoGJrhBdDABa1bsEjscb1AAAAABJRU5ErkJggg==" // defensive
"mobility": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAKCAYAAABv7tTEAAAAQklEQVR42mOw2PHgf9+X/ygYmxgDOgApgmF0xTg1wTTisgWnJnTN6M7Fq4lkDVSxBT00sRqASxNBm/EFO9khCRIHABDzAc+vGvQQAAAAAElFTkSuQmCC" // mobility
"range": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42mNggAKLHQ/+9335j4JBYgzIAKsgkmY4B6YI3UQUeZgAuqnIpoFpFA6Sqehi5CnEazXRniE6eIgNcADtwMQtWOgT0gAAAABJRU5ErkJggg==" // range
"utility": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAMCAYAAACwXJejAAAAU0lEQVR42mNgQAIWOx787/vy/z+IZsAGQJLoGEMRzBSYBrymIdM4rYOZiKEQm/HI1qNysJgO1ozuI2QT4dZicwtGUCAHIDpGMRmXKRhhhc0kmBwAbSTOuAXc0NYAAAAASUVORK5CYII="// utility
}
App.KL.Game.Phase.Draft.Assets.card.active: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAGCAYAAADHYm6gAAAANklEQVR42mNgwALMp5//TwpmIAaAFLJLOJKECRoOM7Tvy3+SMF7DyTUUr+GUGorVcGoZim44AHENJuRrYpF/AAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.card.main: String
"data:image/png;base64,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"
App.KL.Game.Phase.Draft.Assets.card.allies: String
"data:image/png;base64,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"

View File

@ -0,0 +1,16 @@
// filter
// =====================
App.KL.Game.Phase.Draft.Assets.filter.background: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAADQCAYAAACUVDZIAAACE0lEQVR42u3dO04CQRzA4em8ghaegNgKrYln8EaaUNhyFW7BFTiChb2rf5Ihwz6QfUST5dvkFybLK/OxL6pNqVgen9fVcrOrVtv9oRjXy89F759fs6qc27m5xzisUtty7YiTYMaK8gPe7j+qxd2LWgqb0uqIWUeEdVkNTIjTYCa78zS7ecoHTjDDyiegFANb47itMgxTPo1DGVa+bAQ5FWRsmiDHQYYhSJAgQQokSJAgBRIkSJAgQYIEKZAgQYIUSJAgBRIkSJACCRIkSJAgQYIUSJAgQQokSJAgQYIECVIgQYIEKZAgQQokSJAgBRIkSJBQQIIEKZAgQYIUSJAgQYIECRKkQIIECVIgQYIECRIkSJACCRIkSIEECVIgQYIEKZAgQYKEAhIkSIEECRKkQP4H5HKzAzkSMgxBggQ5T8jVdg9yJGQYggQJEqRAggQJUiBBggQJEiRIkAIJEiRIgQQJUiBBggQpkCBBggQJEiRIgQQJEqRAggQJEiRIkCAFEiRIkAIJEqRAggQJUiBBggQJBSRIkAIJEiRIgQQJEiRIkCBBCuQfQT4sXsH0LMxOIPNKOP0h4/EEEuYwxFZImP0ROyHzC9Vd3atziyy7uX3ST+cwW4+REPtjNs7aEIdhNi7IHf/6HyuP15Fx468Ss+uXyG+KmyleQ5d6hN3h5mmxxKDeJV+U/xHNoTyf3+bdZhWG38iSLQn5ZPm+AAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.filter.icon: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAbElEQVR42mNgQAIWOx787/vyHwWDxBiIAcga2mU/gDGygQQ147IJZBBeQ2C24LMAZghWS4j1J06LQIIgGwbWAIq8AJMg5Aq8FsGiCZchMEvwuhQ5ISFjklImLg3o4kQnb3yGDx5DGMgByGkCABtMGgikVxUvAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.filter.input: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAPCAYAAABQkhlaAAAAUElEQVR42mNgAAJd7bb/IxkzIAcCu4TjiMTwwBjJgYAcGKMBMRoQowExGhCjATEaEKMBMRoQowExGhBUDAgzl64RGwggv6N0vEACIxWDwgAAd8ufnGfNeIEAAAAASUVORK5CYII="
App.KL.Game.Phase.Draft.Assets.filter.check_false: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAKklEQVR42mNgAAIzl67/7bIf4BjEZ0CWYJdwhGO4AnQJZAUUSOK1E59rAea0VhRBV4/wAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Draft.Assets.filter.check_true: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAJklEQVR42mNgAAIzl67/7bIf4BjEZ8AmgaIAmwQMUyCJ1058rgUA9IdvWCCrT8sAAAAASUVORK5CYII="

View File

@ -0,0 +1,16 @@
// footer
// =====================
App.KL.Game.Phase.Draft.Assets.footer.stencil.main: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVR42u3OIQEAAAgDMCyOGPQvCDFuJuZX03tJJSAgICAgICAgICAgICAgkA48lJQATI4CDw0AAAAASUVORK5CYII="
App.KL.Game.Phase.Draft.Assets.footer.stencil.left: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAASCAYAAAAZk42HAAAA60lEQVRIDcWWwQ2DMBRDufbWKxt0A2bpIp2HoToCO3AEfSRXVsGQT/KTSihgOf5+FNR2z8driTj64b3gGMbvdm7r/7lddyU+ERCWCYiUtQhMFEhqLkCzYVIHRvoA85nm+49ZZEFPdjaMZ1i0Nwsmupw3/zaMd1CuH0Xt5VZZ8LjeGRUWpaOkrUVhogpf5QLI7rrysufyN1OF1NC5qJrHnlMYFVBL56JqJnskjNpcU+eiai57DmHUxto6F1Wz2bODUZta6FxUzYdn999MbWilc1HVgT2/b0aZW+pcVPVgzwajjK11FD3rAY89Ziu/MPx2bdASCAAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Draft.Assets.footer.stencil.diagonal_left: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAASCAYAAAAZk42HAAAA60lEQVRIDcWWwQ2DMBRDufbWKxt0A2bpIp2HoToCO3AEfSRXVsGQT/KTSihgOf5+FNR2z8driTj64b3gGMbvdm7r/7lddyU+ERCWCYiUtQhMFEhqLkCzYVIHRvoA85nm+49ZZEFPdjaMZ1i0Nwsmupw3/zaMd1CuH0Xt5VZZ8LjeGRUWpaOkrUVhogpf5QLI7rrysufyN1OF1NC5qJrHnlMYFVBL56JqJnskjNpcU+eiai57DmHUxto6F1Wz2bODUZta6FxUzYdn999MbWilc1HVgT2/b0aZW+pcVPVgzwajjK11FD3rAY89Ziu/MPx2bdASCAAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Draft.Assets.footer.stencil.diagonal_right: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAASCAYAAAAZk42HAAAA1ElEQVRIDc2XwQ2DMBAE/c0vXzpIB9SSRlIPRVECPeRJdJGMQNjOGN8qRrJAx2pvx2BLDsHhGqd5jWMYn6dnq8Vxvz1WxWjGMIAYktwVEObZBLKHUAWkvpdBXst7+xK0mVJ3CaQ3CJugapAeIapBeoWoAiEQ/1z86NeqhbBtWLmwU94/QQgE0aSae9aKICQg0XgGznllQUhAosk19q4nQUhAovEOW/I7gZCARFNqqnh3ACHbZ48QNjEbCIEgGsVsE88vCAlINKShShNowHjWUAVp9f0ACML8do5nEEsAAAAASUVORK5CYII="
App.KL.Game.Phase.Draft.Assets.footer.stencil.right: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAASCAYAAAAZk42HAAAA1ElEQVRIDc2XwQ2DMBAE/c0vXzpIB9SSRlIPRVECPeRJdJGMQNjOGN8qRrJAx2pvx2BLDsHhGqd5jWMYn6dnq8Vxvz1WxWjGMIAYktwVEObZBLKHUAWkvpdBXst7+xK0mVJ3CaQ3CJugapAeIapBeoWoAiEQ/1z86NeqhbBtWLmwU94/QQgE0aSae9aKICQg0XgGznllQUhAosk19q4nQUhAovEOW/I7gZCARFNqqnh3ACHbZ48QNjEbCIEgGsVsE88vCAlINKShShNowHjWUAVp9f0ACML8do5nEEsAAAAASUVORK5CYII="

View File

@ -0,0 +1,4 @@
// header
// =====================
App.KL.Game.Phase.Draft.Assets.header: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8AAAABACAYAAADVjh7eAAAF8klEQVR42u3dMZITOxAA0LkCESegiEhJdhOusAkk3IBg4w3ISTgBCSc1ZaqmcA3eXXs80nSrX/AK+PDtsdRqqaXx7PTxzbfD3u7ePh0iXAeQx5Z5Y88c1PO9I39O8wDWFogHoIdJI0jy2kf7AlBjTnC9QPUNbwUwkHIxkn0Rd3//w6IQCueIc9dnXAPmfAUwSGoAAIACGMjh1tNOxt44sQkEyM/Xv3bk3CmvowCWxNC3IH7BuCHxBqr4AQUwOAk0QYpNQo4h49BYrDhPtHjdl/pD3rS+AAWwQS4h7/jeva9j+X5iFsAcBiCvKIAFD5KVUxIwzgF5BVAASySIOe0LIG/E3VRtseGa6TZwG+D4io8CGLBYBJBTFTyYkyHduJmiDFqJglsnegsE5CHIG+O9nulgnAPyugJY8Jg8tTsAAFDvFmhFBpcWo2LltnGTqf0uOV13Ao+NL2DP3BA9X8hn0HaMLNeiz73epBHJdrvz2n7dMh6ivhZcElNiDqxnXK+cCE6AAQBQWCEesOE98NhSAEPiCW5+L7cfW+QgFgBjUlv6GkDmz9HrYYgKYANe34gJjA0QQzTv/y03a3vFo7jXNvSLpeWvCmAAAEUD7BpjYpgWsXL8t5/e/eoSXwpggxkxhBhFTEA6vv4jfzDG95Tn4vc4po+/vnZCrABGQkIsJFus7fE9cUAuVsgirokcT06AAQBAIabdGXrDaz717RVTCmBofFuHdiLqgiPCa635/5wWWRgjbip81ojtsccTexl7TO0RRwpgDFbcYpewsFozToyt/79zpC0wbvRJtmvZ+/P3fmIvxrYCGACTHtodMaVdS3xfU3/W+VwK4ES3Vhj8SNSw38k98lC095QzxdiId8vMv18+sff0vy//vXYlokkSALCwAgAnwJQugAEUmWhfssecuKXC7cg978JZPrH33M9tBQUwJgIg9a29xjniDfAUaHlzhLw9mZQA6k2MvXN5lIWSOcxizvWCmMcJsFMS3LqGsWgcik2AADk2c962bqNMASzYASz60LdggwpwAgwWZlhoAeYjxIp4BAUwABY5AHK764bkBbABAX1POz0wRq4CcMdP7OvJOOf4MUeMlhucAAM4dbCBYIMFQH6Tt0u0rwKYYQZMlR+tMsrnNMEA8gYYG6AAlli4sP31Sd5bz459d7ylSh8CAJXW+tY+wQpgHSJYodf3iY5F9GkRbIzJfyD2QVyDE+CdB7EkQctYqRpfI58Ayxlx7zwAxh2LW1+TXA4KYMWNRMiKODn++aUTzspPVjSmtCdAhc1sm3egALa4RDwV+Q6sSR85XXuBu/dAfCqAofBtYvOp75wAq54CmwC0LWADE2DIAviSxVjEBZtFpEV/y2sUXxaRjDnejW3EhX7TTjBIAVwxuA1ofe160H8AciMYf2OM70lyRH/6XGD8AWBe0Q5OgAsG/ukTe2fLn1m6dDpoDB5wu7BJ+7rrvvb61zxETm4Wi5gbxDz6HAVww8UWgEm1TfssNyVHaLsMmz/iEzAHowAusMPoib2SoUTrZAGbkmBxjpgBBXCpxOHpvZL62ve3aYLx5JpB3vB5XSMogCU+QrV/7z6uElNOWOUskFPkh5EOQrb89zYgIXgBLOC1ByAnaGuFHm77N861G5Q8ATbAAGIsYFrl4wh53lxD9Tww4oPfIm0KXdqWLdp8r36UV1EAu1UVAMAJ8GCnmpnbzF0gMNB3gLP/zEr0GdB3DBvLGAvGgPYCwhfAGZOPJ/ZidxgsmF2/PkUcAApgydPnQvsi5iC9jJvdxnau/jj39/oQFMAmAQgW863fx9i14AfrBXo9L0b/A06AsSgA4xmMDcDXuVAAA5B/krbgR0xpb+0C8EoBLKkA3LYYk0dB0UTNmBJnkKwAfnj/eLjG5w/fX/z7Lw8/D9e+JrTwWqzyr43OtZX2E/c+f1vXzpfmV+NBX2oHfQa3mzQCME9UX+9+m7AsODZ9/7VF21avQ72YPH2/534PgAIYwAJxgH6z4Ee/P/7dzDtti/nPNlVAHnSt/AFkyaqjh+F2cQAAAABJRU5ErkJggg=="

View File

@ -0,0 +1,48 @@
Velocity: Nat // move to constants TODO?
6
// ready button
// =====================
App.KL.Game.Phase.Draft.Assets.main_button.ready: App.KL.Game.Assets.ButtonAnimation
{
[
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADY0lEQVR42u2bPWgVQRDH01mLjYUpLAyopJBo4kcS0AQMgfhIEcHGoMRC7dIoErBTFDRiUJsQxUJrLYJNGq0sVLAXRLC3ECxEzszJPHb37e7N3u67e8/7D/x5d3tzx9z+9mM2txkYgPWVTWx8zqwXxp58ylA9MBgMBoPBYDAYrCGGJRAMBoPBYDAYEipYWfD3f2a5ghsB31xV6+FA0Ut0cKZEcZoPqOLl6gbYS+aCJ+YRRb+k0UdJ54dJT5z/65AZKrq3zSe6BZSApz4/FGSdlSqpiyL/GHDWeKTOXNEmACkE2329ALJMhYaA4d7CSgWvPQ2lfiBUrXKA4/MP+0qj03ehbWkAmejk1rdcnGio4mto+d3R0Tdfc5nDLomvsa8VIOD1D0QN4OHjq+3hiY5J+0ZXcvH5xKkXtWps5GmjNHzwVq7BoeVcfM7DJx23Ae45dMULr26ITYXng7hr76IdoAteXRCbDs8GMQpgaoity5vZpfUPVl189D6bPf8qfzH6pXOX2O/M9vNi/M7e2Momp/41HPqlc7XcLKsCXnKAKVWUGNGkfeL0Yy0Dc/nNLL0s9Ftce1voRz5T555l89dea+V0bpb5Kj2lehqgz6iiKWD6lfjR+8T4/fr9pw2RxH6uMgBUAKot2wfQ1mvuvPvSAcb3PIkfAAYCtMHylbn+OiG5twgqAAIghlBOToqG0IWbm1aA0iFUAlB9nnreeIC+5ETtaT4/qmgbQGkS4yqjjJOzVdO4cTUaIAXj6lkhPdAF0OwxoQCPjD+wQuS46FpjAXJg5vxEMCRzIM9HvGZzzYHmMBgCkGPkdaN6jcqqgicCuHN/K4dYBUA1MGnCEpPExAK0xVklPBUgxblj90kdIIkAkrrdC83AygBUP7uoioFF+vj9R08CVHsfwSNpO/uqgmgLrgzA2OREmuwUAVS/ENQGz9xNZYOYQhyIKbNiRubuFZa5Knz66vMOWJIyW3ZJ86ovTtf7dEOF8HwQ54ZXojUzuOwUVRR/CaBjSZlNdH126HrHvZIyUwutNVGcVUgMzwWRACwdW9WUCh6k68KB25qoLAheCESJzIAguUrD8w2nsQkLJFcUPBdEXivyTjXs20wj3nXGa7wk8EyItNhn+SACSHl4tDhnJf0PLuzXrGnbvMD+AqO1w8ibJ9kNAAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADlElEQVR42u2bPWgUQRTH01mLjYUpLBRUUkjk4kciqAGTwHkESRERgyEptBGCWAVEBUVBA4ofEFErY6GFTRTEQgXBQgV7QSzsBcFCZPW/8JbZufnar5nbzXvw527fTHZn5rdv7u3OpK+PjY2NjY2NjY2NjS2H3fgVRTwKbGxs1c80PNswQLZQNvLgSwTxSLCxhYg+TJ/KCBy6+9lrWPJcng8eqQsinD4h4lq+b5o632giPGWb6hARIYCHHhc58rRRKBaoBqoO0dKUmcIETRmF1gqWDprA1xmc7aYODS9pl3NFSyddO9vL0HV9qnoqzQou1aa8f5jpLnEYnFBQXdul+u3JOvBy9lgEnDeArGoVA2yNXlvzGp68WTulABLR3S+/xaIMTBSV8Z1fjfa//h6L3nmKojKqqwTI8OoDMQVwYMflZCrBd6h/60IsOh4afNg4jRx83LPatXcp1pbWYiw6pukT3xOAGzbPGOE1EWId4Jkgbtp5Wg1QB69JEOsETwWxEMC8EHUN7pxajebvf0xp9vaHRBMnnsd/j0/RL4vqHfl/PlM9XA/XPXr2Vdd1oWOX3kSjk0/jOvjEseiXfT7glQ6wTNkSI5TvO3zHqd7Y3Iq13uzy+6h95lkqo1PVGZ9fiaYuvEj5cSz7TINepnoaoMlQjra51kN/TAZwlMGp7PefvwlEiOrpfAxQACPe2SaAqqi5+u5rF0DV+VQAdfUYYEaAKlgmn0oyfHQWMEwAdT4GGBgggWGAgaZQSk5sU+jU+VUlQNcp1AWgeD7xmAEakhMx0kz1Zm69VQJ0TWJ0PmSclK3KRq+9GGAJEagDKEdMVoDDE/eUEAkeyhig9NsGGC6/gahHOjT9KFkSsk2DWQDS4NFzo1gGny94TgDXbTwQD0JdkxhxjSxXtBkAQjJAn/BEgGjn+m2dNEAIACHfUZgHoLj0BdEySxFY0KcfP3sSoBh9gAcpd6aFgJgHYNHkxPQmJgtAcYUgGDx5b6gKYpWSYQ22r1t9ugEfP/ekC5aLT5Vd4l0oDR4kAxTLqpYVngniWP9CpUICQisF+O7ig+RVBAx4p3Ux/szqkzV9fDlqDyymJJ9DLq9KzvB0EDF4J7dfSalqqDb5GjzfmtuzlBJ8meBlgRhKciebqtzwTNNpaPlO3UOqEDwdRHpWpJ1qvG+zHNGuM3rGKwWeDBEP+yTfENcKPDyck0r9fwzerxlo27yD/QMEAl4/ylZhGgAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADhElEQVR42u2bPWgUQRTHr7MWGwtTWBhQSSHRxI8koAkYA2cIEiEgBiUp1EIIgiIBsVEUNKKohaJikVQWWkRB0mhloYK9IIK9hWAhsvofeMfs7Hzt7czu3uU9+HO7b172dt9v33zcbhoNNjY2NjY2to61wYefE84CGxtbXLv9K0kgzgQDXB/jat3GVivAsukOP/mSMMD8OTPmjcuzw81Kl42NrYQBkhfEHdx92sZAHhtrPtwRPK7C+s9LMsUGYDJArrb69YoEUstJdXIl1gueSw2foDww5Yqu6y8ZVZ+bCshUYcEAqhduunhdd2xKmBobM6F0zkVvUNNxTDlxfW8INWIenBVfAuDQ1N1kYOwmK4KQ21hKASSie998E6Lyl0VtfOfH0cjadyEaE2VRG8VqATK8zoGYArh7/1Kr5Pt2XhPq6V0Qov3B/qcsTw0fWi4sMIG2DSwK0T51n9huAdyy66wVHkOsBp4NIphpAZrgMcRq4OkgFgIYGuLEyZfJ6fsfhOYff8xo8syquDB86trVuGMX3op9OqYqfB++9+j/eF378ctrycjosojBJ/Zlv+orA15wgCHlmhih/cDhB15x43MrzrjZe++ccYgZnXmWTF18lfJjX/XhGmyJD6VaA7QZ2nFuvnG4niJxv//8bUGEKM7kKwOeE+CmrbO1ACjf2TaAuqq58f5rBozteD5xDDAnQB0sm08nF3wdQJOPATLA9d2F0uTE1YVOX1nVAvTtQn0AyseT9xmgZXIiV5otDonWAfSdxJh8mHHSbFU1+tmLAQaoQBNAtWLyAtwzdEcLkeBNX33NANXxCTB8xkAaj2jNZhoD1W4wD0A6x+b5FwIYGbbhKwueF8ANmw+Ki+jGSUwRgJRAFWCZ8GSAgLdx+2QaIASAUNlV2A5A+dGXrCKwoE8/fqZ8cgKrBChXH+BB2jfTqoDYDsCikxOfyY4KSQdQfkJQGTz1jS0dxJhSYfU3bzl9JoBj555nYPn4dLPLI/MrreRBKkC5Lbac8GwQx3sWogoTEHoSgG0fn05on+i9lPlbH58sPMmYOfEoafYtpgSg9OQD22p7LHnDM0FE8k7tuJ5SbKhVqSwoJs3tW0oJvlzw8kDsNqnJq1ptw7N1p92qspcEPioEzwSR1or0phq/txlG9NYZrfGCwFMhYrFP6haIdYOHxTkp6H+K8fuaFb0272H/ABnNt042vxY0AAAAAElFTkSuQmCC"
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADLElEQVR42u2cP2gUQRTGr7MWGwtTWBhQSSHRxD9RkAQMgRhSRLAxKGnULo0iATtFQSOGaKdiobUWwcZGKxsFe8HG3kKwEFn5Ft4xOzf/9nZ2dvf8Hnxk983bzdz7zc6+2duk16PRaDRagE0//ZJBzMQoAiTdjtvDX1kGMRMEOFJTVqcAcgql0Wg0Go3GaoxGo9FotPLr6bpvZ1yzd7gWkSdmBYi+B9mj9qC7DY8MVRADQAy5N8Xnn0NttJ3A1U6LA88E0wWuD9B2YOgJQsFWHQh1Dp66B2nZfJZRL/YJqbTKAU7N3ac6qAJAIXr83fdc+lQKSRtHfj0qk3sjQMLrDsQCwInDd/qXJbahsfH1XLI/PfmcSigbB5VTH+Ce/atOeITYDDwXRDAzArTBI8Rm4JkgVgIYG+LCpTfZle1PVqG9TNz5qzuV4i7cep+dmX2Vx+An9lW/7ksBzwRw35FrwwOMKV9hhPZT554Exc2vvfbGrW598MYhZvbii2z5xtuCH/u6L1WeVC4zy4/bBdBlaEffQuPwearE/f7ztw8RkjibLzXAoyc32wtQHdkugKar5t7HbwNgXOcLiWsbwANTG+0GaILl8tmeToQc64PaNoCAR4AdBQhonQCoT2VSnPim0JXbO0aAoVNoCED1fOp+CnidAWgrOHxFDBJtAhhaxNh8qDilWtVNBlcKeCN/BdoA6ldMWYDHZh4ZIUq/0JYCXmcAyrQVcg+U+5Gs2Wz3QH0aLANQ+ijrRrUNvlTwggDu2ns2/xCjWMRUBWjqZ0p4KkDA231wqQgQAkAo9VU4DED1axdVVWBBn3/8bBSgDx62AQ8q/D1nkxCHAVi1OAktdnwAY+ZnaHj6m1ImiHVKT8zk4gOvz5bwuesvB2CF+EzVJe6rrn7GzIFAsskLzwVxfmy9ViFR8k0AtkN8JqF9YfzmwLEhPl0rS1tB/YyhxYkNp4Lh2SDil1w+dLeguqH+L9JhrZ3YLAi+UvDKQKSqSYcVDZ5rOqXqLVhUVYJngyhrRXlLiu9mlhfWcbpOP/uaS9Z4UeDpELHYFxFiPfCwOBdF/b89fF+zodfmA+wf5FOrSpH91yIAAAAASUVORK5CYII="
],
0,
Velocity
}
App.KL.Game.Phase.Draft.Assets.main_button.waiting: App.KL.Game.Assets.ButtonAnimation
{
[
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACjElEQVR42u2bP0sDMRjG3ZzFxcEODgoqHaTSqqjgn0EHEcdOotjF0dlZRUFBEBdRJ/0KgvgBHETwE4ifQXAQqb6Bt+Zec7m73L/Wex544C55k7vmd8klbdrVBUEQBEEQBEEQBEEQBEFQFNXOn5toBQiCIAiCIAgq2irg+L2pHGlFoBeMXNhRfC1g+20LPwfyiF1BjCctqwfG9d6itkWYzxZ0jShW9SdVGZyPFcDptdOOcnXxEP6xByATnX14U565fPljzsOTn44n7l6VaWiU5jyONQIEvM6B6AE4PnXSGp7omDxY3VXm85n5m1xdq1wVyuXRPeXS0I4yn/PwScctgP1j21Z4eUMsKjwbxN6BdTNAP3h5QSw6PBPEWACzhAh4KQHMwrYPU0TnAlCftdYP7lvpdMzpMs40K6Ob1qfQprSkyulxm2eP1ljK/9cAqW4WQdLBsmScFOVxo7O4gcOU02PClJPXtMVyfQDoCFDvHXq83ouCAOo9Kgggr8PY6IEGgDqcIIBsU+Ob8vwASlB+AGWjjlWOAFDGyQbNAqBfmgTI70T0QA1g2HdZOwDU76GQ70D9C3MTwI/Pr7YHaKqvEAD9jk2N3K5DaFsD7BleVRDzBigbHgC9AAled9+cFyCZAJKT7IWmoVEOk50EMK91oN77CB7Zs68oLYim2aVpag6AMeDJzU0miK5ebtw2GxdPygv169bN0DFNwTlNnttiZJxLnkuayfJaaTkQng3iSnk3tpdKO7CjQ8Pzg0gAtiZPPAa8dLwxsu8xpUWCFwViGMsbgsPbGZ5tOMXvedk5Fjw/iLxW5J1q2LeZjHnXGa/xEoEnIdJin22DCCDu8Ghxzk70/yPYr5nTtvkQ+gbL1ixB5J+IaAAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACwElEQVR42u2bMYsUMRiGr7MWGwuvsFBQuUKUu1M8wdNCCxELCytRvMby6gM7BQsPFLERtdJ/IDb+AAsR/AXibxAsRFa+wLt8892XzOxsZncy877wspnky+xMnkkyYbMrKxRFURRFURRFURRFURRFURRFURRFDUHPf08mYrZEgdp4/T3Ak0+XrFvQ4cUs8vtKf+JxHdrRAK9hS2jsoTxo6GlNHKVrHYPaNDZWr28PRl3jdXW9s0A7ALFtRbofDgDXrz0bvS/dflGcKwBBdPPzz2CM/9oo45PfjS9/+RW89fbHAaMMsS5AwisHYgXg2pkn06FE0uLVk7vBON44925w3tr+0Fufv7gffGJ9LxjHGD4lPQV45Pi9JLwhQiwBXgrisbOPfIAxeEOCWBI8D+JcANtCnOUmCK9jgKU61UB991IA6rfWO48/TfMljXwbZy1lNsbLa1JP3uCkAfTreOxNUOJ23nxLxkr5oAHKuSE0KBoVsnFWGrI9V5N6OgZgUvVQV4OOCecjwJYAde/S8boH1gHUPaoOINZhMHugA1DDqQPofQ/iMec1AWhBxQDaRt3cfkmAHgD0rHkA4sabAIzlWYCYE9kDMw2hMYD6xnMClONRz4F6fvIA/vn7r/cAvfONAmAs7YGedwgdJcBDR68EiMsGaOuWAFDPjV3NiwAo8A6fulUFKBaA4py90Bsa7TBZEsDYOlDPjV30St37BJ7Y3ReTG6L3dqmHxxwAY40/FIC18OzONA9iW1+9+37y4NXXYEnbfOTZ41SMzsPN3dj5GIYusaSRHytrk+c5VTena+GlIF5f3e2lb67tjcKN4cUgSmPdP/20YsLrxg8v7FcseTPBmwXismxvcqhuDS81nPL3vMV5LngxiFgrYqca923mMXadYY2XBZ6FKIt9eNEQxwJPFudw1j/WcL/mkrbNN9B/u5qbBaYnxLEAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACuUlEQVR42u2bPUtcQRSGt7MONhaxsFDQYBEifuEGskmRFBJSWFiJ4jaWWy/YKVi4EAk2oqmSfxDS5AdYiOAvEH9DwEJk5QycZe5xZu7XzL3j7vvCi/fOnNl7ncczHzo2GhAEQRAEQRAEQRAEQRAEQRAEQRCkdPy/3yfnrwygpdPrfsydFeP70TvF3m9QUbKuDKwyM6GcmajDq3oYhbIlFQMzcpKFJucZd+WDY1wE1P1uEoYNUBY3ijSC47ECuPbte3/x0xEcwNS3oZwAyESX/94qc1rr5jr85Ifx+393ys3zm2fmOo41AgS8lwMxAXBhtTdI+fk3B8qTMx1lvl96dwFndLP1q7SJCXl6savM9zx80vUA4Ou3e054gFgPPBdEYmYEaIMHiPXAM0EsBTAkRB8dwB4meN4Bwkm7Ot6XawGor1o39v8Myumay2WcNNXJGFOZr3Z63M6PS2cs1VcBLxXg+NRWEID02SzuFO5AloyT0iHLz8rSzvQOrnbyma5YWtIDYAmAenbo8XoWpQHUMyoNIO+FyQSvfXYFgLY4jnEBND2H413vIOMlKBtAOectt04AMK1DqwBoK5MAac7j34YgAz0MoVUDJGgjPQfq85MJ4P3DY/QA5f3IALRdmzo51iE0aoBjEx8UxLoByrYvASDNhaHnRQZI8F7Nfk0CJBNAss8sNA2NcpiMGaAEZtsH6nNjiKzUs4/gkY3nYnxDNK0uTUvzGAEymLoBpsKTB35MEIv64+ZPtfQm07Us5zJ574qRcUXq0sq+tH+rTqOvNCTabIrjMp9OheeC+HmyM1Jen+9G5czwbBDpm9qeO0wY8MJ4d6WXMJXlgpcH4rBZdl7dLgzPNZzi73nVuRQ8G0TeK/JJNZzb9GM+dcZ7PC/wJETa7LOHBWJs8Ghzzvb6fyo4r1nTsfkMegJcSUS65FGGMAAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACiUlEQVR42u2bu0oEQRBFNzMWEwMNDBRUDERxVTQQDUxEDAyMRDEy3FgwU1BQEMRM/QrxF4wEv8CPEAxEVmqglpqiuufdMyP3woXe6prH9tl+QW+nA0EQBEEQBEEQBEEQBEEQBEENUvfhvU82K2+++n0ymqmlInhOuhAE1Tz2ohUgCMJIyIvNwZpFBq2hMqkeKgbBZd4yJOV10twMbq4jgEtbV3ALHQPIRJdfPyNzF5bmOvzyq3GWtjcBAl57IMYAzs1eDLollcnjU73I/Lm78AQHtIuD5DQAODJx6IUHiPXA80EkZiZAFzxArAeeBbEQQEAMD88CODZ/mh8gHN6Sy9reXRiActW6f/4yiFOZ4zrPWpXpHCtW1nUy7/j+zZtL9aEBLq7ehgNI92Zxo3ADsnSeloSs75XmOusdfNfpZ/py5XcKAXBy6ex/AZS9Q+bLXpQEUPaoJIC8D2OH7IEErxUAJZwkgNZzON/3Djpfg3IB1N9vfuE6CDyC1hqAukFDAHTFNECeE0P2QALWKoBZhtDQAOU7hJgDGV5jAMr5yQL4/fPbeICuH2WV8BoB0FW2GrmpQ2gogBpeKoBDoxsRxLoB6mvbAFDOjTwvWrG88CRAgjc8vRsHSCaA5DJ7oTU06mGyTQBd+0DXFidrT02CR2WCR44dxK4KorW6tJbmAFgAnj5ab0HM682D52j4IFNZxzmmP/tydF6eujwxy1nv5zJDcjkRng/i9ngPrtA7c2dep4bngkgPOZq5jBkNXw28k5XbmCmWCV4WiHAxa1ilwfMNp3B1+zztQvBcEHmvyKekcDYzu2kfp73++BGZ93ilwNMQabPPBsRq4NHmnF3qH25xXrOmY/Mp9Af2GLkUugzdkAAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACnklEQVR42u2bv0osMRTG7azlNhZaWFxBxUL24j9U8E+hhYil1cXLtbG0tlZRUBDERtRKX0EQH8BCBJ9AfAbB4iJ7PYGzZo5JJsnMzuw63wcfzCQnmWx+k8xkN9vRAUEQBEEQBEEQBEEQBEFQiMZOH+voBQiCIAiCIAiq2irg8LWuHLQi0AsGF44UXwvYPvvC5lQemSvIcKcVdcPEti20L3w+W9o1Qqzqz6syuBwrgFOrx23l0YV9+MMJgEx05u5Fefr86Ys5D3d+czx+86xMU6M053GsESDgtQ/EBMBfk0eN6YmOyT9Ht5X5fHruqlSP1S4q5eGhHeXe/i1lPufpk44bAHtGNp3wyoZYVXguiD/6fpsB2uCVBbHq8EwQMwEsEiLgNQlgEXZ9mCq6FID6W+va3m0jnY45XcaZ3sqo0fortCktr3J63J+Te2cs5X9rgFQ3iyDpYFkyToryuNNZ3ME+5fQYn3Lymq5Yrg8AIwHqo0OP10dRGkB9RKUB5HUYGyPQAFCHkwaQbep8U54NoARlAyg7daR2AIAyTnZoEQBtaRIgPxMxAjWAvs+yVgCot6GSz0D9C3MTwLd/7y0P0FRfJQDajk2d3KpTaEsD7BpYURDLBig7vh0A6s9Gfi76poUCJHid3bNJgGQCSM5zFJqmRjlNthNA2zrQtsTxSQsdfQSPnNhX1CyIprdL06s5AGaAJzc3mSDGemnjur5x9qA8v3bZaAwd0xTCafLcFSPjYvJi0kzOUp9sp8up8FwQl4e3M3uxdwuOtDc8G0QC8HfiKGHAa47XB3cTprQgeCEQfSwbBPs7Gp5rOsXvecU5EzwbRF4r8k417NvMx7zrjNd4ucCTEGmxz3ZBBJB4eLQ4Z+f6/xHs1yxp27yH/gNKH2VxbTXTHAAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACw0lEQVR42u2bv2oVQRTG01mLjYUpLBRUUoiSRDGC0UILEQsLK1FMY5k6YKdgYUARG1ErfQOx8QEsRPAJxGcQLESunIHvcvbkzO7sv3t3dr8PPjJ79sxmd347MztksrJCURRFURRFURRFURRFURRFURRFUdQY9Pz3bCZmS2SojdffAzz56ZJ1T/R4M4v8fbm/8bgP7WiC17A5NPZYXjT0tBRH6VrHoKbmxuoN7cWoary+7rcOtAMQm1akh+EAcP3as8n70u0X2bkAEEQ3P/8MxvivjXN88/vx5S+/grfe/jhgnEOuC5Dw8oFYALh25sl8KJGyePXkbjCON869G523tj8M1ucv7gefWN8LxjGGTynPAR45fq8U3hgh5gCvDOKxs498gDF4Y4KYEzwPYiuATSHWeQjC6xlgri5roKF7KQD1V+udx5/mcSkjbvOs5ZzN8WIp9eQLThpAf47HvgQlb+fNt9JcOT9qgHJtCA2KRoVsnpWGbK+VUk/nAExZPdTVoGPC9QiwIUDdu3S+7oFVAHWPqgKIdRjMHugA1HCqAHq/B/mY81IAWlAxgLZRN7dfEqAHAD2rDUA8eArAWMwCxJzIHtjREBoDqB+8S4ByPOk5UM9PHsA/f/8NHqB3vUkAjJU90G2H0EkCPHT0SoC4bIC2bg4A9dyIeTE1VhegwDt86lYRoFgAirvshd7QaIfJnADG1oF6bqwbq9v7BJ7Y3RfTNUTv61IPj10AjDX+WABWwrM70zyITX317vvZg1dfg6Vs44jZ47IcHcPD3dj5GIYksZQRj51rEvPc5nr2PstcCa8M4vXV3UH65treJJwMLwZRGuv+6acFE14/fnhhv2CJ1YJXB+KybB9yrG4Mr2w45d/zFudW8GIQsVbETjXu2+zG2HWGNV4n8CxEWezDi4Y4FXiyOIc7/cca7tdc0rb5BP0HDgy+ncy+DfkAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAACvElEQVR42u2bv0ocURTGt0sdbFLEIoUBE7YICbsb0UBWC1NISGFhJYo2ltaCXQIWLiSENCGxMm8QbPIAFiL4BCHPELAQWTkXznLneO6df3dm7u5+H3w4c+bMznh/nvtHr60WBEEQBEEQBEEQBEEQBEEQBEEQBBkd/x8OyfkvVqDut8thzI0V4/vRO8XeblBRsr4KrLMyoZyVaMOruxuFshUVA1M5yaDmPP2ufHCMk4Cm303CcAHK4laRm+B4bAAufvg87KwcwRWY2rYqJwAy0d7ZX2Mua9t8DT/51fjNn3/GSz+u7pmvca4KEPDGB2IC4KuFwajk288/Gs8+3Tfm8+7Ln3BGL/VPS5uYkOc6B8Z8zt0nHY8APn6x54UHiM3A80EkZipAFzxAbAaeBrEUwCohhmgA9iTBCw4QTtrX8KHcCEB71rp++HsUp2OOyzxpuiZztFio++y87a/n3ly6Xge8VIAzTzYrAUifzeJG4QZkyTwpG7L8rCz3ae/gu08+05dLU3oALAHQrg47366iNIB2RaUB5LUwmeDtfr8AQFce5/gAas/hfN87yHwJygVQjnm9/hcATGvQOgC6YhIgjXn82xBUYIAutG6ABG2qx0B7fNIAXt/cRg9Qnk8NQNex1sixdqFRA3zw6K2B2DRAee84AKSxUI6LWiwEQIL3cP59EiCZAJJDVqHWNcpuMmaAEphrHWiPjb5YiOojeGR1X0xoiNrsUpuaxwiQITQNMBWe3PCjQSzq5Y0TM/Um07GMc0ye+3JkXpFrabF3u79Mo9FX6v5c1vJ8saJOheeDuDq7P1Veax9E5czwXBDpm9p69ilhwKvGO68HCVMsF7w8ECfNsvGadmF4vu4Uf8+rz6XguSDyWpF3qmHfZhjzrjNe4wWBJyHSYp89KRBjg0eLc3bQ/1PBfs2Gts1n0B23elaG/0rHdgAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAAChUlEQVR42u2bu0rEQBSG7azFxkILCwUVC1nxhhaihY2IhYWVKFaWWy/YKSgoCGKnPoX4ClaCT+BDCBYiKydwlpPDmcl9ksj/ww+TmZNkMt/ODWaHhiAIgiAIgiAIgiAIgiAIgiCoQVp+eO+TzcKbr36fjGZqqQieky4EQTWPvWgFCIIwEvJic7BmkZnWUJlUDuVbMCaZtwxJcakeBjfXEcCl7Su4hY4BZKIrr5+RuQtLcxl++dU4S9ubAAGvPRBjAOfnLgbdktLkieluZL5e7jzBAe3iIDkNAI5OHnnhAWI98HwQiZkJ0AUPEOuBZ0EsBBAQw8OzAI4vnOUHCIe35LK+fxcGoFy1Hpy/DPIpzfk6zlqV6Rgrr6z7ZNzJ/Zs3lspDA1xcuw0HkJ7N4kbhBmTpOC0JWT8rzX1WHXz36Xf6YuU3hQA4tdT7XwBl75DxshclAZQ9Kgkg78PYIXsgwWsFQAknCaD1Ho731UHHa1AugPr7FjrXQeARtNYA1A0aAqArTwPkOTFkDyRgrQKYZQgNDVDWIcQcyPAaA1DOTxbA75/fxgN0/SirhNcIgK601chNHUJDAdTwUgEcHtuMINYNUN/bBoBybiw6L1rwJECCNzKzFwdIJoDkMnuhNTTqYbJNAF37QF/dyoRHaYJHjh3Ergqitbq0luYAWACePmhjQczrrcPnaEghU1rnc56+9sXouDxlefIsp6lbGjMklxPh+SDuTHThCr073/M6NTwXRHrJ8exlzGj4auCdrt7GTHmZ4GWBCBezhlUaPN9wCle3z9MuBM8FkfeKfEoKZzOzm/Zx2huPH5F5j1cKPA2RNvtsQKwGHm3O2aX+4RbnNWs6Np9Cfyk3o2jRAXQZAAAAAElFTkSuQmCC"
],
0,
Velocity
}
App.KL.Game.Phase.Draft.Assets.main_button.cancel: App.KL.Game.Assets.ButtonAnimation
{
[
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADYUlEQVR42u2bvWsUQRjGL40QO3MWUUEkIhZCijQxhYUEtNBGCCFgk0IwKAEra/0HrpJcd0mhJGCKNCliIUGQXHFwkCIB65gmXbBJEcZ55zKXmdmZ2Y+b3b27PA887Me8u7O8v5ud2d25SgUaKH1hrIosQBAEQRAEQRAEQRAElarpepshCxAEQRAEQdDwij5K4sNk9Cmg9o8Jp3oiUA9MfXBGeLIugKxU1NzbHMsj7gRPGvtaouW66aStjs7nO3+/tIIsyUzSGOLqSGNx/lAnK8JsZeVyvVbrLn1WY831YbAA+Kt6f7A8MgZzawDp100+f/Zc2JY4WSZjS3FMixtknz+eEbbBkmUy1goQ8AYHogZwtTrRBUXr5Pd3JoXlNm6bxXp15Ibw0uhdYbmtlncBEigfvNIhXlF4Poi0bQXoglcaxCsOzwaxJ4C9QDxcfMvY9rbb6+ts88EUY41GZ3try+56nW3enGBsbc0dw30495r9nOR9xsaGO46XUQzF+s5FdYk6ed3qdXy7fiuS7NDwggPMajEQ8anVYq1XCx14PvHktWZfMNZs+uN4Z/93aZmxoyN3DC8TMTSI8InXJeokcMp17Dyc8iY+lPsP4PGxAKaZg9uZfqon6eCgs01LH0BaJ6uwTICnp5dx0ru77PfMrA6Q4s24C1gAaLQ21QTPliTbLz8CkAOw7dMA8uWfdx80EzxKigbworWZSQTAOIA8GUUAtCUIADMC7Ja7kkS3Tkpu3C00MED14VrCBEAXQN+vPOkgJiRAS30A6AIYd5s6OekAoGVRAGmwQ8dI80cNALQBTNjPCAiB+kDaRh8YAmCKJAFgAoASYpEAKZmqaUif9yjUrHP/5Rz7PnYvAjDptZlx9FYnT4ASngZQhZhnK9QAmv0MWT5U5wXw7CxaZ7stIHr7QNe1yf7Z0l/m1fpUeAKgOi8mb4hZX1cFAxj6VZpnxFoYPHNykw1iCFPF4oWx52MmlX8dHWd784vdfbROF2/uo7gfC28ix5r76JbWXP7orFPe9rJcmytOJjqUY+H5IH4ef9SzP127DWd0Ynh5QQSEAuGFhggIJcDzQUzlAp6Nhtk9wXNBpFZFcHyz1zBvM73lbDMCR60vCLzMEAGkf+Al/f9E6VPuLVPnh2HKfRI2/wGfwkJ/aJYi7wAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADqUlEQVR42u2av0scQRTHzyZgmVwKiSGFEkISkGBjLCyCkCtSCSEkpDlCIIKEFCEIqcw/cFXwutPCoBARGwtTiATFKw4CVyikVhutJI2FvMybu3fOzs7O7a27e7Pe+8KX3Z15d7c3n3vzY29yORaLxWKxWCwWi8VisVhO6jtAHs0twQBZDJDF6sXscyYDuSuIBo+7UQbI6ha40j8ANEPMWLahJyp1CQ+PPoBYMVb+A2nd5ELfTUC73phQKgG62/Ao81T7AJJNINOE61ImLOSHAJ10l2XKtDD2wQtyENSwsXr20S/btSxs3dv8vNEEs13G2GwC1wk0H8SoL+zU2DD6OYF0ygHwVMt7bx7187QtAf7uu8XOD2fOHoD0C7x4Oi5t+pJU52TmpJB5SfvieUHaBIvqKNYIkOFlB6IHIA7eBIqm+NP996TpmrvNdE0z4JnBEWm6VutbABGUDd61hJgBeDaIeG0EGATvWkHMEDwTxCsBjAxRfOhB8QPAxkawl5dh9f4oQLkMsL4ebFG/ensIYHHRGnfw8i1sjYhxe2Xlslz/zLU12JoohL+3SuWyTJz/uPvI19hxw4sdYFTLCYNN1SrUJl80GtomUS/jRLxV4vOOpj8CHB4Gxxwfw9Hn2cYkwqZaDWpTrxvgSOJ8c+yZteHjsnsAsVERgGoBZvPBqBfg/n7jGo82gPQeKiwd4NmZBOHxzg7sFqa8AAVUX1wTFgPUsk01wvMBJFimMhWgeG9TmQSIQJpg/n756jHCw0bxAGxmm96IDLAbALF71ACaGogBRgSoxxi7UHxduy7UBFBAiQpQXVwTTAYYBWDYSUycAHUJUAwwKsCTk8YkBI9pAcTJDr6GLJYaDDAqQHEuJyJhx0Ds/iwA8ZrHQFcB4jqtVwESxDQBIhjVu+OT0WehzclGGICq62+K8HP4iQ+gHofLDRNAPQ6f6iQJkOB5AKoQk8xCD0AcZ3BsU729LSEmBvD83Du2oet1CdE6BqJpwa8CPD31xzXHy6SyT4Xn2xeTNMRIj9LiBBj3ozTLjDU1ePrONBPEuIwPl21/rGL9Uv8A7L0qtsrwHO9FL8O4X+8/tdZq+DB6afChrwy7tOrsXOAfqNTtyYfZlj9a6f333s20jaOGjstt4dkgzt2446S/DTzuCYeGlyWIDK+NXIbI8ELKBLHrTmG95YqvBC8IImYANqRt9xrv2+zctNsMwWH2xQLPKYgMLxcLxLTt2Y6vbGlPyi5tmQ8L7z+EV/72JDc4RgAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADsklEQVR42u2bv0scQRTHzyZgungpTIQQEkIIAQsbY2ERhFgkjSBBSCMhEIkIgUDSJv/AVcHrTguDQkRsLJJCRBSvODiwUEhtbLSSNBbyMm/u3jq7NzN3tzc7t3f3HnzZ3ZnZnXfvs/Njd+cyGTY2NjY2NjY2NjY2NqN9B8iiOBIMkC11AH3T5TupwwGycf/KxtZlLZCjwPDYErTcPwCUdrijTF/OLPXdgjQHKw3+RUGN5sswXjgEnq900KTSpoxKllog7uuaLoc0PfCwFVJLDMGzQWTz27qWsg8AFhelcB8V5SQBRhNJkMsFamY8wLJxzvNhcX+Ta2gqHBWQmkaSLKpbnTI2cCxH0oBpRCo8E0QJcDf7EHb7BlhJCGObkEIA6W65ejYmpXOG8rhVJdPyrl5MSulgUR6V1QJkeO3vNhuFGAKIAyiBwsEdNdd/T4qOuTv0223SxGZ+aFiKjtX8ACAWsMFjiO2BZ4OIx1qAJngMsT3wdBBbAtgKxOPpNwCbm2atrsL6oxGAQgFga8sskS/LifLGMuJ6WN/2sBi319bMdYo8LFPXt+VlWL8tntXy+es0sf/j5p1KXJRgu4bnHGBcycHdZsUilCZeVoJjM5Evy4nyVhP1/Z1bADg5MZcRebJMHN/E/q/HI9bAu1L6AGJQEYCqakBCQTo6qhzj1gaQrqHCigK8uKitc2cH9scm4vmGaaPP2w8QgXkHWL2jVWGAdEHS3fk1AMW1dWkhgGL758PHkBCeybeo/zW+ia6aAbYBYKO+MUAXQcKuE8+r14U6Bqg+lJOfDDAOwEYnMS4BauoLfMMZLgNsAuDZWQUAbn0BxMkOnkMSjxrSNwGLATYLUOxLCI7GQDyO5ZsIHAPsVIDVIKYaIEH0CRCDqQqn9EnPQqN1Hr6ahp8D982+ffoitT85pQVI+aTt8clEARK8EEAVYpKt0DrOoOihOimAl5e1dZbLEqLWt9PTa+3tSYghgOfn4TKojY1EW58KL1hs5gti3NdVzgC28iqtVILS1EwYoM5Evld46tJB/FCog+hK8oWx5SMo5q/0D8LB69kgDffRl2galvs9867m3GgavqguLnw21onwgpfZlo+xx7PvYWXoCRy8nbd+kMVyFGhXqgsvBFH8ABXi1xt3e0rfBp+mSio8WthUd/19r0LseHjR9ZO9BLFr4Nkgdq08PMfFnbzQ2NrSSmaCiHcq/mDb6jVet9m8aLUZgsPW5wReT0Dsdni6/xR4WU+Z4nWbPtUIm/9EUE+KQYHp8QAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAADEUlEQVR42u2asWsUQRjFL40QO5MUUUEkFhaBFDaaOqCFlkEEmxQWwRBIZa3/wJW50hQKAS3SaiFBEK8QDlJEsE6qdMEmRRjnzd0cs7Mzs3uT2dvb8z143O7MtzvD99udmd3bVouiKIqiKIqiKIqiKIqiKIqiJkjvZ24I2Fkp2m0BM00NFeB56VIUVfPYyyxQFPV/62GnJ9p/xdDYzxSqAsfwqVeoHErTTEc6nyHrRwa73AQIt8ydMiem63cO4PeZObqBzgDUdC8frSq7DtB1vAuq8Si5dwIkvOZA1MwUQEyWOkhPnpuzd5T1Poes8bqIA7bVHQiKCAgdRIj1wAtBxP5wCDUB+uARYj3wXBA1QLG7m78DiwBeBeLv9ZdCHBz4vbcnPi8sCdHphONkvYqT8aE4tPdtRc4Z+/v+OFmHmKi+ye2P128my08o5zbArdsr7iG0DMBYq4k6pG5X/Fp72k9OSLJexcn4oGR7p5vbQpyc+GNknYqJ6Zvc/nL/QSW5CgKcv6cARt+BSQAiqQBgepCQTJKOj/v7+A0B1OcwYdkAz8/zbR4eih+ra3F9qwPg/NKEABxc0aaRDFeSXFd+DqA8t6ssA1D+/nm9kzHg+fpm979ugIBGgBJa2b5NEkAAm0iAhUnC0InjiobQxADNh2vdz9oASmjNBVh2EZMSoKO92gBKYM0GeHbWB4DfcQHEYgfHaMtHjVoADuA1G6DcVhASzYHYb8QcaMAjwKYBtOCVAqghjhMgkmkaS/qqV6F2m0fP1sWnubvRfbPj8FYnNTwToIaXAWhCrPIuDM4zsH6orgrgxUW+zV5PQYzqm56fHfNlFfDMbcBTAM2vsquGGPu6KhnA1K/SAivWscGzP613QUxl9cI48Gcm6j/MLoqfzzeGZdhGX+wyxH198Sp3rF2GIa27/cbbph72Yvrmixs1LxqMz4XwQhDfXrtFV+h3i8tBl4ZHiFMAjxCnAF4IIl3dc55v8RIFzwcRVw46EPpyii6wfI6zffn4iTLA4e5LAo8QpwCeDZG+ggdARnEZNv8AJdH8aPxbaOAAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAAC4UlEQVR42u2bsUskMRTGtRG0O7nizkIOG7srrLS2PEsR4RoLCxEEq6v9C2wtz8ID4a6w9YpDBHGLA8FCwVorOzsLiXlZ3zKTTTKZJJOdXb8PHjszeZm8fb9MkpmdHRuDhko/xz+IegUQBEEQBEEQBEHv6N4IgiAIgiAIwoIKqgAv9veV1e4EXDlX7+FAcZWUwenmFad+ghxfbtAA2yQbPG8eUfQjel3d848acNeV5wO1l7/oHhAZ+LAMZ76xVvnHgDPGU8vZEoDPF0uRnLZcCXXA8NXClgpebxpKfUJYXlMAz8enYUNoJYBM9GVxSZmpApeh5zdjdXJvBAh4wwOxBJAmV3biyXZrclYZ72PIymtVHHhBpACSg6sSIA4Gngsi7RsB2uAB4mDgmSBGAYyBeLv6XYiTE7sdHoo/H+eEODhw+8ly5Sf9XX7U3r+vcs44Prb7yTLyCYpNbv+a+pwsP66cJwUYamqidqnTEf+Xv3WT45IsV37S3ynZ3sPWjhD393YfWaZ8QmKT26fzC43kqv0AKakEoGhvCSkl6eamu0+fLoB8jiIsHeDTU3+bZ2fiYmk5LLZ3DfCtRxeNkmFKkqnn9wGU5zYdKwGUn3fbuyUjeLbY9PgBsCUAfWMDwBRJoqGT6lUNoYkBFm+uOU4ADAHou4hJCdDQHgCGAnx87AKgz1wAabFDddjkrQYARswzCkKiOZD2MQcCYPsAMsScACmZRaMlfdOrUL3N65VV8Xv6S3Bsuh891WkSYJFR6Rf5IrimIDrnGTK+qW4K4PNzf5tXVwpiUGw8Pxvmy6auviK83oteuSCGPq5KBjD1ozTHijUbPP1tKlOFVKYeGDt+zKTyo8lP4nJto3eMtikW/Rj5/V3f7KurH6MhrbPzw9omD3shsdn8UuetEp4L4t7EDGyA5g0PEEcAHiCOADwXRFg+i4Jng8g9w/XmFKy+cT55pEsCDxBHAJ7vX6BgDb0276FXP5xnf1C1Y1gAAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAAC8ElEQVR42u2bv0scQRTHtRG0i6SIFiGksUthFWtLLSUE0qRIIYKQKrV/ga1lLBIQksJWC5FAyBUBIYWB1FrZ2VnIZN6cT2ZnZ97uzc7s7t19H3y53Z03N8/3mV+7t87MwGAwGAwGg8FgsAhT+/sKWYDBYPlnGsw2AAjryj7PPlEkZAIG62L00fTpHYFtD0vM5XHwWCVeQbJTPpf3paPZ8LwxjcOI6AJ413lxR15wFIrDs6PkTeuuT4LmHYWVDjUbmyTIlWtOD+A9xlXbsWZjVX9sn6FXJbAv4AoxxVYcqZeMEGSfpyw3viZ1m4JrDSCUVwbgj9lFaAxVAMhE71+vGfkqcBl6fh6NknsvQMAbH4gFgLSYshPf+2zPPzfic0xZ7aqKA2+ADEBykCoBYjfwJIh07gUYggeI3cDzQWwEsAnEv1vvlDo+DuvwUH1/+lKpgwPZT5cbP+0v+VF7Z6/0mnF0FPbTZeQTFZs+/rqwlCw/Us6TAoyVWaglGwzU7/WNYXIk0+XGT/uLptu73t5V6uoq7KPLjE9MbPr4ZGU1S676D5CSSgBsPSSkkKTLy+E5fUoA+TtsWC7A29tym+fn6ufaelxsUw3woUfbomT4kuTr+SWA+rt91woA9ee/nY8FEbxQbG78ANgTgHVjA8AUSaKpk+pVTaGJAdo31xwnAMYArLuJSQnQ0x4AxgK8uRkCoM+2ANJmh+qw9K0GADZYZwyERGsgnWMNBMD+AWSIbQKkZNqiLX3uXajb5p/NLfVt8UV0bK4fPdXJCdBmVPhF3gaXC6K4zpD4pjoXwLu7cpsXFwZiVGy8PnvWy1yjz4ZXejMtN8TYx1XJAKZ+lCbsWFuD574b6quQSuaBsfBjJpV/mX+mfr15/3iNjikW9xr5nb79UKrrXqMpbbD7KdgmT3sxsYX8UuetEp4EcW9uGepQteEB4gTAA8QJgCdBhNpTI3ghiNwzpDenoNHF+eSZLgk8QJwAeNI/GEItvDZfw/4DD/rF9VCqA04AAAAASUVORK5CYII="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAAC7ElEQVR42u2bv0scQRTHzyagXSRFtJCQJl2KVLG2NKWIkMYihQSEVNb5C2wtY5GAkBS2SRFECLkiIFgYSG0qOzuLMM6b84XZ2Zm3e7Mze3Pn98GX/fV25/E+O/Nm9/YGAxgMBoPBYFNrH+YeKmQBBoPlNbW/r0jIBADej7paWm0VAfZNt/SJR4kAxZjQPTFkwGCwTgUSPXCKh0+pBqI2Fl7uGB56Yfnzklpns3dgJlrmqMggvZzcneiJZcFr0qCN0zgw3TunxDcZk47NBRTqYckA+hob986RxvLcCW1KUNu2Q9cJ5aQLmGwAobJkAJ7OLUJTqApAJvrv5aqR7wQ+hjs/j8bJvRcg4E0PxApAKrTsxIV3Z37FiLcxZPWrJg48OTIAyUE6CRAnA0+CSNtegCF4gDgZeD6InQB2gfh747VSx8dhHR6qL4+eKnVwIPvp48ZP+0t+1N7357pmHB2F/fQx8omKTa9/WlhKlh8p50kBxsoUasmGQ/VrbX2UHMn0ceOn/UXT7f3d2VXq8jLso48Zn5jY9PrXZy+y5Kp8gJRUAmDrLiGVJF1cjLZpKQHka9iwXIDX1/U2T07Uj9W1uNjuNcC7O9oWJcOXJN+dXwOor+3bVwGol3/evquI4IVic+MHwEIAto0NAFMkiYZOOq9pCE0M0H645jgBMAZg20lMSoCe9gAwFuDV1QgALfsCSJMdOoelHzUAsEOdMRAS1UDaRg0EwPIAMsQ+AVIybdGUPvcs1G3z/NWG+rz4JDo214/e6uQEaDOq/CJvg8sFUawzJH6ozgXw5qbe5tmZgRgVG9dnT73M1ftseLUv03JDjH1dlQxg6ldpwoy1N3juF1u+E1LJvDAWfsyk4x/nH6ufm9v/99E6xeLuI79vW29q57r7aEgb7u4F2+RhLya2kF/qvDXCkyC+f7AMTVCt4QHiDMADxBmAJ0GE+lMneCGIfGdIX05B44vzySNdEniAOAPwfH8KgXr8bL6F3QJheklNpnq4FQAAAABJRU5ErkJggg=="
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAwCAYAAADJuP4nAAAC2UlEQVR42u2bsUscQRTGz0YwnWKhKYKksUthFWvLpJQQSJPCQgTByjp/ga1lLBQEU9iaIkhAvCIgpFBIrZWdnYWM8+Z8x+zuzLvd2Zm92833wcfd7rzZHd9vnJkd114PgiAIKqHvU7OKjEx0ESDotlxqb0+RkQkA7NSQ1SqAGEIhCIIgCMJqDIIgCIKqP0+nns7wzN7itQjvmGUgjtrI7tpG9yRsGdogCkAcuXfFm5/DLvRdQCqH4sBzwZTADQH6Kpa9QFmwdTtCys6TupNWzWcV92JfEG7WBuDvqTm4hc4AZKJP71eNXRW4DD0/javk3gkQ8NoDMQOQJlcO4sl2c+aNMR9jyGrWozjwgsgApACpEiCOB54EkY6dAH3wAHE88FwQawGsA/Fm/YtSp6d+HxyoH/Nvldrfl+N0uYnT8VIc3e/XOz1nHB/743QZxQS1TX8/erUYLT9SzqMCDLWZqCX1++rP2odBciTpchOn40Xp+91tbit1e+uP0WUmJqRt+vvZ8kqSXE0+QEoqAbD9kpBMkq6vB8f0KQHka9iw8gAfHor3PD9XF6trYW37rwG+9GjblAxXklw9vwBQX9t1LgNQf/7b2smY4Pnalm8/AE4IwLJtA8AYSaKhk+qNGkIjA7QfrrmdABgCsOwiJiZAx/0AMBTg/f0AAH02BZAWO1SHrR81ALDGPGMgRJoD6RhzIABOHkCG2CRASqZtWtKnXoXm7/n347o6mVsKbls+jnZ1UgK0GWX+Im+DSwVRnGfI/FCdCuDjY/GeV1cGYlDbeH52zJepfvtseMOXs5qCGLpdFQ1g7K00YcXaGLz8m1KuCrFsNoyFP2ZS+eHMgrr89HV4jr5TW/LnKO7n541C3fw5GtL627vee/KwF9I2X1zsvI2EJ0H8Nv0aHqNLwwPEDsADxA7AkyDCzbkWPB9E7hnSm1NwdXM+eaSLAg8QOwCvyj9jwAlemy+hZyavpXTnTEuJAAAAAElFTkSuQmCC"
],
4 * Velocity,
Velocity
}

View File

@ -0,0 +1,7 @@
// hero portraits
// =====================
App.KL.Game.Phase.Draft.Assets.portrait.hero.background: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAABKCAYAAADAKbZGAAAAcUlEQVR42u3bwQkAIQwEQNu4GuTasSPrVvwdeE+FBGZhyXcK2JSSNfVp4609ZJftF7tuxG7oyNgvGhgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY+Dg43QY+3ZeBXMwEjZrO46oJAlgAAAAASUVORK5CYII="
App.KL.Game.Phase.Draft.Assets.portrait.hero.border: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAABPCAYAAACUEffIAAAAnklEQVR42u3asQ3CMBBA0RuLnZiFeRiHASjpCSKCyOAUoFiWD96TrrT87cKVIx52x9N0uFyHnntjlDJEV/FldHWigVSdGaLX4iNL9Hv8HB7JCBf+F+GZXpTyZRHePRwAAAAAAAAAAPhl/mT1Dvdhsnf4eT+lC5+bhQsXLrxZ9BKeJf7Z+hI+evxq55b4cu2n0yR6S0DvaXp7395gqz1uy7Mq9gTE4rAAAAAASUVORK5CYII="

File diff suppressed because one or more lines are too long

View File

@ -5,15 +5,51 @@ App.KL.Game.Phase.Draft.when(
event : App.Event,
): IO<Maybe<App.State.local<App.KL.State>>>
let players = global@players
let room = String.take(16, Crypto.Keccak.hash(local@room))
let room = String.take(16, Crypto.Keccak.hash(local@room))
let ready = Maybe.if!((x) x@ready, players{local@user}) // verify if local user is ready
let controls = local@draft // buttons controls (hover, click, active, etc)
case event {
frame:
let main_button = controls@main_button
let init = main_button@animation@init_loop
let end = App.KL.Game.Assets.ButtonAnimation.get_limit(main_button@animation)
let actual = main_button@frame
let main_button =
if actual >=? end then
main_button@frame <- init
else
main_button@frame <- main_button@frame + 1
let controls = controls@main_button <- main_button
let local = local@draft <- controls
App.set_local!(App.KL.State.Local.game(local))
input:
switch String.starts_with(event.id) {
"HF": // HF = hero-filter = name of hero to filter
let local = local@filter <- filter@hero_name <- event.text
App.set_local!(App.KL.State.Local.game(local))
} default App.pass!
mouse_move:
let default_controls = App.KL.Game.Controls.Draft.default(ready, controls)
let controls = switch String.starts_with(event.id) {
"R": // ready
if ready then
if controls@main_button_hovered then
controls
else
let new_button = App.KL.Game.Assets.ButtonAnimation.Button.new(App.KL.Game.Phase.Draft.Assets.main_button.cancel, 0)
let controls = controls@main_button <- new_button
let controls = controls@main_button_hovered <- true
controls
else
controls
"btn-header-": // hover in header buttons
let event_id = String.drop(11, event.id)
App.KL.Game.Controls.Draft.header.update(event_id, default_controls)
} default default_controls
let local = local@draft <- controls
App.set_local!(App.KL.State.Local.game(local))
mouse_click:
switch String.starts_with(event.id) {
"H" : // Set Player Hero
@ -33,12 +69,17 @@ App.KL.Game.Phase.Draft.when(
case player {
none: App.pass!
some:
let can_ready = App.KL.Game.Player.has_hero(player.value)
let ready_u8 =
if player.value@ready then 0#8
else if can_ready then 1#8
else 0#8
App.new_post!(room, App.KL.Game.Phase.Draft.Event.set_ready.serial(ready_u8))
let can_ready = App.KL.Game.Player.has_hero(player.value)
let ready_info =
if player.value@ready then {0#8, App.KL.Game.Phase.Draft.Assets.main_button.ready}
else
if can_ready then { 1#8, App.KL.Game.Phase.Draft.Assets.main_button.waiting}
else {0#8, App.KL.Game.Phase.Draft.Assets.main_button.ready}
let local = local@draft <- controls@main_button <- controls@main_button@animation <- ready_info@snd
IO {
App.new_post!(room, App.KL.Game.Phase.Draft.Event.set_ready.serial(ready_info@fst))
App.set_local!(App.KL.State.Local.game(local))
}
}
"T" : // Set a team
let player_count = String.drop(1, event.id)

View File

@ -0,0 +1,32 @@
App.KL.Game.Phase.Play.Assets.interface.top: String
"data:image/png;base64,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"
App.KL.Game.Phase.Play.Assets.interface.top.dead: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAvCAYAAAClgknJAAAA0UlEQVR42u2ayw2AIBAFqcAC7NOjXdiuwXjEaFTY3xBIOO8MMXzemlLl2KclS85kOaThTSU0CppJaBZSl7BYJbUalt+peC2PnUKspts2J1HbE76ZIQJ8NUsk+N9MEeE/s0WGf2UkwD+ykuBvJWjwV4l+BKiTL7DNaybPITAEWuDPgYanChQHAhqeJmCaspmldmj44lJEen1FFkA/4tExCjrIQkeJ6DAXHaejGxr4llI3Tb1E3Snce8NIAUkJ11NfQsL97tUqEeLyiPvBQ0NCguEALTFIyZF1RbwAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.Assets.interface.top.life_placeholder: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAhCAYAAADZPosTAAAAqUlEQVR42q3WwQ2AMAwDwA7AAjwQAyDW7LqMAAKJDyRO7aRSv6dSk6StJVdfjvPe87Q+uwzbt54Dv1gKtDAZ9DAJRBgNRhgFjmDDIIOFIIOFJ2QxCCqYC6qYCWawH8imCUElTRdU04SnU9KEdxfVJ/XvRd2DrgzU2xAIq8K7I6nvWXOBqgYEUmlGIJ3m6CfTfc5aUpoqKA3ukhmLwPSjp+R9YoEl2AtWYReM1Yo9Nul7hAAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.Assets.interface.top.life_green: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAYAAADtNKTnAAAASUlEQVR42u3MuwkAIAxAwazlkk7mOPYRBAt/YPIai9wAJwLlqsqDkpQH3mQKPMkWWJNjYEmuwWsSQQR/BB0ObokZDtbEDQcjgRrIJQkoZdOOigAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.Assets.interface.top.life_red: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAYAAADtNKTnAAAAT0lEQVR42mNgoBD8W7fkP8UG/OUr/U+xAWQbgmwAWYagG0CyIdgMIMkQXAYQbcioAaMGDA4DQIBiA3AZQnLWptgAdEPILuYoNgBmCKUlPgDWlzbp+XS3GgAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.Assets.interface.top.ap: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAALCAYAAAC3ZUeVAAAAMklEQVR42mNgQAN9X/7/xxAwXPTpP4YAXBBZACyILgAWRBcgXhBsCYYAsiCKgzEEgAAAEsBkeRIf5ncAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.Assets.interface.top.portrait_placeholder: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAFRUlEQVRYCb2Yv6pUVxSHb2sXUhhuZTqVi4GAfwoJGFsRUgVSpBEjWNj4AEICClNYBJF0Vr6CoLcR8gJh7jPkMSLKt+d8x9/Zs/eZmTveXNis/Xetb/32Omdm7sHBKf+uHD37uE+bC3tyvPj44cN/Y5vbu9Uazi6c/2GrZuCjw5/X9veCAVza8jN4b+/GeQBwdvnwzhpAK4m3fzwclWqt9wJyjnayD7RXhb34za3SFvd+LY5xvnz1tDSDsUZT5d7NtKD1kUq39nXnqFeBCfzTdz8WUCB1ihqTdrwoCaRKgOyqdMbtAuYCsAQhmGrhZISNmpsAk4D7hqtlvQXMXMYkFuNR6eF87mn2hb317fVyvZntRmASWa4SY6/J9oCFBpI4jOu4TUgnhfXgmG28dmahQ/kEpq7noIGlAStwSWK5mNyCnMUmLM4JIpwKqJjzBpqUxRA8gTnfA9a3vv68877Edn4C6aCG5QETuMAtF6tXzpzSQzkkvAnOAZf9xyv/7AeYxhmajKOtYVEigc0Ux/YFwarMaIc3h3s811O4Bv799m99YGEPv746ubIWMEqbNVYg7PL5i3HNfSaDZX8dgwSYK/sGMVAWYG6XM9iJsukk+wILKEQpj+H6UJRgArkXSwL/vn9bGusETv+qLbA+gKXpawRGWTbrRGvWAptpDfzml0fFMc4TTkgta+zVr6BpTRxLPIHpF+CETeh0msBCkzVOgVcJYGgtaFTDDy0Bs098/LKXhv9UtwALOWfngIHNs4yB/vvxkxGc4My/e3itlEVC1n1iCZ0PIPuIc2AwJxynVRmvRZVVl71cO/uAYgygpUA/oWvIenzl6Onn7yRDaeAbvxPgHjTzHKiBUQIYGmUALPuAwzlzNOGx+KgB6zHA7LMk6HeBW9AJDCQOrC2uX2hrGGVNIqGt7xowxyQKnP4TtqlwHravE0G1OBVSaK2glgVjlGes355NYJWFYSdgIBM0YX3AhKyt0ACz1gMFiDWBKYlTAXOoht0GmEQsA6C3AebTrQYmiZ0UVl0fAuvLcugprLJagPE1p/DewKrLOzE/4QhMvQLdAhZSq7qbgImnMNi6LMbXmvWT2eO8vLwrWJwIPAftDQANMHvx14OGQWBhOcfcWkk4oU1YSwCF/fRhnXnfCqjcUtq3A/sKzAbgCfRy9dA1a1hQbIEdvoALWzKOH5XMkwCQLWhLAcseYE2SpPMmsy+wcVNd1iYlIXRRMr54jLBRGipqDQuNdU3LHACbgMf4wzvbuue8a2vAqmuAsQwCljVhBNbW72ATcV7liZPK5rWz17rHMm4C+wvVh0p4rhBwr8mHCSuIc44NZHBBUY3GmGQSHCiEyL36Ye3GX/+sfnEwAJZ6AQwnBdaajV8MOhMsLcEc5z772ho6ldYHe00MnyOsv5FS3fI0+/O8AWtg4VrWPT0rNCoLTF9gfHK2CSu0JcDVo7SH6qBmrsMErvduGgP51blLpTzyOfDcmrLCaoHeBVjHu1gTJlEggfZ5QGFfgRthhQZYBzVIBqvXth1bDgDXZSDw1rBCC9wqC0ugBWhCrbWcY58KZ93S3xlWaMF6NgGyLzTncj77NTCge8H2oHHKNd6//Xr2oQSIvT1o5vXFbdJOraywWhU2wM1rzwsw3117QAK3EuMMZ2kkT/tisEIDiwo4B5gH06A9aGDdU1vO8wl6JrBCCwswrz/e1TVIjoGqoQvo8E2QtS+urLBaYL+/9KCA+PGdEHwPYSys/fEb3/Dvrf8FVmiAhSYwH+u9dvfqy5Ic+7KdubLCagm4T9PPrvYTWNZKhYRd7gsAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.Assets.interface.bottom: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAABBCAYAAAAKeLsHAAAEyElEQVR42u2dTY7UMBBGe8cFWMCCE4xYw5ZLzBW4ySzZzlU4BBJX4AZs2DcyklE6cuKyXVX+yYtUQrQ0mX75XM/udJK53RbcPr3+vGsUPPBckYctE/bLh99qBQ88V+JhE4b95t2Xpvr49NI9dHjgYVtQLiOEDg88bAvLpWfo8MCDZC4glx6hwwMPkrmQXDxDhwceJHNBuXiEDg88SObCcrEMHR54kAxyMQkdHniQDHIxCR0eeJAMcjEJHR54kAxyMQkdHniQDHIxCR0eeJAMcjEJHR54kAxyMQkdHniQTKUILJ59EQOfJexYuQEMDzwePF59WrR9+3O/5+rI+qWVe/MMYHjg0RGMZp+WOqLoB7c70HjQzplkZg/86f3zQ8EDTw/BaPZpqSOq5BJK8yleKwsmvrZKQ8Izn2C0+jQcn1JPVAnG6xGBDGB44BlHMDWSKRaMtlwQDDzwzCOYUskUCcZCLggGHnjmEkyJZMSCsZILgoEHnvkEI5WMSDCWckEw8MAzp2AkkskKxlouocLViKliAMMDj5znqI+s+/dMMqeC8ZBL6nqEla6zoCHh6XVdTyyPHj6SzKFgvOSyD5oBDA887TxbLq8+TkkmebGdp1wQDDzwrCGYvWSKLiv+/P3Xg5nC//evx9cQDA0JzzUFc3r7T27lEmWyl82+EAwNCc91BZOUjPRjkUQyCIaGhOfagnmQTOk5l5xkNAUT9he+apst7KMBDA88HjwjCOa/ZGpP6qYEU3MeJieYWULfMkUGeODpwbOEYDTkIhXM6KHvw84NYHjgseSZXjBaq5cSwYwa+lHYuQEMDzxWPNML5ugE7/b8jIVgRgtdGjY88HjLZUnB1KxoSgUzSuilMwk88HjKZcmTvDXfKNUE3jv0mpkEHng85TK9YLTOydQKplfotTMJPPB4ymUpwVjdiyT5KOYZestMAg88nnJBMEqC8Qq9dSaBBx5PuSAYRcFYh64xk8ADj6dcEIyyYKxC15pJ4IHHUy4IxkAw2qFrziTwwOMpFwRjJBit0LVnEnjg8ZTLMILR+vu1Lc/jTR2Y8G9t4DV3dR+V1kwCDzxePPt99JLLw3Nheq1czi5+6h26dtjwwOPFs2Ua6sl2Yfv69se/ZZ8GpMSwuQPUs7TChgeeHjwePRxcEZwh+XtnSclYlvQgjVCaocMDzwo8US63mi1KZrbHCI4+s8ADzwo8TXJBMgxieOAxlQuSYRDDA4+pXJAMgxgeeEzlgmQYxPDAYyoXJMMghue6PC5yCVv4RSsJJvKUFIP4Ojzbn28dKzPnE3lcBLPKYIsXBQUzSyse6JGul6CeXa73iLO4tCzuLeopf3PBpOQy20DJyaVmlqKoIwEdSWa2fjGXzNHKxWKW2L6m2fQtKxeKqq29ZDRllusfi6uJ1SWzbc59w64gl7ObtljVUGcNnhs7s0sm1fOqkok7jTDxNuwUSOvB6iUXyTkXipJ8JDobW96S0ejD+Frs++23yM2SiTtKmfpIMho1mlykq53SallyS96/135b34/k51uPl0VmI0tG81NF6nlR4fc1SUayBAylLRlLuWzDrpELRdWMk/24m0EycZ8S4RZLRrLj0c9RpOSisXqgKM1VlLZkPM8x7RcaKZf8BUdERs5iqgziAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Play.Assets.interface.user: String
"data:image/png;base64,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"
App.KL.Game.Phase.Play.Assets.interface.user.life: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAAANCAYAAACkYvxcAAAAd0lEQVRYCe3WsQ3AMAgFUdbKkpks46Qn8gafIqJ5SHTIBRyHq4Zxv91SDxIGZmg9V5fUg4SBEVnJg2qAdxgYBWhAkzIALOf9l+8NsIAFrFTD6vZPNmMxFmMx0b6J0hkwFmMxVrot6vbNxliMxVhMtG+idAYjY1V9cEEJch85MJkAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.Assets.interface.user.ap: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAGCAYAAACB1M0KAAAAJklEQVR42mNgwAL6vvz/P9Qwhicsdjz4P9TwqCdGPTHqCQKeAAIAliYVnQmzbRMAAAAASUVORK5CYII="

File diff suppressed because one or more lines are too long

View File

@ -4,19 +4,18 @@ App.KL.Game.Phase.Play.draw.fator.number: F64
App.KL.Game.Phase.Play.draw.fator.string: String
F64.show(App.KL.Game.Phase.Play.draw.fator.number)
// BOARD DRAWING
// =============
App.KL.Game.Phase.Play.draw.theme.secondary: String
"#eb6bff"
type App.KL.Game.Phase.Play.draw.SkillInfo {
new(
hero: String
name: String
delay: U64
)
}
PlayersInfo: Type
Pair<Maybe<App.KL.Game.Creature>, App.KL.Game.Player>
SkillInfo: Type
Pair<String,Pair<App.KL.Game.Hero, App.KL.Game.Skill>>
// draw all the screen (round, seconds, canvas, list of skills)
App.KL.Game.Phase.Play.draw(img: VoxBox, local: App.KL.Game.State.Local, game: App.KL.Game): DOM
let players_info = App.KL.Game.Phase.Play.draw.get_players_info(game@players, game@board)
<div style={
"width": "max(100vw, 900px)",
"height": "max(100vh, 650px)",
@ -25,470 +24,135 @@ App.KL.Game.Phase.Play.draw(img: VoxBox, local: App.KL.Game.State.Local, game: A
"background-color":" #071840"
}>
// interface
{ App.KL.Game.Phase.Play.draw.interface(local, game) }
{ App.KL.Game.Phase.Play.draw.board_canvas(local, game, img) }
{ App.KL.Game.Phase.Play.draw.interface(local, game, players_info) }
// canvas
{ App.KL.Game.Phase.Play.draw.canvas.elem(local, game, img) }
// tab
{ App.KL.Game.Phase.Play.draw.tab(local, game, players_info) }
</div>
App.KL.Game.Phase.Play.draw.interface(local: App.KL.Game.State.Local, game: App.KL.Game): DOM
let players_info = App.KL.Game.Phase.Play.draw.interface.top.get_players(game@players, game@board)
<div>
{App.KL.Game.Phase.Play.draw.interface.top(players_info, local, game)}
{App.KL.Game.Phase.Play.draw.interface.bottom(local@user, players_info, local@hud@skill)}
{App.KL.Game.Phase.Play.draw.interface.user(local@user, players_info)}
{App.KL.Game.Phase.Play.draw.interface.casts(local@user, game@moment, game@players)}
</div>
// AUX FUNCTIONS
// =================================
App.KL.Game.Phase.Play.draw.interface.casts(user: String, moment: App.KL.Game.Moment, players: Map<App.KL.Game.Player>): DOM
case moment {
execution:
casts = moment.casts
p_cst = moment.previous_casts
<div style={
"position": "absolute"
"bottom": "0"
"right": "0"
"width": "300px"
"margin-right": "5px"
}>
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, p_cst[1], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, p_cst[0], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(true, casts[0], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, casts[1], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, casts[2], players)}
</div>
} default <span style={"display": "none"}></span>
App.KL.Game.Phase.Play.draw.interface.casts.item(main: Bool, cast: Maybe<App.KL.Game.Cast>, players: Map<App.KL.Game.Player>): DOM
let name = Maybe {
get cast = cast
get player = players{cast@player}
App.KL.Game.Phase.Play.draw.get_player_hero(player: App.KL.Game.Player): Maybe<App.KL.Game.Hero>
Maybe {
get hero_id = player@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
get skill = hero@skills{Char.to_string(cast@letter)}
return hero@name | " - " | skill@name
} <> ""
<div style={
"color": "white"
"background-color": if main && Bool.not(name =? "") then "#2a1956" else "transparent"
"width": if main then "100%" else "98%"
"padding": "0 20px"
"margin-left": if main then "0" else "2%"
"height": if main then "48px" else "36px"
"flex": if main then "2" else "1"
"display": "flex"
"border-radius": "5px"
"align-items": "center"
}>name</div>
App.KL.Game.Phase.Play.draw.interface.top(players_info: Map<PlayersInfo>, local: App.KL.Game.State.Local, game: App.KL.Game): DOM
let inner =
<div>
{App.KL.Game.Phase.Play.draw.interface.top.timer(game@moment)}
{App.KL.Game.Phase.Play.draw.interface.top.round(game@turn)}
{App.KL.Game.Phase.Play.draw.interface.top.scores(game@score)}
{App.KL.Game.Phase.Play.draw.interface.top.players(local@user, players_info, game@cemetery, game@board)}
</div>
<header style={
"position": "absolute",
"top": "0"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(624, 91, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.draw.assets.interface.top, inner)}
</header>
App.KL.Game.Phase.Play.draw.interface.top.timer(moment: App.KL.Game.Moment): DOM
let bar = case moment {
initial:
if moment.countdown >? App.KL.Constants.initital_delay then
U64.to_f64(moment.countdown - App.KL.Constants.initital_delay) / U64.to_f64(App.KL.Constants.initial_time)
else
0.0
preparation:
U64.to_f64(moment.countdown) / U64.to_f64(App.KL.Constants.round_time)
execution: 0.0
return hero
}
<div style={
"position": "absolute"
"top": "4%"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"height": "8.5%"
"background-color": "#eb6bff"
"border-radius": "2px"
"width": String.show_clean(F64.show(bar * 44.5)) | "%"
}>
</div>
App.KL.Game.Phase.Play.draw.get_players_heroes(players: Map<App.KL.Game.Player>): List<App.KL.Game.Hero>
let list = Map.values!(players)
let list = List.mapped!(list)!((player) App.KL.Game.Hero.get_by_id(player@hero_id <> 65536))
let list = List.somes!(list)
list
App.KL.Game.Phase.Play.draw.interface.top.round(round: U64): DOM
<div style={
"position": "absolute"
"bottom": "8%"
"font-size": "1.2rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}>
<span>Nat.show(U64.to_nat(round))</span>
</div>
App.KL.Game.Phase.Play.draw.get_players_skills(players: Map<App.KL.Game.Player>): List<SkillInfo>
let game_heroes = App.KL.Game.Phase.Play.draw.get_players_heroes(players)
let game_skills = List.flatten!(List.mapped!(game_heroes)!((hero) List.mapped!(Map.to_list!(hero@skills))!((x) {Pair.fst!!(x), {hero,Pair.snd!!(x)}})))
let game_skills = List.sort!((a,b) let as = Pair.snd!!(Pair.snd!!(a)); bs = Pair.snd!!(Pair.snd!!(b)); U64.cmp(as@delay, bs@delay), game_skills)
game_skills
App.KL.Game.Phase.Play.draw.interface.top.scores(scores: App.KL.Game.Score): DOM
let blue_hp = I32.sub(App.KL.Constants.max_score, scores@points@snd)
let red_hp = I32.sub(App.KL.Constants.max_score, scores@points@fst)
// return a list with skill info of all players
// the either serves to tell where the walk skills are
App.KL.Game.Phase.Play.draw.get_skills_to_tab(
players: Map<App.KL.Game.Player>
): List<Either<Unit, SkillInfo>>
let skills = App.KL.Game.Phase.Play.draw.get_players_skills(players)
App.KL.Game.Phase.Play.draw.get_skills_to_tab.go(skills, false)
App.KL.Game.Phase.Play.draw.get_skills_to_tab.go(
skills: List<SkillInfo>
found_walk: Bool
): List<Either<Unit, SkillInfo>>
case skills {
nil: []
cons:
let skill = skills.head@snd@snd
if (skill@name =? "Walk") || (skill@delay =? 500) then
if found_walk then
App.KL.Game.Phase.Play.draw.get_skills_to_tab.go(skills.tail, found_walk)
else
Either.left!!(unit) & App.KL.Game.Phase.Play.draw.get_skills_to_tab.go(skills.tail, true)
else
Either.right!!(skills.head) & App.KL.Game.Phase.Play.draw.get_skills_to_tab.go(skills.tail, found_walk)
}
<div style={
"position": "absolute"
"top": "35%"
"font-size": "1.5rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}>
<span style={"margin-right": "2.2%"}>Nat.show(I32.to_nat(blue_hp))</span>
<span>Nat.show(I32.to_nat(red_hp))</span>
</div>
App.KL.Game.Phase.Play.draw.apply_condition(
condition: App.KL.Game.Skill -> Bool
skill_info: SkillInfo
): Bool
let skill = skill_info@snd@snd
condition(skill)
type PlayersInfo {
new(
team: App.KL.Game.Team
creature: Maybe<App.KL.Game.Creature>
hero_id: Maybe<Nat>
)
}
App.KL.Game.Phase.Play.draw.get_allies_enemies(
user: String
players_info: Map<PlayersInfo>
): Pair<Map<PlayersInfo>, Map<PlayersInfo>>
let {blues, reds} = App.KL.Game.Phase.Play.draw.sep_blue_red(players_info)
let player_info = players_info{user}
case player_info {
none: {blues, reds} // when local user isnt a player, blues come first
some:
let player = player_info.value@snd
let player_team = player@team // if local user is a player, then his team come first
if App.KL.Game.Team.blue =? player_team then
{blues, reds}
else
{reds, blues}
}
App.KL.Game.Phase.Play.draw.interface.top.get_players(
// separate blue and red teams
App.KL.Game.Phase.Play.draw.sep_blue_red(
players: Map<PlayersInfo>
): Pair<Map<PlayersInfo>, Map<PlayersInfo>>
let result = {{} :: Map<PlayersInfo>, {} :: Map<PlayersInfo>}
for id:player_info in players with result:
let {allies, enemies} = result
let player = player_info@snd
if App.KL.Game.Team.eql(player@team, App.KL.Game.Team.blue) then
let allies = allies{id}<-player_info
{allies, enemies}
else
let enemies = enemies{id}<-player_info
{allies, enemies}
result
App.KL.Game.Phase.Play.draw.get_players_info(
players: Map<App.KL.Game.Player>,
board: App.KL.Game.Board
): Map<PlayersInfo>
let result = {}
for id:player in players with result:
result{id} <- PlayersInfo.new(player@team, none, player@hero_id)
result{id} <- {none, player}
for coord:tile in board with result:
Maybe {
get creature = tile@creature
get id = creature@player
get info = result{id}
return result{id} <- info@creature <- some(creature)
return result{id} <- info@fst <- some(creature)
} <> result
result
App.KL.Game.Phase.Play.draw.interface.top.players(user: String, players_info: Map<PlayersInfo>, cemetery: App.KL.Game.Cemetery, board: App.KL.Game.Board): DOM
// get team to show in left and team to show in right
let {user_team, enemy_team} =
Maybe {
get info = players_info{user}
let team = info@team
case team {
blue: some({App.KL.Game.Team.blue, App.KL.Game.Team.red})
red: some({App.KL.Game.Team.red, App.KL.Game.Team.blue})
neutral: none
}
} <> {App.KL.Game.Team.blue, App.KL.Game.Team.red} // set as default team
App.KL.Game.Phase.Play.draw.get_life(creature: Maybe<App.KL.Game.Creature>): I32
case creature {
none: 0
some: creature.value@hp
}
// TODO change when formap for DOM published
let players_info = Map.to_list!(players_info)
<div style={"display": "contents"}>
<div style={
"position": "absolute"
"top": "18%"
"left": "3.2%"
"width": "39.7%"
"height": "51%"
"display": "grid"
"grid-template-columns": "repeat(5, 1fr)"
"grid-template-rows": "1fr"
"grid-column-gap": "3px"
}>
for info in players_info:
let {id, snd_info} = info
let team = snd_info@team
let creature = snd_info@creature
let dead = List.find!((x) id =? x@fst, cemetery)
if team =? user_team then
App.KL.Game.Phase.Play.draw.interface.top.creature(creature, dead, false, id =? user)
else
<span style={"display": "none"}></span>
</div>
<div style={
"position": "absolute"
"top": "18%"
"left": "57%"
"width": "39.7%"
"height": "51%"
"display": "grid"
"grid-template-columns": "repeat(5, 1fr)"
"grid-template-rows": "1fr"
"grid-column-gap": "3px"
}>
for info in players_info:
let {id, snd_info} = info
let team = snd_info@team
let creature = snd_info@creature
let dead = List.find!((x) id =? x@fst, cemetery)
if team =? enemy_team then
App.KL.Game.Phase.Play.draw.interface.top.creature(creature, dead, true, false)
else
<span style={"display": "none"}></span>
</div>
</div>
App.KL.Game.Phase.Play.draw.interface.get_life_percentage(creature: Maybe<App.KL.Game.Creature>): F64
App.KL.Game.Phase.Play.draw.get_life_percentage(creature: Maybe<App.KL.Game.Creature>): F64
case creature {
none: 0
some: F64.mul(100.0, I32.to_f64(creature.value@hp) / I32.to_f64(creature.value@hero@max_hp))
}
App.KL.Game.Phase.Play.draw.interface.get_ap(creature: Maybe<App.KL.Game.Creature>): I32
App.KL.Game.Phase.Play.draw.get_ap(creature: Maybe<App.KL.Game.Creature>): I32
case creature {
none: 0
some: creature.value@ap
}
App.KL.Game.Phase.Play.draw.interface.top.creature(creature: Maybe<App.KL.Game.Creature>, dead: Maybe<App.KL.Game.Cemetery.Dead>, is_enemy: Bool, is_user: Bool): DOM
let life_percentage = String.show_clean(F64.show(App.KL.Game.Phase.Play.draw.interface.get_life_percentage(creature)))
let ap = App.KL.Game.Phase.Play.draw.interface.get_ap(creature)
<div style={"position": "relative", "width": "100%", "height": "100%", "order": if is_user then "1" else "2"}>
// portrait
<img src=App.KL.Game.Phase.Play.draw.assets.interface.top.portrait_placeholder style={
"top": "2%"
"left": "4.5%"
"transform-origin": "top left"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"position": "absolute"
}></img>
<div style={"position": "absolute", "top": "46%", "left": "63%", "transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")", "transform-origin": "top left"}>
{ App.KL.Game.Phase.Play.draw.interface.top.creature.life_ap(life_percentage, ap, is_enemy) }
</div>
// death portrait
{
case dead {
none: <span style={"display":"none"}></span>
some:
<div style={"display": "contents"}>
<img src=App.KL.Game.Phase.Play.draw.assets.interface.top.dead style={
"left": "0"
"transform-origin": "top left"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"position": "absolute"
}></img>
<span style={
"position": "absolute"
"top": "38%"
"font-size": ".9rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}> String.show_clean(I32.show(dead.value@snd)) | " TURNS"</span>
</div>
}
}
</div>
App.KL.Game.Phase.Play.draw.interface.top.creature.life_ap(life_percentage: String, ap: I32, is_enemy: Bool): DOM
<div style={"position": "relative"}>
// life bar
<img src=App.KL.Game.Phase.Play.draw.assets.interface.top.life_placeholder></img>
<img
src= if is_enemy then App.KL.Game.Phase.Play.draw.assets.interface.top.life_red else App.KL.Game.Phase.Play.draw.assets.interface.top.life_green
style={
"left": "2px"
"top": "1px"
"position": "absolute"
"clip-path": "polygon(0 0%, "|life_percentage|"% 0%, "|life_percentage|"% 100%, 0% 100%)"
}>
</img>
// ap bar
for img in App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap, [{2.0,21.0}, {8.0,15.0}, {14.0,9.0}]):
img
</div>
App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap: I32, positions: List<Pair<F64, F64>>): List<DOM>
if ap <=? 0 then []
else
case positions {
nil: []
cons:
<img src=App.KL.Game.Phase.Play.draw.assets.interface.top.ap style={
"position": "absolute"
"left": String.show_clean(F64.show(positions.head@fst)) | "px"
"top": String.show_clean(F64.show(positions.head@snd)) | "px"
}></img> & App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap - 1, positions.tail)
}
App.KL.game.Phase.Play.Draw.interface.bottom.get_skills(skills: Map<App.KL.Game.Skill>, max: Nat): List<Pair<String, App.KL.Game.Skill>>
result = {[] :: List<Pair<String, App.KL.Game.Skill>>, max}
for key: skill in skills with result:
if (max <=? 0) || (skill@name =? "Walk") then
result
else
let result = result@fst <- {key, skill} & result@fst
result@snd <- result@snd - 1
result@fst
App.KL.Game.Phase.Play.Draw.interface.bottom.get_walk_key(skills: Map<App.KL.Game.Skill>): String
case skills {
tip: ""
bin:
if skills.val@name =? "Walk" then
skills.key
else
App.KL.Game.Phase.Play.Draw.interface.bottom.get_walk_key(skills.left) | App.KL.Game.Phase.Play.Draw.interface.bottom.get_walk_key(skills.right)
}
App.KL.Game.Phase.Play.draw.interface.bottom(user: String, players_info: Map<PlayersInfo>, skill_hovered: Maybe<App.KL.Game.Skill>): DOM
// get user in players map
// if user isnt a player this interface isnt shown
let user = players_info{user}
without user: <span style={"display": "none"}></span>
// get hero of user, if none this interface isnt shown
let hero =
Maybe {
get hero_id = user@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
return hero
}
without hero: <span style={"display": "none"}></span>
// draw content TODO change when formap implemented
let skills = hero@skills
let skills_list = App.KL.game.Phase.Play.Draw.interface.bottom.get_skills(skills, 4)
let content =
<div style={
"position": "relative"
"width": "100%"
"height": "100%"
}>
{
let walk_key = App.KL.Game.Phase.Play.Draw.interface.bottom.get_walk_key(skills)
<span style={"position": "absolute", "left": "1.25%", "top": "25%"}>walk_key</span>
}
<div style={
"position": "absolute"
"display": "grid"
"grid-template-columns": "repeat(4, 1fr)"
"grid-template-rows": "1fr"
"gap": "2%"
"width": "73%"
"height": "73%"
"left": "13.5%"
}>
for info in skills_list:
let {key, skill} = info
let id = "SK"|key
let show = Maybe.if!((x) String.eql(skill@name, x@name), skill_hovered)
<div style={
"position": "relative"
}>
<div id=id style={
"background-color": "#190d1f"
"border-radius": "5px"
"padding": "5px"
"animation": "fade-in 0.1s"
"position": "absolute"
"transform-origin": "bottom center"
"transform": "translate(-15%, -101%)"
"width": "150%"
"color": "white"
"display": if show then "block" else "none
"
}>skill@description</div>
<span id=id style={"position": "absolute", "bottom": "1%", "left": "7%"}>key</span>
<span id=id style={"position": "absolute", "width": "100%", "height": "100%", "display": "flex", "justify-content": "center", "align-items": "center", "color": "white"}>skill@name</span>
</div>
</div>
</div>
<footer style={
"position": "absolute",
"bottom": "0"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(280, 65, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.draw.assets.interface.bottom, content)}
</footer>
App.KL.Game.Phase.Play.draw.interface.user(user: String, players_info: Map<PlayersInfo>): DOM
let user = players_info{user}
without user: <span style={"display": "none"}></span>
let creature = user@creature
let life_percentage = App.KL.Game.Phase.Play.draw.interface.get_life_percentage(creature)
let ap = App.KL.Game.Phase.Play.draw.interface.get_ap(creature)
let content =
<div style={
"position": "relative"
"width": "100%"
"height": "100%"
}>
<img src=App.KL.Game.Phase.Play.draw.assets.interface.top.portrait_placeholder style={
"position": "absolute"
"transform": "scale("|F64.show(App.KL.Game.Phase.Play.draw.fator.number * 2)|")"
"transform-origin": "top left"
"top": "4%"
"left": "4%"
}></img>
<img src= App.KL.Game.Phase.Play.draw.assets.interface.user.life style={
"position": "absolute"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"transform-origin": "top left"
"top": "61%"
"left": "34%"
"clip-path": "polygon(0 0%, "|String.show_clean(F64.show(life_percentage + 8))|"% 0%, "|String.show_clean(F64.show(life_percentage))|"% 100%, 0% 100%)"
}></img>
<div style={
"position": "absolute"
"top": "74%"
"left": "31%"
"display": "flex"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"transform-origin": "top left"
}>
for i in [0 to ap : I32]:
<img src=App.KL.Game.Phase.Play.draw.assets.interface.user.ap style={
"margin-right": "-3px"
}></img>
</div>
</div>
<footer style={
"position": "absolute",
"bottom": "0"
"left": "0"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(249, 112, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.draw.assets.interface.user, content)}
</footer>
App.KL.Game.Phase.Play.draw.wrapper(width: Nat, height: Nat, bt: Nat, id: String, fator: F64, background: String, inner: DOM): DOM
<div class="pixel-art" id=id style={
"height": Nat.show(F64.to_nat(fator * Nat.to_f64(height))) | "px",
@ -502,339 +166,6 @@ App.KL.Game.Phase.Play.draw.wrapper(width: Nat, height: Nat, bt: Nat, id: String
{inner}
</div>
App.KL.Game.Phase.Play.draw.assets.interface.top: String
"data:image/png;base64,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"
App.KL.Game.Phase.Play.draw.assets.interface.top.dead: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAvCAYAAAClgknJAAAA0UlEQVR42u2ayw2AIBAFqcAC7NOjXdiuwXjEaFTY3xBIOO8MMXzemlLl2KclS85kOaThTSU0CppJaBZSl7BYJbUalt+peC2PnUKspts2J1HbE76ZIQJ8NUsk+N9MEeE/s0WGf2UkwD+ykuBvJWjwV4l+BKiTL7DNaybPITAEWuDPgYanChQHAhqeJmCaspmldmj44lJEen1FFkA/4tExCjrIQkeJ6DAXHaejGxr4llI3Tb1E3Snce8NIAUkJ11NfQsL97tUqEeLyiPvBQ0NCguEALTFIyZF1RbwAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.draw.assets.interface.top.life_placeholder: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAhCAYAAADZPosTAAAAqUlEQVR42q3WwQ2AMAwDwA7AAjwQAyDW7LqMAAKJDyRO7aRSv6dSk6StJVdfjvPe87Q+uwzbt54Dv1gKtDAZ9DAJRBgNRhgFjmDDIIOFIIOFJ2QxCCqYC6qYCWawH8imCUElTRdU04SnU9KEdxfVJ/XvRd2DrgzU2xAIq8K7I6nvWXOBqgYEUmlGIJ3m6CfTfc5aUpoqKA3ukhmLwPSjp+R9YoEl2AtWYReM1Yo9Nul7hAAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.draw.assets.interface.top.life_green: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAYAAADtNKTnAAAASUlEQVR42u3MuwkAIAxAwazlkk7mOPYRBAt/YPIai9wAJwLlqsqDkpQH3mQKPMkWWJNjYEmuwWsSQQR/BB0ObokZDtbEDQcjgRrIJQkoZdOOigAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.draw.assets.interface.top.life_red: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAYAAADtNKTnAAAAT0lEQVR42mNgoBD8W7fkP8UG/OUr/U+xAWQbgmwAWYagG0CyIdgMIMkQXAYQbcioAaMGDA4DQIBiA3AZQnLWptgAdEPILuYoNgBmCKUlPgDWlzbp+XS3GgAAAABJRU5ErkJggg=="
App.KL.Game.Phase.Play.draw.assets.interface.top.ap: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAALCAYAAAC3ZUeVAAAAMklEQVR42mNgQAN9X/7/xxAwXPTpP4YAXBBZACyILgAWRBcgXhBsCYYAsiCKgzEEgAAAEsBkeRIf5ncAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.draw.assets.interface.top.portrait_placeholder: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAFRUlEQVRYCb2Yv6pUVxSHb2sXUhhuZTqVi4GAfwoJGFsRUgVSpBEjWNj4AEICClNYBJF0Vr6CoLcR8gJh7jPkMSLKt+d8x9/Zs/eZmTveXNis/Xetb/32Omdm7sHBKf+uHD37uE+bC3tyvPj44cN/Y5vbu9Uazi6c/2GrZuCjw5/X9veCAVza8jN4b+/GeQBwdvnwzhpAK4m3fzwclWqt9wJyjnayD7RXhb34za3SFvd+LY5xvnz1tDSDsUZT5d7NtKD1kUq39nXnqFeBCfzTdz8WUCB1ihqTdrwoCaRKgOyqdMbtAuYCsAQhmGrhZISNmpsAk4D7hqtlvQXMXMYkFuNR6eF87mn2hb317fVyvZntRmASWa4SY6/J9oCFBpI4jOu4TUgnhfXgmG28dmahQ/kEpq7noIGlAStwSWK5mNyCnMUmLM4JIpwKqJjzBpqUxRA8gTnfA9a3vv68877Edn4C6aCG5QETuMAtF6tXzpzSQzkkvAnOAZf9xyv/7AeYxhmajKOtYVEigc0Ux/YFwarMaIc3h3s811O4Bv799m99YGEPv746ubIWMEqbNVYg7PL5i3HNfSaDZX8dgwSYK/sGMVAWYG6XM9iJsukk+wILKEQpj+H6UJRgArkXSwL/vn9bGusETv+qLbA+gKXpawRGWTbrRGvWAptpDfzml0fFMc4TTkgta+zVr6BpTRxLPIHpF+CETeh0msBCkzVOgVcJYGgtaFTDDy0Bs098/LKXhv9UtwALOWfngIHNs4yB/vvxkxGc4My/e3itlEVC1n1iCZ0PIPuIc2AwJxynVRmvRZVVl71cO/uAYgygpUA/oWvIenzl6Onn7yRDaeAbvxPgHjTzHKiBUQIYGmUALPuAwzlzNOGx+KgB6zHA7LMk6HeBW9AJDCQOrC2uX2hrGGVNIqGt7xowxyQKnP4TtqlwHravE0G1OBVSaK2glgVjlGes355NYJWFYSdgIBM0YX3AhKyt0ACz1gMFiDWBKYlTAXOoht0GmEQsA6C3AebTrQYmiZ0UVl0fAuvLcugprLJagPE1p/DewKrLOzE/4QhMvQLdAhZSq7qbgImnMNi6LMbXmvWT2eO8vLwrWJwIPAftDQANMHvx14OGQWBhOcfcWkk4oU1YSwCF/fRhnXnfCqjcUtq3A/sKzAbgCfRy9dA1a1hQbIEdvoALWzKOH5XMkwCQLWhLAcseYE2SpPMmsy+wcVNd1iYlIXRRMr54jLBRGipqDQuNdU3LHACbgMf4wzvbuue8a2vAqmuAsQwCljVhBNbW72ATcV7liZPK5rWz17rHMm4C+wvVh0p4rhBwr8mHCSuIc44NZHBBUY3GmGQSHCiEyL36Ye3GX/+sfnEwAJZ6AQwnBdaajV8MOhMsLcEc5z772ho6ldYHe00MnyOsv5FS3fI0+/O8AWtg4VrWPT0rNCoLTF9gfHK2CSu0JcDVo7SH6qBmrsMErvduGgP51blLpTzyOfDcmrLCaoHeBVjHu1gTJlEggfZ5QGFfgRthhQZYBzVIBqvXth1bDgDXZSDw1rBCC9wqC0ugBWhCrbWcY58KZ93S3xlWaMF6NgGyLzTncj77NTCge8H2oHHKNd6//Xr2oQSIvT1o5vXFbdJOraywWhU2wM1rzwsw3117QAK3EuMMZ2kkT/tisEIDiwo4B5gH06A9aGDdU1vO8wl6JrBCCwswrz/e1TVIjoGqoQvo8E2QtS+urLBaYL+/9KCA+PGdEHwPYSys/fEb3/Dvrf8FVmiAhSYwH+u9dvfqy5Ic+7KdubLCagm4T9PPrvYTWNZKhYRd7gsAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.draw.assets.interface.bottom: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAABBCAYAAAAKeLsHAAAEyElEQVR42u2dTY7UMBBGe8cFWMCCE4xYw5ZLzBW4ySzZzlU4BBJX4AZs2DcyklE6cuKyXVX+yYtUQrQ0mX75XM/udJK53RbcPr3+vGsUPPBckYctE/bLh99qBQ88V+JhE4b95t2Xpvr49NI9dHjgYVtQLiOEDg88bAvLpWfo8MCDZC4glx6hwwMPkrmQXDxDhwceJHNBuXiEDg88SObCcrEMHR54kAxyMQkdHniQDHIxCR0eeJAMcjEJHR54kAxyMQkdHniQDHIxCR0eeJAMcjEJHR54kAxyMQkdHniQTKUILJ59EQOfJexYuQEMDzwePF59WrR9+3O/5+rI+qWVe/MMYHjg0RGMZp+WOqLoB7c70HjQzplkZg/86f3zQ8EDTw/BaPZpqSOq5BJK8yleKwsmvrZKQ8Izn2C0+jQcn1JPVAnG6xGBDGB44BlHMDWSKRaMtlwQDDzwzCOYUskUCcZCLggGHnjmEkyJZMSCsZILgoEHnvkEI5WMSDCWckEw8MAzp2AkkskKxlouocLViKliAMMDj5znqI+s+/dMMqeC8ZBL6nqEla6zoCHh6XVdTyyPHj6SzKFgvOSyD5oBDA887TxbLq8+TkkmebGdp1wQDDzwrCGYvWSKLiv+/P3Xg5nC//evx9cQDA0JzzUFc3r7T27lEmWyl82+EAwNCc91BZOUjPRjkUQyCIaGhOfagnmQTOk5l5xkNAUT9he+apst7KMBDA88HjwjCOa/ZGpP6qYEU3MeJieYWULfMkUGeODpwbOEYDTkIhXM6KHvw84NYHjgseSZXjBaq5cSwYwa+lHYuQEMDzxWPNML5ugE7/b8jIVgRgtdGjY88HjLZUnB1KxoSgUzSuilMwk88HjKZcmTvDXfKNUE3jv0mpkEHng85TK9YLTOydQKplfotTMJPPB4ymUpwVjdiyT5KOYZestMAg88nnJBMEqC8Qq9dSaBBx5PuSAYRcFYh64xk8ADj6dcEIyyYKxC15pJ4IHHUy4IxkAw2qFrziTwwOMpFwRjJBit0LVnEnjg8ZTLMILR+vu1Lc/jTR2Y8G9t4DV3dR+V1kwCDzxePPt99JLLw3Nheq1czi5+6h26dtjwwOPFs2Ua6sl2Yfv69se/ZZ8GpMSwuQPUs7TChgeeHjwePRxcEZwh+XtnSclYlvQgjVCaocMDzwo8US63mi1KZrbHCI4+s8ADzwo8TXJBMgxieOAxlQuSYRDDA4+pXJAMgxgeeEzlgmQYxPDAYyoXJMMghue6PC5yCVv4RSsJJvKUFIP4Ojzbn28dKzPnE3lcBLPKYIsXBQUzSyse6JGul6CeXa73iLO4tCzuLeopf3PBpOQy20DJyaVmlqKoIwEdSWa2fjGXzNHKxWKW2L6m2fQtKxeKqq29ZDRllusfi6uJ1SWzbc59w64gl7ObtljVUGcNnhs7s0sm1fOqkok7jTDxNuwUSOvB6iUXyTkXipJ8JDobW96S0ejD+Frs++23yM2SiTtKmfpIMho1mlykq53SallyS96/135b34/k51uPl0VmI0tG81NF6nlR4fc1SUayBAylLRlLuWzDrpELRdWMk/24m0EycZ8S4RZLRrLj0c9RpOSisXqgKM1VlLZkPM8x7RcaKZf8BUdERs5iqgziAAAAAElFTkSuQmCC"
App.KL.Game.Phase.Play.draw.assets.interface.user: String
"data:image/png;base64,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"
App.KL.Game.Phase.Play.draw.assets.interface.user.life: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAAANCAYAAACkYvxcAAAAd0lEQVRYCe3WsQ3AMAgFUdbKkpks46Qn8gafIqJ5SHTIBRyHq4Zxv91SDxIGZmg9V5fUg4SBEVnJg2qAdxgYBWhAkzIALOf9l+8NsIAFrFTD6vZPNmMxFmMx0b6J0hkwFmMxVrot6vbNxliMxVhMtG+idAYjY1V9cEEJch85MJkAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.draw.assets.interface.user.ap: String
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAGCAYAAACB1M0KAAAAJklEQVR42mNgwAL6vvz/P9Qwhicsdjz4P9TwqCdGPTHqCQKeAAIAliYVnQmzbRMAAAAASUVORK5CYII="
App.KL.Game.Phase.Play.draw.board_canvas(local: App.KL.Game.State.Local, game: App.KL.Game, img: VoxBox): DOM
<div style={
"cursor": "url("| App.KL.Game.Phase.Play.draw.get_cursor(local, game) | "), auto"
"max-width": "max(100vw, 900px)",
"max-height": "max(100vh, 650px)",
"overflow": "scroll",
"display": "flex"
"justify-content": "center"
"align-items": "center"
}>{
let width = Nat.show(U32.to_nat(local@screen_size@fst / 2))
let height = Nat.show(U32.to_nat(local@screen_size@snd / 2))
DOM.vbox({
"class": "pixel-art"
"id": "game_screen",
"width": width,
"height": height,
"scale": "2"
},
{},
App.KL.Game.Phase.Play.draw.canvas(img, local, game))
}</div>
// CANVAS DRAWING
// ================
// draw canvas
App.KL.Game.Phase.Play.draw.canvas(
img: VoxBox
local: App.KL.Game.State.Local
game: App.KL.Game
): VoxBox
open game
let hits = case game.moment {
initial: none
preparation: none
execution: some(game.moment.hits)
}
let img = App.KL.Game.Phase.Play.draw.board(game, local@preview, hits, local@user, local@mouse, local@screen_size, img)
let img = App.KL.Game.Phase.Play.draw.bases(game, local@user, local@screen_size, img)
let img = App.KL.Game.Phase.Play.draw.cursor(local@mouse, game.board, local@screen_size, img)
img
// draw canvas board
App.KL.Game.Phase.Play.draw.landscape(blueprint: App.KL.Game.Board.Blueprint, screen: Pair<U32, U32> img: VoxBox): VoxBox
let landscape = blueprint@landscape
for coord:tile in landscape with img:
App.KL.Game.Phase.Play.draw.tile.terrain(tile, Hexagonal.Axial.Map.new!, none, coord, screen, img)
img
App.KL.Game.Phase.Play.draw.board(
game: App.KL.Game
preview: App.KL.Game.Cast.Preview
hits: Maybe<App.KL.Game.Indicators>
user: String
mouse: Pair<U32, U32>
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
open game
let map = game@board
let mouse_coord = Hexagonal.Axial.from_screen_xy(mouse, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
let indicators = App.KL.Game.Phase.Play.Draw.get_indicators(preview, mouse_coord, user, game)
let ap_used = App.KL.Game.Moment.get_player_used_ap(game) // If there is a skill being cast, returns the player address and used ap
let img = App.KL.Game.Phase.Play.draw.landscape(game@blueprint, screen, img)
for coord:tile in map with img:
let indicator = Hexagonal.Axial.Map.get!(coord, hits <> indicators)
let img = App.KL.Game.Phase.Play.draw.grid(coord, game@moment, screen, img)
let img = App.KL.Game.Phase.Play.draw.tile.terrain(tile@terrain, preview@picks, indicator, coord, screen, img)
let img = App.KL.Game.Phase.Play.draw.tile.indicator(indicator, coord, screen, img)
let img = App.KL.Game.Phase.Play.draw.tile.creature(game, tile@creature, coord, ap_used, screen, img)
let img = App.KL.Game.Phase.Play.draw.tile.token(game, tile@token, coord, screen, img)
img
img
// TODO optimize?
App.KL.Game.Phase.Play.draw.grid(
coord: Hexagonal.Axial
moment: App.KL.Game.Moment
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
case moment {
initial: img
preparation:
let indicator = App.KL.Game.Indicator.gray_line
let indicator_img = App.KL.Game.Indicator.get_img(indicator)
let {x, y} = App.KL.Game.Phase.Play.draw.centralize.new(coord, screen)
VoxBox.Draw.image(x, y, App.KL.Constants.z_index.grid, indicator_img, img)
execution: img
}
App.KL.Game.Phase.Play.draw.tile.token(
game: App.KL.Game
token: Maybe<App.KL.Game.Token>,
token_coord: Hexagonal.Axial,
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
without token: img
let col = case App.KL.Game.Token.get_dominance(token) as team {
none: Col32.new(100,100,100,255)
some:
case team.value {
blue: Col32.new(0, 0, 255, 255)
red: Col32.new(255, 0, 0, 255)
} default Col32.new(100,100,100,255)
}
let coords = Hexagonal.Axial.range(token_coord, token@range)
for coord in coords with img:
let {cx, cy} =
Hexagonal.Axial.to_screen_xy(coord, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
if Hexagonal.Axial.eql(coord, token_coord) then
VoxBox.Draw.square(cx,cy,App.KL.Constants.z_index.token,10,10,col,img)
else
VoxBox.Draw.square(cx,cy,App.KL.Constants.z_index.token,5,5,col,img)
img
App.KL.Game.Phase.Play.draw.bases(
game: App.KL.Game
user: String
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
case game@moment {
initial:
let player = game@players{user}
without player: img
let allies = App.KL.Game.Player.get_allies(player, game@players)
let bases = game@blueprint@bases
for coord:team in bases with img:
let indicator = App.KL.Game.Team.get_indicator(team)
App.KL.Game.Phase.Play.draw.tile.indicator(some(indicator), coord, screen, img)
for l_user:player in allies with img:
let init_pos = player@init_pos
without init_pos: img
let indicator =
if String.eql(user, l_user) then
App.KL.Game.Indicator.green_line
else
App.KL.Game.Indicator.gray_line
App.KL.Game.Phase.Play.draw.tile.indicator(some(indicator), init_pos, screen, img)
img
preparation: img
execution: img
}
App.KL.Game.Phase.Play.Draw.get_indicators(
preview: App.KL.Game.Cast.Preview
target: Hexagonal.Axial,
user: String,
game: App.KL.Game
): App.KL.Game.Indicators
Maybe {
get pair = preview@skill
let skill_key = pair@fst
get skill = App.KL.Game.Skill.get(user, skill_key, game)
let targets = App.KL.Game.Picks.get_skill_coords(skill_key, preview@picks)
let targets = target & targets
let game = App.KL.Game.Cast.simulate(skill@delay, (x) String.eql(x@player, user), game)
get center = App.KL.Game.Board.find_player_coord(user, game@board)
get creature = App.KL.Game.Board.Creature.get(center, game@board)
let indicator = App.KL.Game.Indicator.blue_line
let indicators = Hexagonal.Axial.Map.new!
let distance = App.KL.Game.Creature.Status.movement_range(Nat.to_i32(U64.to_nat(skill@range)), creature)
let coords = Hexagonal.Axial.range(center, distance)
// set range indicator
for coord in coords with indicators:
Hexagonal.Axial.Map.set!(coord, indicator, indicators)
let areas = App.KL.Game.Effect.indicators.get_indicators(center, skill, {skill_key, user} targets, game@board)
return Hexagonal.Axial.Map.union!(indicators, areas)
} <> Hexagonal.Axial.Map.new<App.KL.Game.Indicator>
// draw mouse indicator
App.KL.Game.Phase.Play.draw.cursor(
mouse: Pair<U32, U32>
board: App.KL.Game.Board
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
coord = Hexagonal.Axial.from_screen_xy(mouse, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
{x,y} = App.KL.Game.Phase.Play.draw.centralize.old(coord, screen)
let has_tile = App.KL.Game.Tile.get(coord, board)
case has_tile {
none:
img
some:
VoxBox.Draw.image(x, y, App.KL.Constants.z_index.cursor, App.KL.Game.Field.Mouse.mouse_ui, img)
}
// draws tile terrain
App.KL.Game.Phase.Play.draw.tile.terrain(
terrain: App.KL.Game.Terrain
picks: App.KL.Game.Picks
indicator: Maybe<App.KL.Game.Indicator>
tile_coord: Hexagonal.Axial
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
let indicator = indicator <> App.KL.Game.Indicator.background
let {i, j} = App.KL.Game.Phase.Play.draw.centralize.new(tile_coord, screen)
let field = App.KL.Game.Field.get_by_id.default(terrain@field_id)
let field_drawing = field@draw(terrain, indicator)
let tile_drawing = VoxBox.Draw.image(i, j, I32.to_u32(tile_coord@j + App.KL.Constants.z_index.terrain), field_drawing, img)
let tile_drawing = App.KL.Game.Phase.Play.draw.letter(tile_coord, picks, screen, tile_drawing)
tile_drawing
App.KL.Game.Phase.Play.draw.tile.indicator(
indicator: Maybe<App.KL.Game.Indicator>
tile_coord: Hexagonal.Axial
screen: Pair<U32,U32>
img: VoxBox
): VoxBox
without indicator: img
let {i, j} = App.KL.Game.Phase.Play.draw.centralize.new(tile_coord, screen)
let ind_img = App.KL.Game.Indicator.get_img(indicator)
let img = VoxBox.Draw.image(i, j, App.KL.Constants.z_index.indicator, ind_img, img)
img
App.KL.Game.Phase.Play.draw.tile.creature.get_draw_pose(game: App.KL.Game, coord: Hexagonal.Axial): App.KL.Game.Hero.Draw.Pose
open game
case game.moment {
initial: App.KL.Game.Hero.Draw.Pose.idle
preparation:
App.KL.Game.Hero.Draw.Pose.idle
execution: case game.moment.casts {
nil:
App.KL.Game.Hero.Draw.Pose.idle
cons: Maybe {
//get success = if game.moment.success then some(unit) else none
get success = case game.moment.success {
left: none
right: some(unit)
}
get creature = App.KL.Game.Board.Creature.get(coord, game.board)
let cast = game.moment.casts.head
get player = creature@player
open cast
if String.eql(player, cast.player) then Maybe {
let frame = game.moment.frame
let center = game.moment.coord <> coord
let target = cast.target
let letter = cast.letter
get skill = App.KL.Game.Cast.get_skill(cast, game)
get creature = App.KL.Game.Cast.get_creature(cast, game)
return App.KL.Game.Hero.Draw.Pose.cast(frame, center, target, letter, skill, creature)
} else none
} <> App.KL.Game.Hero.Draw.Pose.idle
}
}
// draws tile creature if any
App.KL.Game.Phase.Play.draw.tile.creature(
game: App.KL.Game
creature: Maybe<App.KL.Game.Creature>,
coord: Hexagonal.Axial,
ap_used: Maybe<Pair<String, I32>>
screen: Pair<U32,U32>
img: VoxBox
): VoxBox
case creature {
none: img
some:
let hero = creature.value@hero
let draw_pose = App.KL.Game.Phase.Play.draw.tile.creature.get_draw_pose(game, coord)
let {draw_coord, draw_voxbox} = hero@draw@vbox_img(draw_pose)
let draw_coord = draw_coord <> coord
//let aux = I32.to_u32(App.KL.Constants.hexagon_radius) //U32
//let cy = cy - (aux * 2) //U32
//let cx = cx - aux //U32
//log(U32.show( cy + 100))
{cx, cy} = Hexagonal.Axial.to_screen_xy(draw_coord, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
let img_x = cx - (128::U32)
let img_y = cy - (128::U32)
let height = I32.to_u32(hero@draw@height)
let img = VoxBox.Draw.image(img_x, img_y, App.KL.Constants.z_index.hero, draw_voxbox, img)
open creature.value as creature
case creature.player {
none:
img
some:
let img = App.KL.Game.Phase.Play.Bar.show_hp(cx - 17, (cy - height), creature.value, img)
let img = App.KL.Game.Phase.Play.draw.ap(img_x - 12, (img_y - height) - 3, creature.value, ap_used, img)
img
}
}
// AUX FUNCTIONS
// =============
App.KL.Game.Phase.Play.draw.get_cursor(
local: App.KL.Game.State.Local
game : App.KL.Game
@ -949,7 +280,7 @@ App.KL.Game.Phase.Play.draw.shield(
let shield = Nat.show(Int.to_nat(shield))
VoxBox.Draw.text(shield, PixelFont.small_black, Pos32.new(cx, cy, 0), img)
App.KL.Game.Phase.Play.Draw.gray_overlay(game: App.KL.Game): DOM
App.KL.Game.Phase.Play.draw.gray_overlay(game: App.KL.Game): DOM
open game
case game.moment {
initial: <div></div>

View File

@ -0,0 +1,299 @@
App.KL.Game.Phase.Play.draw.canvas.elem(
local: App.KL.Game.State.Local,
game: App.KL.Game, img: VoxBox
): DOM
<div style={
"cursor": "url("| App.KL.Game.Phase.Play.draw.get_cursor(local, game) | "), auto"
"max-width": "max(100vw, 900px)",
"max-height": "max(100vh, 650px)",
"overflow": "scroll",
"display": "flex"
"justify-content": "center"
"align-items": "center"
}>{
let width = Nat.show(U32.to_nat(local@screen_size@fst / 2))
let height = Nat.show(U32.to_nat(local@screen_size@snd / 2))
DOM.vbox({
"class": "pixel-art"
"id": "game_screen",
"width": width,
"height": height,
"scale": "2"
},
{},
App.KL.Game.Phase.Play.draw.canvas(img, local, game))
}</div>
// CANVAS DRAWING
// ================
// draw canvas
App.KL.Game.Phase.Play.draw.canvas(
img: VoxBox
local: App.KL.Game.State.Local
game: App.KL.Game
): VoxBox
open game
let hits = case game.moment {
initial: none
preparation: none
execution: some(game.moment.hits)
}
let img = App.KL.Game.Phase.Play.draw.canvas.board(game, local@preview, hits, local@user, local@mouse, local@screen_size, img)
let img = App.KL.Game.Phase.Play.draw.canvas.bases(game, local@user, local@screen_size, img)
let img = App.KL.Game.Phase.Play.draw.canvas.cursor(local@mouse, game.board, local@screen_size, img)
img
// draw canvas board
App.KL.Game.Phase.Play.draw.canvas.landscape(blueprint: App.KL.Game.Board.Blueprint, screen: Pair<U32, U32> img: VoxBox): VoxBox
let landscape = blueprint@landscape
for coord:tile in landscape with img:
App.KL.Game.Phase.Play.draw.canvas.tile.terrain(tile, Hexagonal.Axial.Map.new!, none, coord, screen, img)
img
App.KL.Game.Phase.Play.draw.canvas.board(
game: App.KL.Game
preview: App.KL.Game.Cast.Preview
hits: Maybe<App.KL.Game.Indicators>
user: String
mouse: Pair<U32, U32>
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
open game
let map = game@board
let mouse_coord = Hexagonal.Axial.from_screen_xy(mouse, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
let indicators = App.KL.Game.Phase.Play.Draw.canvas.get_indicators(preview, mouse_coord, user, game)
let ap_used = App.KL.Game.Moment.get_player_used_ap(game) // If there is a skill being cast, returns the player address and used ap
let img = App.KL.Game.Phase.Play.draw.canvas.landscape(game@blueprint, screen, img)
for coord:tile in map with img:
let indicator = Hexagonal.Axial.Map.get!(coord, hits <> indicators)
let img = App.KL.Game.Phase.Play.draw.canvas.grid(coord, game@moment, screen, img)
let img = App.KL.Game.Phase.Play.draw.canvas.tile.terrain(tile@terrain, preview@picks, indicator, coord, screen, img)
let img = App.KL.Game.Phase.Play.draw.canvas.tile.indicator(indicator, coord, screen, img)
let img = App.KL.Game.Phase.Play.draw.canvas.tile.creature(game, tile@creature, coord, ap_used, screen, img)
let img = App.KL.Game.Phase.Play.draw.canvas.tile.token(game, tile@token, coord, screen, img)
img
img
// TODO optimize?
App.KL.Game.Phase.Play.draw.canvas.grid(
coord: Hexagonal.Axial
moment: App.KL.Game.Moment
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
case moment {
initial: img
preparation:
let indicator = App.KL.Game.Indicator.gray_line
let indicator_img = App.KL.Game.Indicator.get_img(indicator)
let {x, y} = App.KL.Game.Phase.Play.draw.centralize.new(coord, screen)
VoxBox.Draw.image(x, y, App.KL.Constants.z_index.grid, indicator_img, img)
execution: img
}
App.KL.Game.Phase.Play.draw.canvas.tile.token(
game: App.KL.Game
token: Maybe<App.KL.Game.Token>,
token_coord: Hexagonal.Axial,
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
without token: img
let col = case App.KL.Game.Token.get_dominance(token) as team {
none: Col32.new(100,100,100,255)
some:
case team.value {
blue: Col32.new(0, 0, 255, 255)
red: Col32.new(255, 0, 0, 255)
} default Col32.new(100,100,100,255)
}
let coords = Hexagonal.Axial.range(token_coord, token@range)
for coord in coords with img:
let {cx, cy} =
Hexagonal.Axial.to_screen_xy(coord, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
if Hexagonal.Axial.eql(coord, token_coord) then
VoxBox.Draw.square(cx,cy,App.KL.Constants.z_index.token,10,10,col,img)
else
VoxBox.Draw.square(cx,cy,App.KL.Constants.z_index.token,5,5,col,img)
img
App.KL.Game.Phase.Play.draw.canvas.bases(
game: App.KL.Game
user: String
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
case game@moment {
initial:
let player = game@players{user}
without player: img
let allies = App.KL.Game.Player.get_allies(player, game@players)
let bases = game@blueprint@bases
for coord:team in bases with img:
let indicator = App.KL.Game.Team.get_indicator(team)
App.KL.Game.Phase.Play.draw.canvas.tile.indicator(some(indicator), coord, screen, img)
for l_user:player in allies with img:
let init_pos = player@init_pos
without init_pos: img
let indicator =
if String.eql(user, l_user) then
App.KL.Game.Indicator.green_line
else
App.KL.Game.Indicator.gray_line
App.KL.Game.Phase.Play.draw.canvas.tile.indicator(some(indicator), init_pos, screen, img)
img
preparation: img
execution: img
}
App.KL.Game.Phase.Play.Draw.canvas.get_indicators(
preview: App.KL.Game.Cast.Preview
target: Hexagonal.Axial,
user: String,
game: App.KL.Game
): App.KL.Game.Indicators
Maybe {
get pair = preview@skill
let skill_key = pair@fst
get skill = App.KL.Game.Skill.get(user, skill_key, game)
let targets = App.KL.Game.Picks.get_skill_coords(skill_key, preview@picks)
let targets = target & targets
let game = App.KL.Game.Cast.simulate(skill@delay, (x) String.eql(x@player, user), game)
get center = App.KL.Game.Board.find_player_coord(user, game@board)
get creature = App.KL.Game.Board.Creature.get(center, game@board)
let indicator = App.KL.Game.Indicator.blue_line
let indicators = Hexagonal.Axial.Map.new!
let distance = App.KL.Game.Creature.Status.movement_range(Nat.to_i32(U64.to_nat(skill@range)), creature)
let coords = Hexagonal.Axial.range(center, distance)
// set range indicator
for coord in coords with indicators:
Hexagonal.Axial.Map.set!(coord, indicator, indicators)
let areas = App.KL.Game.Effect.indicators.get_indicators(center, skill, {skill_key, user} targets, game@board)
return Hexagonal.Axial.Map.union!(indicators, areas)
} <> Hexagonal.Axial.Map.new<App.KL.Game.Indicator>
// draw mouse indicator
App.KL.Game.Phase.Play.draw.canvas.cursor(
mouse: Pair<U32, U32>
board: App.KL.Game.Board
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
coord = Hexagonal.Axial.from_screen_xy(mouse, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
{x,y} = App.KL.Game.Phase.Play.draw.centralize.old(coord, screen)
let has_tile = App.KL.Game.Tile.get(coord, board)
case has_tile {
none:
img
some:
VoxBox.Draw.image(x, y, App.KL.Constants.z_index.cursor, App.KL.Game.Field.Mouse.mouse_ui, img)
}
// draws tile terrain
App.KL.Game.Phase.Play.draw.canvas.tile.terrain(
terrain: App.KL.Game.Terrain
picks: App.KL.Game.Picks
indicator: Maybe<App.KL.Game.Indicator>
tile_coord: Hexagonal.Axial
screen: Pair<U32, U32>
img: VoxBox
): VoxBox
let indicator = indicator <> App.KL.Game.Indicator.background
let {i, j} = App.KL.Game.Phase.Play.draw.centralize.new(tile_coord, screen)
let field = App.KL.Game.Field.get_by_id.default(terrain@field_id)
let field_drawing = field@draw(terrain, indicator)
let tile_drawing = VoxBox.Draw.image(i, j, I32.to_u32(tile_coord@j + App.KL.Constants.z_index.terrain), field_drawing, img)
let tile_drawing = App.KL.Game.Phase.Play.draw.letter(tile_coord, picks, screen, tile_drawing)
tile_drawing
App.KL.Game.Phase.Play.draw.canvas.tile.indicator(
indicator: Maybe<App.KL.Game.Indicator>
tile_coord: Hexagonal.Axial
screen: Pair<U32,U32>
img: VoxBox
): VoxBox
without indicator: img
let {i, j} = App.KL.Game.Phase.Play.draw.centralize.new(tile_coord, screen)
let ind_img = App.KL.Game.Indicator.get_img(indicator)
let img = VoxBox.Draw.image(i, j, App.KL.Constants.z_index.indicator, ind_img, img)
img
App.KL.Game.Phase.Play.draw.canvas.tile.creature.get_draw_pose(game: App.KL.Game, coord: Hexagonal.Axial): App.KL.Game.Hero.Draw.Pose
open game
case game.moment {
initial: App.KL.Game.Hero.Draw.Pose.idle
preparation:
App.KL.Game.Hero.Draw.Pose.idle
execution: case game.moment.casts {
nil:
App.KL.Game.Hero.Draw.Pose.idle
cons: Maybe {
//get success = if game.moment.success then some(unit) else none
get success = case game.moment.success {
left: none
right: some(unit)
}
get creature = App.KL.Game.Board.Creature.get(coord, game.board)
let cast = game.moment.casts.head
get player = creature@player
open cast
if String.eql(player, cast.player) then Maybe {
let frame = game.moment.frame
let center = game.moment.coord <> coord
let target = cast.target
let letter = cast.letter
get skill = App.KL.Game.Cast.get_skill(cast, game)
get creature = App.KL.Game.Cast.get_creature(cast, game)
return App.KL.Game.Hero.Draw.Pose.cast(frame, center, target, letter, skill, creature)
} else none
} <> App.KL.Game.Hero.Draw.Pose.idle
}
}
// draws tile creature if any
App.KL.Game.Phase.Play.draw.canvas.tile.creature(
game: App.KL.Game
creature: Maybe<App.KL.Game.Creature>,
coord: Hexagonal.Axial,
ap_used: Maybe<Pair<String, I32>>
screen: Pair<U32,U32>
img: VoxBox
): VoxBox
case creature {
none: img
some:
let hero = creature.value@hero
let draw_pose = App.KL.Game.Phase.Play.draw.canvas.tile.creature.get_draw_pose(game, coord)
let {draw_coord, draw_voxbox} = hero@draw@vbox_img(draw_pose)
let draw_coord = draw_coord <> coord
//let aux = I32.to_u32(App.KL.Constants.hexagon_radius) //U32
//let cy = cy - (aux * 2) //U32
//let cx = cx - aux //U32
//log(U32.show( cy + 100))
{cx, cy} = Hexagonal.Axial.to_screen_xy(draw_coord, App.KL.Constants.hexagon_radius, U32.to_i32(screen@fst) / 4, U32.to_i32(screen@snd) / 4)
let img_x = cx - (128::U32)
let img_y = cy - (128::U32)
let height = I32.to_u32(hero@draw@height)
let img = VoxBox.Draw.image(img_x, img_y, App.KL.Constants.z_index.hero, draw_voxbox, img)
open creature.value as creature
case creature.player {
none:
img
some:
let img = App.KL.Game.Phase.Play.Bar.show_hp(cx - 17, (cy - height), creature.value, img)
let img = App.KL.Game.Phase.Play.draw.ap(img_x - 12, (img_y - height) - 3, creature.value, ap_used, img)
img
}
}

View File

@ -0,0 +1,429 @@
App.KL.Game.Phase.Play.draw.interface(
local: App.KL.Game.State.Local,
game: App.KL.Game
players_info: Map<PlayersInfo>
): DOM
<div>
{App.KL.Game.Phase.Play.draw.interface.top(players_info, local, game)}
{App.KL.Game.Phase.Play.draw.interface.bottom(local@user, players_info, local@hud@skill)}
{App.KL.Game.Phase.Play.draw.interface.user(local@user, players_info)}
{App.KL.Game.Phase.Play.draw.interface.casts(local@user, game@moment, game@players)}
</div>
App.KL.Game.Phase.Play.draw.interface.casts(user: String, moment: App.KL.Game.Moment, players: Map<App.KL.Game.Player>): DOM
case moment {
execution:
casts = moment.casts
p_cst = moment.previous_casts
<div style={
"position": "absolute"
"bottom": "0"
"right": "0"
"width": "300px"
"margin-right": "5px"
}>
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, p_cst[1], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, p_cst[0], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(true, casts[0], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, casts[1], players)}
{App.KL.Game.Phase.Play.draw.interface.casts.item(false, casts[2], players)}
</div>
} default <span style={"display": "none"}></span>
App.KL.Game.Phase.Play.draw.interface.casts.item(main: Bool, cast: Maybe<App.KL.Game.Cast>, players: Map<App.KL.Game.Player>): DOM
let name = Maybe {
get cast = cast
get player = players{cast@player}
get hero_id = player@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
get skill = hero@skills{Char.to_string(cast@letter)}
return hero@name | " - " | skill@name
} <> ""
<div style={
"color": "white"
"background-color": if main && Bool.not(name =? "") then "#2a1956" else "transparent"
"padding": "0 20px"
"margin-left": if main then "0" else "2%"
"height": if main then "48px" else "36px"
"flex": if main then "2" else "1"
"display": "flex"
"border-radius": "5px"
"align-items": "center"
}>name</div>
App.KL.Game.Phase.Play.draw.interface.top(players_info: Map<PlayersInfo>, local: App.KL.Game.State.Local, game: App.KL.Game): DOM
let inner =
<div>
{App.KL.Game.Phase.Play.draw.interface.top.timer(game@moment)}
{App.KL.Game.Phase.Play.draw.interface.top.round(game@turn)}
{App.KL.Game.Phase.Play.draw.interface.top.scores(game@score)}
{App.KL.Game.Phase.Play.draw.interface.top.players(local@user, players_info, game@cemetery, game@board)}
</div>
<header style={
"position": "absolute",
"top": "0"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(624, 91, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.Assets.interface.top, inner)}
</header>
App.KL.Game.Phase.Play.draw.interface.top.timer(moment: App.KL.Game.Moment): DOM
let bar = case moment {
initial:
if moment.countdown >? App.KL.Constants.initital_delay then
U64.to_f64(moment.countdown - App.KL.Constants.initital_delay) / U64.to_f64(App.KL.Constants.initial_time)
else
0.0
preparation:
U64.to_f64(moment.countdown) / U64.to_f64(App.KL.Constants.round_time)
execution: 0.0
}
<div style={
"position": "absolute"
"top": "4%"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"height": "8.5%"
"background-color": App.KL.Game.Phase.Play.draw.theme.secondary
"border-radius": "2px"
"width": String.show_clean(F64.show(bar * 44.5)) | "%"
}>
</div>
App.KL.Game.Phase.Play.draw.interface.top.round(round: U64): DOM
<div style={
"position": "absolute"
"bottom": "8%"
"font-size": "1.2rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}>
<span>Nat.show(U64.to_nat(round))</span>
</div>
App.KL.Game.Phase.Play.draw.interface.top.scores(scores: App.KL.Game.Score): DOM
let blue_hp = I32.sub(App.KL.Constants.max_score, scores@points@snd)
let red_hp = I32.sub(App.KL.Constants.max_score, scores@points@fst)
<div style={
"position": "absolute"
"top": "35%"
"font-size": "1.5rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}>
<span style={"margin-right": "2.2%"}>Nat.show(I32.to_nat(blue_hp))</span>
<span>Nat.show(I32.to_nat(red_hp))</span>
</div>
App.KL.Game.Phase.Play.draw.interface.top.players(user: String, players_info: Map<PlayersInfo>, cemetery: App.KL.Game.Cemetery, board: App.KL.Game.Board): DOM
// get team to show in left and team to show in right
let {user_team, enemy_team} =
Maybe {
get info = players_info{user}
let player = info@snd
let team = player@team
case team {
blue: some({App.KL.Game.Team.blue, App.KL.Game.Team.red})
red: some({App.KL.Game.Team.red, App.KL.Game.Team.blue})
neutral: none
}
} <> {App.KL.Game.Team.blue, App.KL.Game.Team.red} // set as default team
// TODO change when formap for DOM published
let players_info = Map.to_list!(players_info)
<div style={"display": "contents"}>
<div style={
"position": "absolute"
"top": "18%"
"left": "3.2%"
"width": "39.7%"
"height": "51%"
"display": "grid"
"grid-template-columns": "repeat(5, 1fr)"
"grid-template-rows": "1fr"
"grid-column-gap": "3px"
}>
for info in players_info:
let {id, player_info} = info
let {creature, player} = player_info
let team = player@team
let dead = List.find!((x) id =? x@fst, cemetery)
if team =? user_team then
App.KL.Game.Phase.Play.draw.interface.top.creature(creature, dead, false, id =? user)
else
<span style={"display": "none"}></span>
</div>
<div style={
"position": "absolute"
"top": "18%"
"left": "57%"
"width": "39.7%"
"height": "51%"
"display": "grid"
"grid-template-columns": "repeat(5, 1fr)"
"grid-template-rows": "1fr"
"grid-column-gap": "3px"
}>
for info in players_info:
let {id, player_info} = info
let {creature, player} = player_info
let team = player@team
let dead = List.find!((x) id =? x@fst, cemetery)
if team =? enemy_team then
App.KL.Game.Phase.Play.draw.interface.top.creature(creature, dead, true, false)
else
<span style={"display": "none"}></span>
</div>
</div>
App.KL.Game.Phase.Play.draw.interface.top.creature(creature: Maybe<App.KL.Game.Creature>, dead: Maybe<App.KL.Game.Cemetery.Dead>, is_enemy: Bool, is_user: Bool): DOM
let life_percentage = String.show_clean(F64.show(App.KL.Game.Phase.Play.draw.get_life_percentage(creature)))
let ap = App.KL.Game.Phase.Play.draw.get_ap(creature)
<div style={"position": "relative", "width": "100%", "height": "100%", "order": if is_user then "1" else "2"}>
// portrait
<img src=App.KL.Game.Phase.Play.Assets.interface.top.portrait_placeholder style={
"top": "2%"
"left": "4.5%"
"transform-origin": "top left"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"position": "absolute"
}></img>
<div style={"position": "absolute", "top": "46%", "left": "63%", "transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")", "transform-origin": "top left"}>
{ App.KL.Game.Phase.Play.draw.interface.top.creature.life_ap(life_percentage, ap, is_enemy) }
</div>
// death portrait
{
case dead {
none: <span style={"display":"none"}></span>
some:
<div style={"display": "contents"}>
<img src=App.KL.Game.Phase.Play.Assets.interface.top.dead style={
"left": "0"
"transform-origin": "top left"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"position": "absolute"
}></img>
<span style={
"position": "absolute"
"top": "38%"
"font-size": ".9rem"
"margin-left":" auto"
"margin-right":" auto"
"left":" 0"
"right":" 0"
"text-align":" center"
"color": "white"
}> String.show_clean(I32.show(dead.value@snd)) | " TURNS"</span>
</div>
}
}
</div>
App.KL.Game.Phase.Play.draw.interface.top.creature.life_ap(life_percentage: String, ap: I32, is_enemy: Bool): DOM
<div style={"position": "relative"}>
// life bar
<img src=App.KL.Game.Phase.Play.Assets.interface.top.life_placeholder></img>
<img
src= if is_enemy then App.KL.Game.Phase.Play.Assets.interface.top.life_red else App.KL.Game.Phase.Play.Assets.interface.top.life_green
style={
"left": "2px"
"top": "1px"
"position": "absolute"
"clip-path": "polygon(0 0%, "|life_percentage|"% 0%, "|life_percentage|"% 100%, 0% 100%)"
}>
</img>
// ap bar
for img in App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap, [{2.0,21.0}, {8.0,15.0}, {14.0,9.0}]):
img
</div>
App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap: I32, positions: List<Pair<F64, F64>>): List<DOM>
if ap <=? 0 then []
else
case positions {
nil: []
cons:
<img src=App.KL.Game.Phase.Play.Assets.interface.top.ap style={
"position": "absolute"
"left": String.show_clean(F64.show(positions.head@fst)) | "px"
"top": String.show_clean(F64.show(positions.head@snd)) | "px"
}></img> & App.KL.Game.Phase.Play.draw.interface.top.creature.ap(ap - 1, positions.tail)
}
App.KL.Game.Phase.Play.draw.interface.bottom(user: String, players_info: Map<PlayersInfo>, skill_hovered: Maybe<App.KL.Game.Skill>): DOM
// get user in players map
// if user isnt a player this interface isnt shown
let info = players_info{user}
without info: <span style={"display": "none"}></span>
// get hero of user, if none this interface isnt shown
let hero =
Maybe {
let player = info@snd
get hero_id = player@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
return hero
}
without hero: <span style={"display": "none"}></span>
// draw content TODO change when formap implemented
let skills = hero@skills
let skills_list = App.KL.Game.Phase.Play.draw.interface.bottom.get_skills(skills, 4)
let content =
<div style={
"position": "relative"
"width": "100%"
"height": "100%"
}>
{
let walk_key = App.KL.Game.Phase.Play.draw.interface.bottom.get_walk_key(skills)
<span style={"position": "absolute", "left": "1.25%", "top": "25%"}>walk_key</span>
}
<div style={
"position": "absolute"
"display": "grid"
"grid-template-columns": "repeat(4, 1fr)"
"grid-template-rows": "1fr"
"gap": "2%"
"width": "73%"
"height": "73%"
"left": "13.5%"
}>
for info in skills_list:
let {key, skill} = info
let id = "SK"|key
let show = Maybe.if!((x) String.eql(skill@name, x@name), skill_hovered)
<div style={
"position": "relative"
}>
<div id=id style={
"background-color": "#190d1f"
"border-radius": "5px"
"padding": "5px"
"animation": "fade-in 0.1s"
"position": "absolute"
"transform-origin": "bottom center"
"transform": "translate(-15%, -101%)"
"width": "150%"
"color": "white"
"display": if show then "block" else "none
"
}>skill@description</div>
<span id=id style={"position": "absolute", "bottom": "1%", "left": "7%"}>key</span>
<span id=id style={"position": "absolute", "width": "100%", "height": "100%", "display": "flex", "justify-content": "center", "align-items": "center", "color": "white"}>skill@name</span>
</div>
</div>
</div>
<footer style={
"position": "absolute",
"bottom": "0"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(280, 65, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.Assets.interface.bottom, content)}
</footer>
App.KL.Game.Phase.Play.draw.interface.user(user: String, players_info: Map<PlayersInfo>): DOM
let info = players_info{user}
without info: <span style={"display": "none"}></span>
let creature = info@fst
let life_percentage = App.KL.Game.Phase.Play.draw.get_life_percentage(creature)
let ap = App.KL.Game.Phase.Play.draw.get_ap(creature)
let content =
<div style={
"position": "relative"
"width": "100%"
"height": "100%"
}>
<img src=App.KL.Game.Phase.Play.Assets.interface.top.portrait_placeholder style={
"position": "absolute"
"transform": "scale("|F64.show(App.KL.Game.Phase.Play.draw.fator.number * 2)|")"
"transform-origin": "top left"
"top": "4%"
"left": "4%"
}></img>
<img src= App.KL.Game.Phase.Play.Assets.interface.user.life style={
"position": "absolute"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"transform-origin": "top left"
"top": "61%"
"left": "34%"
"clip-path": "polygon(0 0%, "|String.show_clean(F64.show(life_percentage + 8))|"% 0%, "|String.show_clean(F64.show(life_percentage))|"% 100%, 0% 100%)"
}></img>
<div style={
"position": "absolute"
"top": "74%"
"left": "31%"
"display": "flex"
"transform": "scale("|App.KL.Game.Phase.Play.draw.fator.string|")"
"transform-origin": "top left"
}>
for i in [0 to ap : I32]:
<img src=App.KL.Game.Phase.Play.Assets.interface.user.ap style={
"margin-right": "-3px"
}></img>
</div>
</div>
<footer style={
"position": "absolute",
"bottom": "0"
"left": "0"
"width": "min-content"
}>
{App.KL.Game.Phase.Play.draw.wrapper(249, 112, 0, "", App.KL.Game.Phase.Play.draw.fator.number, App.KL.Game.Phase.Play.Assets.interface.user, content)}
</footer>
// AUX FUNCTION
// =========================================
App.KL.Game.Phase.Play.draw.interface.bottom.get_skills(
skills: Map<App.KL.Game.Skill>,
max: Nat
): List<Pair<String, App.KL.Game.Skill>>
result = {[] :: List<Pair<String, App.KL.Game.Skill>>, max}
for key: skill in skills with result:
if (max <=? 0) || (skill@name =? "Walk") then
result
else
let result = result@fst <- {key, skill} & result@fst
result@snd <- result@snd - 1
result@fst
App.KL.Game.Phase.Play.draw.interface.bottom.get_walk_key(skills: Map<App.KL.Game.Skill>): String
case skills {
tip: ""
bin:
if skills.val@name =? "Walk" then
skills.key
else
App.KL.Game.Phase.Play.draw.interface.bottom.get_walk_key(skills.left) | App.KL.Game.Phase.Play.draw.interface.bottom.get_walk_key(skills.right)
}

View File

@ -0,0 +1,520 @@
App.KL.Game.Phase.Play.draw.tab(
local: App.KL.Game.State.Local,
game: App.KL.Game,
players_info: Map<PlayersInfo>
): DOM
let tab_active = local@hud@tab_active
let tab_which = local@hud@tab_which
if tab_active then
<div style={
"position": "fixed"
"top": "0"
"left": "0"
"width": "100vw"
"height": "100vh"
"background-color": "rgba(0,0,0,0.35)"
"animation": "fade-in 100ms"
}>
<div class="pixel-art" style={
"position": "fixed"
"top": "50%"
"left": "50%"
"transform": "scale("| App.KL.Game.Phase.Play.draw.fator.string |") translate(-50%, -50%)"
"transform-origin": "top left"
"box-shadow": "100% 100% 30px black"
}>
<div style={
"position": "relative"
}>
<img src=App.KL.Game.Phase.Play.Assets.tab.background></img>
{ App.KL.Game.Phase.Play.draw.tab.close }
{ App.KL.Game.Phase.Play.draw.tab.score(game@score) }
{ App.KL.Game.Phase.Play.draw.tab.timer }
{ App.KL.Game.Phase.Play.draw.tab.content(tab_which, local@user, players_info) }
{ App.KL.Game.Phase.Play.draw.tab.controls(tab_which) }
</div>
</div>
</div>
else
<span style={"display": "none"}></span>
App.KL.Game.Phase.Play.draw.tab.score(score: App.KL.Game.Score): DOM
let blue_hp = I32.sub(App.KL.Constants.max_score, score@points@snd)
let red_hp = I32.sub(App.KL.Constants.max_score, score@points@fst)
<div style={
"position": "absolute"
"width": "87%"
"top": "5%"
"display": "flex"
"justify-content": "space-between"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"color": "white"
}>
<span> String.show_clean(I32.show(blue_hp)) </span>
<span> String.show_clean(I32.show(red_hp)) </span>
</div>
App.KL.Game.Phase.Play.draw.tab.close: DOM
<div style={
"position": "absolute"
"right": "-12px"
"top": "-8px"
}>
<img src=App.KL.Game.Phase.Play.Assets.tab.button.close></img>
</div>
App.KL.Game.Phase.Play.draw.tab.timer: DOM
<div style={
"position": "absolute"
"top": "8.3%"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
"color": App.KL.Game.Phase.Play.draw.theme.secondary
}>
<span>"13:58"</span>
</div>
App.KL.Game.Phase.Play.draw.tab.content(
tab_which: App.KL.Game.Controls.Hud.Tab
user: String
players: Map<PlayersInfo>
): DOM
<div style={
"left": "1%"
"top": "15%"
"position": "absolute"
"height": "72%"
"width": "98%"
}>
{
case tab_which {
stats: App.KL.Game.Phase.Play.draw.tab.content.stats(user, players)
recap: App.KL.Game.Phase.Play.draw.tab.content.recap(user, players)
skills:
let players = BBT.map!!!((x) x@snd, players)
App.KL.Game.Phase.Play.draw.tab.content.skills(players)
}
}
</div>
App.KL.Game.Phase.Play.draw.tab.content.skills(players: Map<App.KL.Game.Player>): DOM
let rows_quantity = 10 // 7 is the number of rows
let skills = App.KL.Game.Phase.Play.draw.get_skills_to_tab(players)
let blocks = List.chunks_of!(rows_quantity, skills) // 7 is the number of rows
let blocks = List.indices!(blocks)
let last = List.length!(blocks) - 1
<div style={
"height": "100%"
"display": "flex"
"margin": "0 5%"
"overflow-x": "auto"
"animation": "fade-in 100ms"
}>
for block in blocks:
let { block_number, skills_info } = block
<div style={"display": "contents"}>
<div style={"height": "100%"}>
<div style={
"height": "8%"
"display": "flex"
"align-items": "center"
"margin-bottom": "5px"
}>
{
if block_number =? 0 then
<div style={"display": "contents"}>
<img
style={"margin-right": "5px"}
src=App.KL.Game.Phase.Play.Assets.tab.arrow.1
></img>
<span style={"color": "#861cef"}>"Beginning"</span>
</div>
else
<img src=App.KL.Game.Phase.Play.Assets.tab.arrow.2></img>
}
</div>
for skill_info in skills_info:
<div style={
"height": "7%"
"display": "flex"
"align-items": "center"
"text-transform": "uppercase"
"color": "white"
"margin-bottom": "5px"
}>
{
case skill_info {
left:
<img
style={"width": "100%"}
src=App.KL.Game.Phase.Play.Assets.tab.divisor.walk
> </img>
right:
let {key, info} = skill_info.value
let {hero, skill} = info
<div style={"display": "contents"}>
<img
style={"margin-right": "5px", "height": "100%"}
src=App.KL.Game.Phase.Play.Assets.tab.portrait.neutral
></img>
<img
style={"margin-right": "5px", "height": "100%"}
src=App.KL.Game.Phase.Play.Assets.tab.portrait.neutral
></img>
<span style={"font-size": ".55rem"}>skill@name</span>
</div>
}
}
</div>
</div>
<div style={"margin": "0 10px", "display": "flex", "align-items": "flex-end"}>
{
if block_number =? last then
<span style={"display": "none"}></span>
else
<img
src=App.KL.Game.Phase.Play.Assets.tab.divisor.vertical
style={"height": "91.5%"}
></img>
}
</div>
</div>
</div>
App.KL.Game.Phase.Play.draw.tab.content.stats(
user: String,
players: Map<PlayersInfo>
): DOM
let {allies, enemies} = App.KL.Game.Phase.Play.draw.get_allies_enemies(user, players)
let allies = List.indices!(Map.values!(allies))
let enemies = List.indices!(Map.values!(enemies))
<div style={"display": "flex", "justify-content": "space-between", "width": "100%", "height": "100%", "animation": "fade-in 100ms"}>
{ App.KL.Game.Phase.Play.draw.tab.content.stats.table(allies, false) }
<img
style={"height": "100%"}
src=App.KL.Game.Phase.Play.Assets.tab.divisor.vertical
></img>
{ App.KL.Game.Phase.Play.draw.tab.content.stats.table(enemies, true) }
</div>
App.KL.Game.Phase.Play.draw.tab.content.stats.table(
players: List<Pair<Nat, PlayersInfo>>
reversed: Bool
): DOM
let last = List.length!(players) - 1
let flex_direction =
if reversed then "row-reverse" else "row"
<div style={
"width": "45%"
"height": "100%"
"text-align": "center"
"color": "white"
}>
<div> // header
<div style={
"display": "flex"
"align-items": "center"
"color": App.KL.Game.Phase.Play.draw.theme.secondary
"font-size": "0.7rem"
"flex-direction": flex_direction
}>
<div style={"flex": "2"}></div>
<div style={"flex": "1"}>"Hp"</div>
<div style={"flex": "1"}>"Kills"</div>
<div style={"flex": "1"}>"Deaths"</div>
<div style={"flex": "1"}>"Assists"</div>
</div>
</div>
for info in players: // body
let {indice, player_info} = info
let creature = player_info@fst
let player = player_info@snd
let hero = App.KL.Game.Phase.Play.draw.get_player_hero(player)
let last = indice =? last
case hero {
none: <span style={"display": "none"}></span>
some: App.KL.Game.Phase.Play.draw.tab.stats.table.row(reversed, last, hero.value, player, creature)
}
</div>
App.KL.Game.Phase.Play.draw.tab.stats.table.row(
reversed: Bool
last: Bool
hero: App.KL.Game.Hero
player: App.KL.Game.Player
creature: Maybe<App.KL.Game.Creature>
): DOM
let inside_margin = // apply margin left if in right and vice-versa
if reversed then "0 0 0 5px" else "0 5px 0 0"
let outside_margin =
if reversed then "0 12px 0 0" else "0 0 0 12px"
let text_align =
if reversed then "right" else "left"
let flex_direction =
if reversed then "row-reverse" else "row"
let portrait =
if reversed then
App.KL.Game.Phase.Play.Assets.tab.portrait.enemy
else
App.KL.Game.Phase.Play.Assets.tab.portrait.ally
<div style={"height": "17%", "font-size": "0.8rem"}>
<div style={
"display": "flex"
"align-items": "center"
"flex-direction": flex_direction
"height": "calc(100% - 11px)" // 10px from 3px of bottom image + 8px of margin
}>
<div style={
"flex": "2"
"height": "100%"
}>
<div style={
"display": "flex"
"align-items": "center"
"flex-direction": flex_direction
"height": "100%"
"margin": outside_margin
}>
<img
style={"margin": inside_margin, "height": "100%"}
src=portrait
></img>
<div style={"text-transform": "uppercase", "text-align": text_align}>
<p style={"font-size": "0.8rem"}>hero@name</p>
<p style={"font-size": "0.7rem", "color": App.KL.Game.Phase.Play.draw.theme.secondary}>"User"</p>
</div>
</div>
</div>
<div style={"flex": "1"}><p>I32.show(App.KL.Game.Phase.Play.draw.get_life(creature))</p></div>
<div style={"flex": "1"}><p>I32.show(player@scoreboard@kills)</p></div>
<div style={"flex": "1"}><p>I32.show(player@scoreboard@deaths)</p></div>
<div style={"flex": "1"}><p>"100"</p></div>
</div>
{
if last then
<span style={"display": "none"}></span>
else
<img
style={"display": "flex", "margin": "4px 0", "width": "100%"}
src=App.KL.Game.Phase.Play.Assets.tab.divisor.horizontal
></img>
}
</div>
App.KL.Game.Phase.Play.draw.tab.content.recap(
user: String
players_info: Map<PlayersInfo>
): DOM
let player_info = players_info{user}
without player_info: App.KL.Game.Phase.Play.draw.tab.content.recap.placeholder // case user not in players map (espectator?)
let creature = player_info@fst
let player = player_info@snd
let recaps = List.take!(10, player@recap)
let recap_len = List.length!(recaps)
if recap_len =? 0 then
App.KL.Game.Phase.Play.draw.tab.content.recap.placeholder
else
<div style={
"width": "80%"
"height": "100%"
"animation": "fade-in 100ms"
"display": "flex"
"align-items": "flex-end"
"margin": "0 auto"
}>
<div style={"width": "100%"}>
<div style={"position": "relative", "display": "flex"}>
<img
src=App.KL.Game.Phase.Play.Assets.tab.recap.graph
style={"width": "100%"}
></img>
<div style={
"position": "absolute",
"top": "0",
"left": "0"
"width": "100%"
"height": "100%"
"display": "flex"
"flex-direction": "row-reverse"
"align-items": "flex-end"
"justify-content": "space-around"
"padding": "1px 0" // border of image
}>
for recap in recaps:
let hp = recap@new_hp
let diff = recap@hp_diff
let diff_percentage = App.KL.Game.Phase.Play.draw.tab.content.recap.get_percentage(diff, creature)
let life_percentage = App.KL.Game.Phase.Play.draw.tab.content.recap.get_percentage(hp, creature)
let life_percentage =
if diff >? 0 then life_percentage - diff_percentage
else life_percentage
let life_percentage = F64.show(life_percentage)
let diff_percentage = F64.show(diff_percentage)
<div style={
"width": "8%",
"height": "100%",
"background-color": "#2d2b86",
"border": "2px solid #6b1fcc"
"display": "flex",
"flex-direction": "column"
"justify-content": "flex-end"
}>
{
case diff >? 0 {
true: <div style={"width": "100%", "height": diff_percentage|"%", "background": "#b5e61c"}></div>
false:<div style={"width": "100%", "height": diff_percentage|"%", "background": "#ed1c24"}></div>
}
}
<div style={"width": "100%", "height": life_percentage|"%", "background": "#eb6aff"}></div>
</div>
</div>
</div>
<div style={"width": "100%", "display": "flex", "justify-content": "space-around", "flex-direction": "row-reverse", "margin-top": "15px"}>
for recap in recaps:
let skill = App.KL.Game.Phase.Play.draw.tab.content.recap.get_skill(recap, players_info)
<div style={"width": "8%"}>
<div style={
"position": "relative"
"width": "100%"
}>
<img
src=App.KL.Game.Phase.Play.Assets.tab.portrait.neutral
style={"width": "100%"}
></img>
<div style={
"display": "flex",
"justify-content": "center",
"align-items": "center",
"position": "absolute"
"width": "100%", "height": "100%"
"top": "0", "left": "0"
"color": "white"
"font-size": "0.55rem"
}>
{
case skill {
none: <span></span>
some: <span>skill.value@name</span>
}
}
</div>
</div>
<img
src=App.KL.Game.Phase.Play.Assets.tab.portrait.neutral
style={"width": "50%", "margin": "-12px auto 0 auto", "display": "block", "position": "relative"}
></img>
</div>
</div>
</div>
</div>
App.KL.Game.Phase.Play.draw.tab.content.recap.get_skill(
recap: App.KL.Game.Recap.Episode
players_info: Map<PlayersInfo>
): Maybe<App.KL.Game.Skill>
Maybe {
let address = recap@address
get player_info = players_info{address}
let player = player_info@snd
get hero_id = player@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
let skill_key = Char.to_string(recap@skill_key)
get skill = hero@skills{skill_key}
return skill
}
App.KL.Game.Phase.Play.draw.tab.content.recap.placeholder: DOM
<div style={
"width": "100%",
"height": "100%",
"display": "flex"
"justify-content": "center"
"align-items": "center"
"color": "white"
}><span>"No recap to show... :("</span></div>
App.KL.Game.Phase.Play.draw.tab.content.recap.get_percentage(
number: I32,
creature: Maybe<App.KL.Game.Creature>
): F64
case creature {
none: 0
some:
let number = I32.abs(number)
F64.mul(100.0, I32.to_f64(number) / I32.to_f64(creature.value@hero@max_hp))
}
App.KL.Game.Phase.Play.draw.tab.controls(
active_tab: App.KL.Game.Controls.Hud.Tab
): DOM
<div style={
"position": "absolute"
"top": "89%"
"margin-left": "auto"
"margin-right": "auto"
"left": "0"
"right": "0"
"text-align": "center"
}>
{
App.KL.Game.Phase.Play.draw.tab.controls.button(
App.KL.Game.Phase.Play.Assets.tab.button.left,
App.KL.Game.Controls.Hud.Tab.stats,
active_tab
)
}
{
App.KL.Game.Phase.Play.draw.tab.controls.button(
App.KL.Game.Phase.Play.Assets.tab.button.middle,
App.KL.Game.Controls.Hud.Tab.skills,
active_tab
)
}
{
App.KL.Game.Phase.Play.draw.tab.controls.button(
App.KL.Game.Phase.Play.Assets.tab.button.right,
App.KL.Game.Controls.Hud.Tab.recap,
active_tab
)
}
</div>
App.KL.Game.Phase.Play.draw.tab.controls.button(
button: App.KL.Game.Phase.Play.Assets.tab.button,
button_tab: App.KL.Game.Controls.Hud.Tab
active_tab: App.KL.Game.Controls.Hud.Tab
): DOM
let tab_text = String.to_lower(App.KL.Game.Controls.Hud.Tab.show(button_tab))
let is_active = App.KL.Game.Controls.Hud.Tab.eql(button_tab, active_tab)
<div id=tab_text style={"position": "relative", "display": "inline-flex", "margin-right": "1px"}>
<img id=tab_text src=button(is_active)></img>
<div id=tab_text style={
"position": "absolute"
"top": "0"
"width": "100%"
"height": "100%"
"display": "flex"
"justify-content": "center"
"align-items": "center"
"color": "white"
"text-transform": "capitalize"
}>
tab_text
</div>
</div>

View File

@ -4,6 +4,8 @@ App.KL.Game.Phase.Play.when(
event: App.Event,
): IO<Maybe<App.State.local<App.KL.State>>>
let room = String.take(16, Crypto.Keccak.hash(local@room))
let controls = local@hud
open game
case event {
frame:
@ -13,63 +15,78 @@ App.KL.Game.Phase.Play.when(
let new_local = new_local@screen_size <- event.info@screen_size
App.set_local!(App.KL.State.Local.game(new_local))
mouse_move:
// mouse move on canvas
if String.eql("game_screen", event.id) then
let {x,y} = event.mouse_pos
let local = local@hud <- App.KL.Game.State.Local.hud.new(none)
let local = local@hud <- local@hud@skill <- none
let local = local@mouse <- {x / 2, y / 2}
App.set_local!(App.KL.State.Local.game(local))
// mouse move on interface
else
switch String.starts_with(event.id) {
"SK":
let key = String.drop(2, event.id)
Maybe {
get user = game@players{local@user}
get hero_id = user@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
get skill = hero@skills{key}
let local = local@hud <- local@hud@skill <- some(skill)
return App.set_local!(App.KL.State.Local.game(local))
} <> App.set_local!(App.KL.State.Local.game(local@hud <- local@hud@skill <- none))
} default App.set_local!(App.KL.State.Local.game(local@hud <- App.KL.Game.State.Local.hud.new(none)))
let default_controls = App.KL.Game.Controls.Hud.initial
let controls =
switch String.starts_with(event.id) {
// hover on skills
"SK":
let key = String.drop(2, event.id)
Maybe {
get user = game@players{local@user}
get hero_id = user@hero_id
get hero = App.KL.Game.Hero.get_by_id(hero_id)
get skill = hero@skills{key}
let controls = local@hud@skill <- some(skill)
return controls
} <> controls
} default controls
let local = local@hud <- controls
App.set_local!(App.KL.State.Local.game(local))
key_down:
case game@moment {
preparation:
let preview = local@preview
switch U16.eql(event.code) {
9#16:
let score = case local@score {
none: some("score")
some: none
}
let local = local@score <- score
App.set_local!(App.KL.State.Local.game(local))
27#16:
let preview = preview@skill <- none
IO {
App.new_post!(room, App.KL.Game.Phase.Play.Event.cast.cancel_casts)
App.set_local!(App.KL.State.Local.game(local@preview <- preview))
}
}default
local =
Maybe {
get casted_skill = App.KL.Game.Skill.get(local@user, event.code, game)
let skill =
case preview@skill as skill {
none:
some({event.code, 1})
some:
if skill.value@fst =? event.code then
none
else
// if tab (esc) pressed
if event.code =? 32#16 then
log("ENTROU")
let local = App.KL.Game.Phase.Play.when.invert_tab(true, controls, local)
App.set_local!(App.KL.State.Local.game(local))
else
case game@moment {
preparation:
let preview = local@preview
switch U16.eql(event.code) {
27#16:
let preview = preview@skill <- none
IO {
App.new_post!(room, App.KL.Game.Phase.Play.Event.cast.cancel_casts)
App.set_local!(App.KL.State.Local.game(local@preview <- preview))
}
}default
local =
Maybe {
get casted_skill = App.KL.Game.Skill.get(local@user, event.code, game)
let skill =
case preview@skill as skill {
none:
some({event.code, 1})
}
return local@preview <- preview@skill <- skill
} <> local
IO {
App.new_post!(room, App.KL.Game.Phase.Play.Event.cast.cancel_skill(event.code))
App.set_local!(App.KL.State.Local.game(local))
}
} default App.pass!
some:
if skill.value@fst =? event.code then
none
else
some({event.code, 1})
}
return local@preview <- preview@skill <- skill
} <> local
IO {
App.new_post!(room, App.KL.Game.Phase.Play.Event.cast.cancel_skill(event.code))
App.set_local!(App.KL.State.Local.game(local))
}
} default App.pass!
key_up:
// if tab (esc) released
if event.code =? 32#16 then
log("SAIU")
let local = App.KL.Game.Phase.Play.when.invert_tab(false, controls, local)
App.set_local!(App.KL.State.Local.game(local))
else
App.pass!
mouse_down:
case game.moment {
initial:
@ -81,8 +98,41 @@ App.KL.Game.Phase.Play.when(
let preview = preview@skill <- none
App.set_local!(App.KL.State.Local.game(local@preview <- preview))
}
mouse_click:
// switch tab
let local = App.KL.Game.Phase.Play.when.switch_tab(event.id, local)
App.set_local!(App.KL.State.Local.game(local))
} default App.pass!
App.KL.Game.Phase.Play.when.switch_tab(
event_id: String
local: App.KL.Game.State.Local
): App.KL.Game.State.Local
let controls = local@hud
let actual_tab = controls@tab_which
let to_string = App.KL.Game.Controls.Hud.Tab.show
let stats = App.KL.Game.Controls.Hud.Tab.stats
let skills = App.KL.Game.Controls.Hud.Tab.skills
let recap = App.KL.Game.Controls.Hud.Tab.recap
let tab = switch String.eql(event_id) {
to_string(stats): stats
to_string(recap): recap
to_string(skills): skills
} default actual_tab
let controls = controls@tab_which <- tab
let local = local@hud <- controls
local
App.KL.Game.Phase.Play.when.invert_tab(
active: Bool
controls: App.KL.Game.Controls.Hud
local: App.KL.Game.State.Local
): App.KL.Game.State.Local
let controls = controls@tab_active <- active
let local = local@hud <- controls
local
App.KL.Game.Phase.Play.when.initial.mouse_down(room: String, local: App.KL.Game.State.Local, game: App.KL.Game): IO<Maybe<App.State.local<App.KL.State>>>
let coord = Hexagonal.Axial.from_screen_xy(local@mouse, App.KL.Constants.hexagon_radius, U32.to_i32(local@screen_size@fst) / 4, U32.to_i32(local@screen_size@snd) / 4)

View File

@ -3,12 +3,4 @@ App.KL.Game.Player.get_allies(
players: Map<App.KL.Game.Player>
): Map<App.KL.Game.Player>
let team = player@team
let result = {}
for user:player in players with result:
if App.KL.Game.Team.eql(player@team, team) then
result{user} <- player
else
result
result
App.KL.Game.Player.get_from_team(team,players)

View File

@ -0,0 +1,14 @@
App.KL.Game.Player.get_enemies(
player: App.KL.Game.Player
players: Map<App.KL.Game.Player>
): Map<App.KL.Game.Player>
let team = player@team
let result = {}
for user:player in players with result:
if Bool.not(App.KL.Game.Team.eql(player@team, team)) then
result{user} <- player
else
result
result

View File

@ -0,0 +1,13 @@
App.KL.Game.Player.get_from_team(
team: App.KL.Game.Team
players: Map<App.KL.Game.Player>
): Map<App.KL.Game.Player>
let result = {}
for user:player in players with result:
if App.KL.Game.Team.eql(player@team, team) then
result{user} <- player
else
result
result

View File

@ -1,14 +1,14 @@
List.find_index<A: Type>(xs: List<A>, f: A -> Bool): Maybe<Pair<A,Nat>>
List.find_index<A: Type>(xs: List<A>, f: A -> Bool): Maybe<Nat>
List.find_index.go<A>(xs,f,Nat.zero)
List.find_index.go<A: Type>(xs: List<A>, f: A -> Bool, i: Nat): Maybe<Pair<A,Nat>>
List.find_index.go<A: Type>(xs: List<A>, f: A -> Bool, i: Nat): Maybe<Nat>
case xs {
nil : Maybe.none!,
cons: case f(xs.head) {
true : Maybe.some!(Pair.new!!(xs.head)(i)),
true : Maybe.some!(i),
false: List.find_index.go!(xs.tail,f,Nat.succ(i))
}
}

View File

@ -1,5 +1,5 @@
Word.s_show(size: Nat)(a: Word(size)): String
neg = Word.is_neg(size, a)
n = Word.to_nat!(Word.abs!(a))
sgn = if neg then "-" else "+"
sgn = if neg then "-" else ""
sgn | Nat.show(n)