;;-----------------------------LICENSE NOTICE------------------------------------
;;  This file is part of CPCtelera: An Amstrad CPC Game Engine 
;;  Copyright (C) 2021 Daniel José García Evans, Iván Alejandro Ontano Herrera,
;;  Sergio Izquierdo Pintado (PyroClastic Software)
;;
;;  Special Thanks to Ennio Fernando Velásquez Berlingeri (PyroBombastic)
;;
;;  This program is free software: you can redistribute it and/or modify
;;  it under the terms of the GNU Lesser General Public License as published by
;;  the Free Software Foundation, either version 3 of the License, or
;;  (at your option) any later version.
;;
;;  This program is distributed in the hope that it will be useful,
;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;  GNU Lesser General Public License for more details.
;;
;;  You should have received a copy of the GNU Lesser General Public License
;;  along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;
;;INPUT SYSTEM
;;

.include "../globals.h.s"
animation_clock: .db #0
revive_clock: .db #10

keyactions:
    ;;#####CONTROLES TECLADO AMSTRAD
    .dw Key_Q, key_up_action 
    ;;.dw Key_A, key_down_action 
    .dw Key_O, key_left_action
    .dw Key_P, key_right_action

    ;;#####CONTROLES JOY AMSTRAD
    ;;.dw Joy0_Up, key_up_action
    ;;.dw Joy0_Down, key_down_action
    .dw Joy0_Left, key_left_action
    .dw Joy0_Right, key_right_action
    .dw Joy0_Fire1, key_up_action

    ;;#####CONTROLES MODERNOS
    .dw Key_Space, key_up_action
    ;;.dw Key_CursorUp, key_up_action
    ;;.dw Key_CursorDown, key_down_action
    .dw Key_CursorLeft, key_left_action
    .dw Key_CursorRight, key_right_action

    .dw 0x0000

key_left_action:
    ld a, e_cmps(ix)
    and #e_cmps_alive   ;;compruebo que el personaje este vivo
    ret z

    ld a, e_cmps + e_size(ix)   ;;cargo la mascara de la espada
    and #0b01111111  ;;mato la espada
    ld e_cmps + e_size(ix), a   ;;actualizo la mascara de la espada

    ld a, e_x(ix)
    cp #9   ;;and a
    ret m   ;;ret z
    ld e_velX(ix), #-1 ;;Asignamos velocidad -1 a ix
    ret

key_right_action:
    ld a, e_cmps(ix)
    and #e_cmps_alive   ;;compruebo que el personaje este vivo
    ret z

    ld a, e_cmps + e_size(ix)   ;;cargo la mascara de la espada
    and #0b01111111  ;;mato la espada
    ld e_cmps + e_size(ix), a   ;;actualizo la mascara de la espada

    ld a, e_x(ix)
    add e_w(ix)
    sub #72 ;;#80
    ret nc

    ld e_velX(ix), #1 ;;Asignamos velocidad 1 a ix
    ret


key_up_action:
    ld a, e_cmps(ix)
    and #e_cmps_alive   ;;compruebo que el personaje este vivo
    jr z, revive_action
    ;;ret z
        ;;jump_action
        ld a, e_clock(ix)
        and a
        ret nz  ;;si no es 0 no hago nada
        ld a, #15                                                               ;;#####reinicio del timer_jump
        ld e_clock(ix), a ;;reinicio el timer si estaba a 0 y he saltado

        ld a, e_cmps + e_size(ix)   ;;cargo la mascara de la espada
        and #0b01111111  ;;mato la espada
        ld e_cmps + e_size(ix), a   ;;actualizo la mascara de la espada

        xor a
        add e_velY(ix) ;;A = e_velY
        ret nz

    ld e_velY(ix), #-11 ;;velocidad del salto
    ret

    revive_action:  ;;si no esta vivo se intenta revivir
    ld a, (revive_clock)
    dec a
    ld (revive_clock), a
    and a
    ret nz  ;;si no es 0 no hago nada
    ld a, #10                                                              ;;#####reinicio del revive_clock
    ld (revive_clock), a ;;reinicio el timer si estaba a 0 y he saltado
    ld a, (lives)               ;;3 vivo, R 2 revivo, R 1 revivo, R 0 no revivo
    dec a
    ret m                       ;;compruebo si me quedan vidas
    ld a, e_cmps(ix)            ;;cargo las mascaras del personaje
    or #0xC0                    ;;pongo a 1 la mascara de alive y render
    ld e_cmps(ix), a            ;;actualizo las mascaras del personaje
    
    ld e_x(ix), #38             ;;pongo al personaje en el centro 
    ld e_y(ix), #16             ;;pongo al personaje arriba
    ld e_velX(ix), #0           ;;elimino la inercia del personaje
    ld e_velY(ix), #0           ;;elimino la inercia del personaje
    ret

;;key_down_action:
;;    ld a, e_cmps(ix)
;;    and #e_cmps_alive   ;;si no esta vivo se intenta revivir
;;    ret nz
;;
;;    ld a, (lives)               ;;3 vivo, R 2 revivo, R 1 revivo, R 0 no revivo
;;    dec a
;;    ret m                       ;;compruebo si me quedan vidas
;;
;;    ld a, e_cmps(ix)            ;;cargo las mascaras del personaje
;;    or #0xC0                    ;;pongo a 1 la mascara de alive y render
;;    ld e_cmps(ix), a            ;;actualizo las mascaras del personaje
;;    
;;    ld e_x(ix), #38             ;;pongo al personaje en el centro 
;;    ld e_y(ix), #16             ;;pongo al personaje arriba
;;
;;    ld e_velX(ix), #0           ;;elimino la inercia del personaje
;;    ld e_velY(ix), #0           ;;elimino la inercia del personaje
;;
;;    ret

;;key_down_action::
    ;;ld a, e_cmps + e_size(ix)   ;;cargo la mascara de la espada
    ;;or #0b10000000              ;;revivo la espada
    ;;ld e_cmps + e_size(ix), a   ;;actualizo la mascara de la espada

    ;;ld a, #0
    ;;ld e_velX(ix), a            ;;velocidad horizontal a 0 del personaje
    ;;ld e_velX + e_size(ix), a   ;;velocidad horizontal a 0 de la espada

    ;;ld a, e_velY(ix)            ;;cae mas rapido el personaje
    ;;inc a
    ;;ld e_velY(ix), a            ;;velocidad vertical del personaje en caida
    ;;ld e_velY + e_size(ix), a   ;;velocidad vertical de la espada en caida

    ;;ld a, e_x(ix)               ;;cargo la x del personaje
    ;;ld e_x + e_size(ix), a      ;;igualo la x de la espada al del personaje

    ;;ld a, e_y(ix)               ;;cargo la y del personaje
    ;;add a, e_h(ix)              ;;me desplazo justo debajo del personaje
    ;;dec a
    ;;ld e_y + e_size(ix), a      ;;pongo la espada debajo del personaje
;;ret

key_revive_action::
    ld a, (lives)               ;;3 vivo, R 2 revivo, R 1 revivo, R 0 no revivo
    dec a
    ret m                       ;;compruebo si me quedan vidas
    ld a, e_cmps(ix)            ;;cargo las mascaras del personaje
    or #0xC0                    ;;pongo a 1 la mascara de alive y render
    ld e_cmps(ix), a            ;;actualizo las mascaras del personaje
    
    ld e_x(ix), #38             ;;pongo al personaje en el centro 
    ld e_y(ix), #16             ;;pongo al personaje arriba
    ld e_velX(ix), #0           ;;elimino la inercia del personaje
    ld e_velY(ix), #0           ;;elimino la inercia del personaje

    ret

sys_input_update::
    ;call cpct_scanKeyboard_f_asm
    call man_entity_first

    ld a, e_clock(ix)   ;;cargo el timer
    and a
    jr z, avoid_dec_jump_timer   ;;si es 0 no lo decremento
        dec a   ;;decremento el timer
        ld e_clock(ix), a   ;;actualizo el timer
    avoid_dec_jump_timer:    ;;se queda a 0 hasta que se reinicie al saltar


    ;;ld a, e_velX(ix)
    ;;or e_velY(ix)
    ;;jr nz, continue_rendering_hero
    ;;    ld a, e_cmps(ix)
    ;;    and #0b10111111 ;;se desactiva el render si no se esta moviendo en ninguna direccion
    ;;    ld e_cmps(ix), a
    ;;    jr continue_input
    ;;continue_rendering_hero:    
    ;;    ld a, e_cmps(ix)
    ;;    or #0b01000000 ;;se activa el render si se esta moviendo en alguna direccion
    ;;    ld e_cmps(ix), a
    ;;    ;;jr continue_input

    ;;ld a, e_cmps(ix)
    ;;and #e_cmps_alive
    ;;jr nz, not_revive   ;;compruebo si esta muerto
    ;;    call cpct_scanKeyboard_f_asm
    ;;    ld hl, #Key_Q
    ;;    call cpct_isKeyPressed_asm
    ;;    jr nz, not_revive               ;;si no esta pulsada continuo
    ;;        call cpct_scanKeyboard_f_asm    ;;vuelvo a escanear el teclado
    ;;        ld hl, #Key_Q
    ;;        call cpct_isKeyPressed_asm 
    ;;        jr z, not_revive            ;;si esta pulsada continuo
    ;;            call sys_input_update   ;;aqui no entra, deberia petar
    ;;            call key_revive_action
    ;;not_revive:

    ;;continue_input:

    ld e_velX(ix), #0 ;;Hacemos que no se mueva
    ;;ld e_velY(ix), #0
    ld iy, #keyactions-4    ;;le resto 4 para que al empezar el bucle sea 0 (la primera tecla)
    
    nextkey:
        ld bc, #4   ;;le suma 4 para pasar a la siguiente tecla
        add iy, bc  ;;esto no modifica el flag Z
        
        ;;Check next key code
        ld l, (iy)
        ld h, 1(iy)
        
        ;;Check for null to end
        ld a, l ;;comprueba que ni H ni L tengan un 1 usando un OR
        or h
        jr z, hero_change_sprite    ;;si HL esta vacio se rompe el bucle

        ;;Test Key and perform
        call cpct_isKeyPressed_asm
    jr z, nextkey

    ;;Key is pressed, perform key_left_action
    ld hl, #nextkey ;;guardo la direccion de salto al principio del bucle para volver despues de la accion de la tecla
    push hl ;;la pongo en la pila
    ld l, 2(iy)
    ld h, 3(iy)
    jp (hl) ;;se salta a la posicion que tenga la tecla pulsada (como hacer un call)


    ;;si la velocidad vertical no es 0
        ;;si la velocidad vertical es positiva
            ;;si la velocidad horizontal es positiva
                ;;sprite caida derecha

            ;;si la velocidad horizontal es negativa
                ;;sprite caida izquierda

        ;;si la velocidad vertical es negativa
            ;;si la velocidad horizontal es positiva
                ;;sprite salto derecha

            ;;si la velocidad horizontal es negativa
                ;;sprite salto izquierda

    ;;si la velocidad vertical es 0
        ;;si la velocidad horizontal no es 0
            ;;si la velocidad horizontal es positiva
                ;;sprite carrera derecha

            ;;si la velocidad horizontal es negativa
                ;;sprite carrera izquierda

        ;;si la velocidad horizontal es 0
            ;;sprite quieto
        
    hero_change_sprite:
        ld a, e_velY(ix)
        and a
        ;;si la velocidad vertical es cero
        jr z, vertical_still
            and a
            jp m, vertical_negative
            ;; Vertical positive
            ld a, e_velX(ix)
            and a
            jp m, left_fall
            ;;Caida Derecha
                ld e_sprite(ix), #<_main_char_10
                ld e_sprite + 1(ix), #>_main_char_10
                jp sword_shit
            ;;Caida Izquierda
            left_fall:
                ld e_sprite(ix), #<_main_char_11
                ld e_sprite + 1(ix), #>_main_char_11
                jp sword_shit
            vertical_negative:
                ld a, e_velX(ix)
                and a
                jp m, left_jump
                ;;Right Jump
                    ld e_sprite + 0(ix), #<_main_char_08
                    ld e_sprite + 1(ix), #>_main_char_08
                    jp sword_shit 
                ;;Salto Izquierdo
                left_jump:
                    ld e_sprite + 0(ix), #<_main_char_09
                    ld e_sprite + 1(ix), #>_main_char_09
                    jp sword_shit
            ;;De pie quietesito papa
            vertical_still:
                ld a, e_velX(ix)
                and a
                jp z, still_still
                and a
                jp p, movement_right

                    ld e_sprite + e_size + 0(ix), #<_main_char_12
                    ld e_sprite + e_size + 1(ix), #>_main_char_12
                    ;;2, 4, 6   (2 frames por sprite)
                    ;;3, 6, 9   (3 frames por sprite)
                    ;;4, 8, 12  (4 frames por sprite)
                    ld a, (animation_clock)
                    inc a
                    ld (animation_clock), a
                    cp #3   ;;si le resto dos y es negativo
                    jp m, first_frame_left
                        cp #6
                        jp m, second_frame_left
                            cp #9
                            jp m, third_frame_left
                                xor a
                                ld (animation_clock), a
                                jp first_frame_left ;;para que el first frame tenga los mismos frames que el resto y el tercero no tenga mas

                            third_frame_left:
                            ld e_sprite + 0(ix), #<_main_char_07
                            ld e_sprite + 1(ix), #>_main_char_07
                            jp sword_shit

                        second_frame_left:
                        ld e_sprite + 0(ix), #<_main_char_05
                        ld e_sprite + 1(ix), #>_main_char_05
                        jp sword_shit

                    first_frame_left:
                    ld e_sprite + 0(ix), #<_main_char_03
                    ld e_sprite + 1(ix), #>_main_char_03
                    jp sword_shit

                ;;Mover izq

                ;;mover derecha
                movement_right:
                    ld e_sprite + e_size + 0(ix), #<_main_char_13
                    ld e_sprite + e_size + 1(ix), #>_main_char_13
                    ;;2, 4, 6   (2 frames por sprite)
                    ;;3, 6, 9   (3 frames por sprite)
                    ;;4, 8, 12  (4 frames por sprite)
                    ld a, (animation_clock)
                    inc a
                    ld (animation_clock), a
                    cp #3   ;;si le resto dos y es negativo
                    jp m, first_frame_right
                        cp #6
                        jp m, second_frame_right
                            cp #9
                            jp m, third_frame_right
                                xor a
                                ld (animation_clock), a
                                jp first_frame_right ;;para que el first frame tenga los mismos frames que el resto y el tercero no tenga mas

                            third_frame_right:
                            ld e_sprite + 0(ix), #<_main_char_06
                            ld e_sprite + 1(ix), #>_main_char_06
                            jp sword_shit

                        second_frame_right:
                        ld e_sprite + 0(ix), #<_main_char_04
                        ld e_sprite + 1(ix), #>_main_char_04
                        jp sword_shit

                    first_frame_right:
                    ld e_sprite + 0(ix), #<_main_char_02
                    ld e_sprite + 1(ix), #>_main_char_02
                    jp sword_shit

                still_still:
                    ld e_sprite + 0(ix), #<_main_char_00
                    ld e_sprite + 1(ix), #>_main_char_00
                ;;jr sword_shit

    
    sword_shit:
    ;;si la espada esta viva
        ;;pongo el sprite de atacar a izquierda o derecha
    ;;si la espada esta muerta
        ;;pongo el sprite de caida normal a izquierda o derecha

    ld a, e_velY(ix)
    dec a
    jp p, use_sword
        ;;guardar espada
        ld a, e_cmps + e_size(ix)           ;;cargo las mascaras de la espada
        and #0x7F                           ;;pongo a 0 la mascara de alive
        ld e_cmps + e_size(ix), a           ;;actualizo las mascaras de la espada

        ld bc, #e_size
        add ix, bc  ;;pongo IX en la espada
        ;;;;call sys_render_clear_prev_pos_entity                 
        ;;call sys_render_clear_pos_entity    ;;borro la espada en su posicion actual
        ret 

    use_sword:  
    ;;sacar espada  
    ld a, e_cmps + e_size(ix)           ;;cargo las mascaras de la espada
    or #0xC0                            ;;pongo a 1 la mascara de alive y render
    ld e_cmps + e_size(ix), a           ;;actualizo las mascaras de la espada

    ld a, e_velY(ix)
    ld e_velY + e_size(ix), a               ;;copio la velocidad Y del personaje a la espada

    ld a, e_velX(ix)    
    ld e_velX + e_size(ix), a               ;;copio la velocidad X del personaje a la espada

    ld a, e_x(ix)   
    ld e_x + e_size(ix), a                  ;;copio la X del personaje a la espada

    ld a, e_y(ix)   
    add e_h + e_size(ix)    
    ld e_y + e_size(ix), a                  ;;copio la Y del personaje a la espada teniendo en cuenta el sprite

    ld bc, #e_size
    add ix, bc  ;;pongo IX en la espada
    ;;ld ix, e_size(ix)   
    
    ;;call sys_render_clear_prev_pos_entity                             
    ;;call sys_render_draw_entity             ;;dibuja la espada en su posicion actual

    ret