;;------------------------------------------------LICENSE NOTICE------------------------------------------------------------------------------
;;  This file is part of Amstrad CPC videogame "Redsea"
;;  Copyright (C) 2021 Crab Party / Elena López (AneleSplats in itch.io) / Iván Tortosa (Pluvs in itch.io, @IvanTortosaBer1 on Twitter) / Antonio Gosálvez (BalgroHub in itch.io)
;;  Copyright (C) 2015 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;;  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/>.
;;------------------------------------------------LICENSE NOTICE-------------------------------------------------------------------------

.globl man_entity_forall_matching_pairing
;.globl e_type_collision
.globl matching_type

.globl _tilemap_01
.globl _cosa
.include "cpctelera.h.s"
.globl m_entities
.globl borrarNivel
.globl cargarNivel1
.globl cargarNivel
.globl guardarNivel
.globl resetearNivel
.globl pasarNivel
.globl _mainC_death
.globl _goal_achieved
.globl _explotarArbol
.globl esperarAnim
.globl death_or_next
.globl tilemapActual
.globl bloquearMovimiento
.globl puertaUpdate

.globl cpct_akp_SFXPlay_asm
.globl cpct_akp_SFXStop_asm
.globl cpct_akp_SFXInit_asm
.globl cpct_akp_SFXGetInstrument_asm


;sys_collision_one_entity:: lo hace para ver los choques de personaje con input con tilemap
; tx = x/4
; ty = y/8
; tw = tilemap-width (0x30, 48)
; p = tilemap + ty * tw + tx

;; A = y
    ;; ld a, 2(ix)
    ;; add 4(ix) ;si no se pone esto en vez de apuntar a esquina abajo izq, apunta a la de arriba
;; A = ty (y/8)
    ;; and #F8    ; A = 8*int(ty/8)
;; HL = A (HL = 8*ty)
    ;; ld h, #0
    ;; ld l, a
;; HL = 48*HL
    ;; add hl, hl ;HL = 16*ty
    ;; ld d, h    ; | DE = 16*ty
    ;; ld e, l    ; |
    ;; add hl, hl ;HL = 32*ty
    ;; add hl, de ;HL = 48*ty
    
;; A = x
    ;; ld a, 1(ix)
    ;; srl a ; | A = tx (x/4)
    ;; srl a ; |

    ;; add_hl_a ; macro para añadirle a hl, a, HL = ty * tw + tx

    ;;ld de, #_tilemap_01
    ;; add hl, de

;; HL = tilemap + ty * tw + tx
    ;; ld a, (hl) ; A = title index on the foot on the entity
    ;; and #F8 ; si sale 0 es solido
    ;; ret nz
;; COLLISION DETECTED

    ;; ld 6(ix), #0

;ret

;;Metodos para cada entidad
;;Cuando una entidad se choca contra el suelo, no puede bajar más
;;Es decir, la velocidad y pasa a ser 0
chocarse_suelo:

    ld 6(ix), #0d0
    ld 5(ix), #0d0

ret

morir:

     ld a, (#esperarAnim)
     or a
     ret nz

        call sfx_morir


    call chocarse_suelo
    ld hl, #_mainC_death
    ld 13(ix), l
    ld 14(ix), h
    ld a, #7
    ld (#esperarAnim), a        ; Reiniciar contador de la animacion

     ; call pasarNivel
     ; call resetearNivel
     


ret

completado:

     ld a, (#esperarAnim)
     or a
     ret nz

    call chocarse_suelo
    ld hl, #_goal_achieved
    ld 13(iy), l
    ld 14(iy), h
    ld a, #7
    ld (#esperarAnim), a        ; Reiniciar contador de la animacion
    ld a, #1
    ld (#death_or_next), a        ; Reiniciar contador de la animacion

;         ld a,  #2  ;canal para reproducirlo
; call cpct_akp_SFXStop_asm


;       ld l,  #2 ;numero de instrumento en el sfx
;     ld h,  #15  ;volumen 0 - min, 15 - max
;     ld e,  #100 ; nota a tocar
;     ld d,  #0 ;velocidad 0 - original, 1-255 otra siendo 1 el mas rapido
;     ld bc, #0 ;pitch, 0 no hay
;     ld a,  #2  ;canal para reproducirlo
;     push ix
;      call cpct_akp_SFXPlay_asm
;      pop ix
    call sfx_ganar
     ; call pasarNivel
     ; call resetearNivel
     


ret

finalArbol:

     ld a, (#esperarAnim)
     or a
     ret nz

    call chocarse_suelo
    ld hl, #_explotarArbol
    ld 13(iy), l
    ld 14(iy), h
    ld a, #20
    ld (#esperarAnim), a        ; Reiniciar contador de la animacion
    ld a, #2
    ld (#death_or_next), a        ; Reiniciar contador de la animacion

    call sfx_ganar

ret


cogerLlave:
     ; Llama a updatePuerta de levels, que elimina la puerta y la llave
     push ix
     push iy
     pop ix
     call puertaUpdate
     pop ix
     call sfx_ganar

ret





sys_collision_update_entities::

    ;;Si no se pueden chocar, se sale fuera de la entidad
    ;Comprobamos que ix puede colisionar con iy
    ld a, 16(ix)
    and 15(iy)
    cp 15(iy)   ;;0 = ix puede colisionar con iy // !0 = no
    jr z, puede_colisionar

    ;Ahora comprobamos si iy puede colisionar con ix
    push ix
    push iy
    pop ix
    pop iy


    ld a, 16(ix)
    and 15(iy)
    cp 15(iy)   ;;0 = iy puede colisionar con ix // !0 = no
    jr z, puede_colisionar

    ;;Si llega aquí significa que ninguno puede colisionar con el otro, se sale del método
    ret


    puede_colisionar:
    
    ;;Primero se elige de caja cubo 2 aristas, una vertical y otra horizontal
    ;;Para que 2 cajas colisionen, uno de sus vértices tiene que estár entre la arista horizontal y vertical de la otra caja
    ;;Necesitamos 2 vértices para cada caja(sup-izq, sup-der, inf-izq), osea 4 bytes (hl y bc)
    
    ;;Vértices de la primera entidad (ix)
    ld a, 1(ix)
    add 5(ix)
    ld h, a
    add 3(ix)
    sub #1
    ld l, a

    ;;Vértices de la segunda entidad (iy)
    ld a, 1(iy)
    add 5(iy)
    ld b, a
    add 3(iy)
    sub #1
    ld c, a

    ;;Vemos si los primeros vértices están dentro de la segunda arista
    ;;Primero
    ld a, l
    sub b
    ret c 

    ;;Segundo
    ld a, c
    sub h
    ret c 


    ;;Vértices de la primera entidad (ix)
    ld a, 2(ix)
    add 6(ix)
    ld h, a
    add 4(ix)
    sub #1
    ld l, a

    ;;Vértices de la segunda entidad (iy)
    ld a, 2(iy)
    add 6(iy)
    ld b, a
    add 4(iy)
    sub #1
    ld c, a


    ;;Tercero
    ld a, l
    sub b
    ret c 

    ;;Cuarto
    ld a, c
    sub h
    ret c

    

    ;;Si el código ha llegado hasta aquí, es que la entidad (ix) ha colisionado con (iy)
    ;;Ahora dependiendo de con que ha chocado, hace una cosa u otra
    
    ;;Si ix es el jugador e iy es una entidad suelo, se llama a parar
	ld a, 15(iy)
	cp #0x02
	jr nz, seguir1
     call chocarse_suelo
	ret

	seguir1:
	;;Si ix es el jugador e iy es una entidad deadly, se llama a morir
	ld a, 15(iy)
	cp #0x08
	jr nz, seguir2
	call morir
     ret

     seguir2:
     ;;Si ix es el jugador e iy es una entidad goal, se llama a completado
	ld a, 15(iy)
	cp #0x10
	jr nz, seguir3
	call completado
     ret

     seguir3:
	;;Si ix es el jugador e iy es una entidad deadly, se llama a morir
	ld a, 15(iy)
	cp #0x20
     jr nz, seguir44
	call finalArbol
     ret

     seguir44:
	;;Si ix es el jugador e iy es una entidad llave, se llama a cogerLlave
	ld a, 15(iy)
	cp #0x40
	jr nz, seguir5
	call cogerLlave
     ret

     seguir5:
	;;Si ix es el jugador e iy es una entidad pared, se llama a chocarse_suelo
	ld a, 15(iy)
	cp #0x80
	ret nz
	call chocarse_suelo
     ret
    
	
ret

;Llama a forall para hacer sys_ai_one_entity con todas las entidades de IA y movibles
sys_collision_update::
    ld ix, #sys_collision_update_entities
    ld a, #0x20
    ld (#matching_type), a
    call man_entity_forall_matching_pairing
ret

sys_collision_tilemap::
    ld ix, #m_entities


     ; Si la velocidad en x es positiva, comprueba solo a la derecha
     ld a, 5(ix)
     cp #1
     jr nz, seguircol1
     call sys_collision_one_entity_upRight
     call sys_collision_one_entity_downRight


     seguircol1:
     ; Si al velocidad en x es negativa, comprueba solo la izquierda
     ld a, 5(ix)
     add #1
     jr nz, seguircol2
     call sys_collision_one_entity_upLeft
     call sys_collision_one_entity_downLeft


     seguircol2:
     ; Si la velocidad en y es positiva, solo coprueba abajo
     ld a, 6(ix)
     cp #3
     jr nz, seguircol3
     call sys_collision_one_entity_downLeft
     call sys_collision_one_entity_downRight


     seguircol3:
     ; Si la velocidad en y es negativa, solo comprueba arriba
     ld a, 6(ix)
     add #3
     ret nz
     call sys_collision_one_entity_upLeft
     call sys_collision_one_entity_upRight


ret








sys_collision_one_entity_downLeft:: ;lo hace para ver los choques de personaje con input con tilemap
; cpctm_setBorder_asm HW_BLACK
 ;;tx = x/4
 ;;ty = y/8
 ;;tw = tilemap-width (0x30, 48)
 ;;p = tilemap + ty * tw + tx

;; A = y
     ld a, 2(ix)
     add 4(ix) ;si no se pone esto en vez de apuntar a esquina abajo izq, apunta a la de arriba
     add 6(ix)
     sub #1
;; A = ty (y/8)
     ;and #0xF8    ; A = 8*int(ty/8)
     srl a
     srl a
     srl a
;; HL = A (HL = 8*ty)
     ld h, #0
     ld l, a
;; HL = 20*HL
     add hl, hl ;HL = 2*ty
     add hl, hl ;HL = 4*ty
     ld d, h    ; | DE = 4*ty
     ld e, l    ; |
     add hl, hl ;HL = 8*ty
     add hl, hl ;HL = 16*ty
     add hl, de ;HL = 20*ty
    
;; A = x
     ld a, 1(ix)
     add 5(ix)
     srl a ; | A = tx (x/4)
     srl a ; |

     add_hl_a ; macro para añadirle a hl, a, HL = ty * tw + tx

     ; metemos en de la direccion del tilemap de ahora(osea (#tilemapActual))
     push ix
     ld ix, #tilemapActual
     ld a, (ix)
     ld e, a
     ld a, 1(ix)
     ld d, a
     pop ix
     add hl, de

     ld a, (hl) ; A = title index on the foot on the entity
     ;and #0b11111010;#0xF4 ; si sale 0 es solido
     cp #7
     jr z, morirse

;; HL = tilemap + ty * tw + tx
     ld a, (hl) ; A = title index on the foot on the entity
     sub #25
     ret nc
;; COLLISION DETECTED

     ld 6(ix), #0
     ld 5(ix), #0
    call sfx_chocarse

     ret

    morirse:
    call morir
    ;call sfx_morir
ret


sys_collision_one_entity_downRight:: ;lo hace para ver los choques de personaje con input con tilemap
; cpctm_setBorder_asm HW_BLACK
 ;;tx = x/4
 ;;ty = y/8
 ;;tw = tilemap-width (0x30, 48)
 ;;p = tilemap + ty * tw + tx

;; A = y
     ld a, 2(ix)
     add 4(ix) ;si no se pone esto en vez de apuntar a esquina abajo izq, apunta a la de arriba
     add 6(ix)
     sub #1;; A = ty (y/8)
     ;and #0xF8    ; A = 8*int(ty/8)
     srl a
     srl a
     srl a
;; HL = A (HL = 8*ty)
     ld h, #0
     ld l, a
;; HL = 20*HL
     add hl, hl ;HL = 2*ty
     add hl, hl ;HL = 4*ty
     ld d, h    ; | DE = 4*ty
     ld e, l    ; |
     add hl, hl ;HL = 8*ty
     add hl, hl ;HL = 16*ty
     add hl, de ;HL = 20*ty
    
;; A = x
     ld a, 1(ix)
     add 3(ix)
     add 5(ix)
     sub #1
     ;add 5(ix)
     srl a ; | A = tx (x/4)
     srl a ; |

     add_hl_a ; macro para añadirle a hl, a, HL = ty * tw + tx

     ; metemos en de la direccion del tilemap de ahora(osea (#tilemapActual))
     push ix
     ld ix, #tilemapActual
     ld a, (ix)
     ld e, a
     ld a, 1(ix)
     ld d, a
     pop ix
     add hl, de

     ld a, (hl) ; A = title index on the foot on the entity
     ;and #0b11111010;#0xF4 ; si sale 0 es solido
     cp #7
     jr z, morirse2

;; HL = tilemap + ty * tw + tx
     ld a, (hl) ; A = title index on the foot on the entity
     sub #25
     ret nc
;; COLLISION DETECTED

     ld 6(ix), #0
      ld 5(ix), #0

    call sfx_chocarse
      ret

    morirse2:
    call morir
    ;call sfx_morir
ret






sys_collision_one_entity_upLeft::
 ;;tx = x/4
 ;;ty = y/8
 ;;tw = tilemap-width (0x30, 48)
 ;;p = tilemap + ty * tw + tx

;; A = y
     ld a, 2(ix)
     add 6(ix)
     ;add #(16 - 1) ;si no se pone esto en vez de apuntar a esquina abajo izq, apunta a la de arriba
;; A = ty (y/8)
     ;and #0xF8    ; A = 8*int(ty/8)
     srl a
     srl a
     srl a
;; HL = A (HL = 1*ty)
     ld h, #0
     ld l, a
;; HL = 20*HL
     add hl, hl ;HL = 2*ty
     add hl, hl ;HL = 4*ty
     ld d, h    ; | DE = 4*ty
     ld e, l    ; |
     add hl, hl ;HL = 8*ty
     add hl, hl ;HL = 16*ty
     add hl, de ;HL = 20*ty
     
    
;; A = x
     ld a, 1(ix)
     add 5(ix)
     srl a ; | A = tx (x/4)
     srl a ; |

     add_hl_a ; macro para añadirle a hl, a, HL = ty * tw + tx

    ; metemos en de la direccion del tilemap de ahora(osea (#tilemapActual))
     push ix
     ld ix, #tilemapActual
     ld a, (ix)
     ld e, a
     ld a, 1(ix)
     ld d, a
     pop ix
     add hl, de

;; HL = tilemap + ty * tw + tx
    ld a, (hl) ; A = title index on the foot on the entity
     ;and #0b11111010;#0xF4 ; si sale 0 es solido
     cp #7
     jr z, morirse3

     ld a, (hl) ; A = title index on the foot on the entity
     ;and #0b11111010;#0xF4 ; si sale 0 es solido
     sub #25
     ret nc
;; COLLISION DETECTED

    

     ld 6(ix), #0
      ld 5(ix), #0

    call sfx_chocarse
    ret

    morirse3:
    call morir
    ;call sfx_morir
ret

sys_collision_one_entity_upRight::
 ;;tx = x/4
 ;;ty = y/8
 ;;tw = tilemap-width (0x30, 48)
 ;;p = tilemap + ty * tw + tx

;; A = y
     ld a, 2(ix)
     add 6(ix)
     ;add #(16 - 1) ;si no se pone esto en vez de apuntar a esquina abajo izq, apunta a la de arriba
;; A = ty (y/8)
     ;and #0xF8    ; A = 8*int(ty/8)
     srl a
     srl a
     srl a
;; HL = A (HL = 8*ty)
     ld h, #0
     ld l, a
;; HL = 20*HL
     add hl, hl ;HL = 2*ty
     add hl, hl ;HL = 4*ty
     ld d, h    ; | DE = 4*ty
     ld e, l    ; |
     add hl, hl ;HL = 8*ty
     add hl, hl ;HL = 16*ty
     add hl, de ;HL = 20*ty
    
;; A = x
     ld a, 1(ix)
     add 3(ix)
     add 5(ix)
     sub #1
     srl a ; | A = tx (x/4)
     srl a ; |

     add_hl_a ; macro para añadirle a hl, a, HL = ty * tw + tx

    ; metemos en de la direccion del tilemap de ahora(osea (#tilemapActual))
     push ix
     ld ix, #tilemapActual
     ld a, (ix)
     ld e, a
     ld a, 1(ix)
     ld d, a
     pop ix
     add hl, de

     ld a, (hl) ; A = title index on the foot on the entity
     ;and #0b11111010;#0xF4 ; si sale 0 es solido
     cp #7
     jr z, morirse4

;; HL = tilemap + ty * tw + tx
     ld a, (hl) ; A = title index on the foot on the entity
     sub #25
     ret nc
;; COLLISION DETECTED

     ld 6(ix), #0
      ld 5(ix), #0

    call sfx_chocarse
      ret

    morirse4:
    call morir

    ;call sfx_morir

ret


sfx_chocarse:
    

    ;  ld a,  #2  ;canal para reproducirlo
    ;  call cpct_akp_SFXStop_asm
    ld de, #_cosa
    call cpct_akp_SFXInit_asm

    ld l,  #2 ;numero de instrumento en el sfx
    ld h,  #7  ;volumen 0 - min, 15 - max
    ld e,  #100 ; nota a tocar
    ld d,  #0 ;velocidad 0 - original, 1-255 otra siendo 1 el mas rapido
    ld bc, #0x001A ;pitch, 0 no hay
    ld a,  #0x10  ;canal para reproducirlo
    push ix
     call cpct_akp_SFXPlay_asm
     pop ix  
ret

sfx_morir:
    ld de, #_cosa
    call cpct_akp_SFXInit_asm

    ; ld a,  #2  ;canal para reproducirlo
    ; call cpct_akp_SFXStop_asm

    ld l,  #2 ;numero de instrumento en el sfx
    ld h,  #10  ;volumen 0 - min, 15 - max
    ld e,  #100 ; nota a tocar
    ld d,  #5 ;velocidad 0 - original, 1-255 otra siendo 1 el mas rapido
    ld bc, #0x0060 ;pitch, 0 no hay
    ld a,  #0x10  ;canal para reproducirlo
    push ix
     call cpct_akp_SFXPlay_asm
     pop ix
     ret

sfx_ganar:
    ld de, #_cosa
    call cpct_akp_SFXInit_asm

    ; ld a,  #2  ;canal para reproducirlo
    ; call cpct_akp_SFXStop_asm

    ld l,  #2 ;numero de instrumento en el sfx
    ld h,  #10  ;volumen 0 - min, 15 - max
    ld e,  #100 ; nota a tocar
    ld d,  #0 ;velocidad 0 - original, 1-255 otra siendo 1 el mas rapido
    ld bc, #0 ;pitch, 0 no hay
    ld a,  #0x10  ;canal para reproducirlo
    push ix
     call cpct_akp_SFXPlay_asm
     pop ix
    ;call cpct_akp_SFXPlay_asm
ret