;;-----------------------------LICENSE NOTICE------------------------------------
;;  This file is part of The Last Fungus: An Amstrad CPC Game 
;;  Copyright (C) 2021 Miguel Perez Tarruella / Antonio Jose Fernandez Belliure / 
;;                     David Martinez Garcia / Ocacho Games (@OcachoGames)
;;
;;  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/>.
;;------------------------------------------------------------------------------

;;====================================================================
;; GLOBL INCLUDES
;;====================================================================
.include "collision.h.s"
.include "cpctelera.h.s"

;;Managers
.include "man/entity.h.s"
.include "man/game.h.s"

;;Macros
.include "macros/math.h.s"

;;Resources
.include "resources/bullet_animations.h.s"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the entity's memory direction we want to know 
;;        if its colliding with something
;; Objetive: Update the collision for one entity.
;;
;; Modifies: A, C, D, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_collision_update_one_entity:
	ld hl, #position_after_behaviour
	push hl

	ld l, e_collision_bhv_b1(ix)
	ld h, e_collision_bhv_b2(ix)

	jp (hl)

	position_after_behaviour:
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the entity's memory direction we want to know 
;;        if its colliding with something
;;	- IY: should contain the entity which we are checking the collider
;; Objetive: Check if an entity is colliding with another by checking
;;			 the x and y positions of both entities
;;
;; Modifies: A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_collision_check_x_check_y_bullet:
	;;Checking the x axis
	ld          a, e_pos_x(ix)
	add         a, e_width(ix)
	sub e_pos_x(iy)
	ret c

	ld          a, e_pos_x(iy)
	add         a, e_width(iy)
	sub e_pos_x(ix)
	ret c

	;;There is collision on the x axis, let's check if there is collision on y

	;;Checking the y axis

	ld          a, e_pos_y(ix)
	add         a, e_height(ix)
	sub e_pos_y(iy)
	ret c

	ld          a, e_pos_y(iy)
	add         a, e_height(iy)
	sub e_pos_y(ix)
	ret c
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the entity's memory direction we want to know 
;;        if its colliding with something
;;	- IY: should contain the entity which we are checking the collider
;; Objetive: Check if an entity is colliding with another by checking
;;			 the x and y positions of both entities
;;
;; Modifies: A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_collision_check_x_check_y_player:
	;;Checking the x axis
	ld          a, e_pos_x(ix)
	add         a, e_width(ix)
	sub e_pos_x(iy)
	ret c

	ld          a, e_pos_x(iy)
	add         a, e_width(iy)
	sub e_pos_x(ix)
	ret c

	;;There is collision on the x axis, let's check if there is collision on y

	;;Checking the y axis

	ld          a, e_pos_y(ix)
	add         a, e_height(ix)
	sub e_pos_y(iy)
	ret c

	ld			a, e_pos_y(ix)
	add			a, e_height(ix)
	ld			b, a
	ld          a, e_pos_y(iy)
	add         a, e_height(iy)
	sub b
	ret c
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Contains the behaviour that should make a player if 
;;           has collided with something
;; Modifies: A, B, D, IY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_collision_player_behaviour:
	m_first_platform = sizeof_e * 4

	;;First we check if the player is moving, if not we don't calculate collision against platforms
	ld a, e_vel_y(ix)
	IS_EQUALS 0
	jp nz, vel_is_not_zero_player_collision

	ld a, e_vel_x(ix)
	IS_EQUALS 0
	jp nz, vel_is_not_zero_player_collision

	ret

	vel_is_not_zero_player_collision:
	;;IY contains the memory direction of the first player, and IX of one bullet
	ld iy, #m_entities

	INCREMENT_REGISTER_2_BYTES iy, m_first_platform

	ld d, #0x04
	loop_collision_player: ;;Looping with the bullets against the players and the other bullet

		IS_ENTITY_INVALID iy
		jr z, no_collision_player

		call sys_collision_check_x_check_y_player
		jr c, no_collision_player

		;;Here we set the is_grounded variable to true
		call man_entity_set_is_grounded

		ld a, e_pos_y(iy)
		ld b, e_height(ix)
		sub b
		ld e_last_position_y(ix), a
		ld e_pos_y(ix), a

		ret

	no_collision_player:
		;;If there is no collision we check the next entity
		INCREMENT_REGISTER_2_BYTES iy, sizeof_e

		dec d
		jp nz, loop_collision_player
	
	;;Here we check if the player is in a y position lower than floor and if so reposition it, if not he is falling from a platform
	ld a, e_pos_y(ix)
	ld b, e_height(ix)
	add b

	IS_HIGHER 190
	jr c, not_collided_with_platform

	ld a, #190
	ld b, e_height(ix)
	sub b
	ld e_last_position_y(ix), a
	ld e_pos_y(ix), a
	call man_entity_set_is_grounded

	ret

	not_collided_with_platform:
		call man_entity_set_is_in_air
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Contains the behaviour that should make a bullet if 
;;           has collided with something
;; Modifies: A, B, D, IY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_collision_bullet_behaviour:

	ld iy, #m_entities
	
	ld a, e_vel_x(ix)
	IS_EQUALS 0
	jp nz, check_all_entities

	ld d, #0x04
	jp loop_collision_bullet
	
	check_all_entities:
	ld d, #0x08
	loop_collision_bullet: ;;Looping with the bullets against the players and the other bullet

		IS_ENTITY_INVALID iy
		jr z, no_collision_bullet

		;;Check if ix is the same memory direction as ours  
		ld a, e_bullet_ref_b1(ix)
		ld b, e_bullet_ref_b1(iy)
		IS_EQUALS_REGISTER b
		jr nz, different_entity_bullet

		ld a, e_bullet_ref_b2(ix)
		ld b, e_bullet_ref_b2(iy)
		IS_EQUALS_REGISTER b
		jr z, no_collision_bullet

		different_entity_bullet:
			call sys_collision_check_x_check_y_bullet
			jr c, no_collision_bullet

			;;Check if the collision of the bullet is against a player or the other bullet
			IS_ENTITY_GIVEN_TYPE_IY e_type_bullet
			jr nz, collision_against_a_bullet

			IS_ENTITY_GIVEN_TYPE_IY e_type_platform
			jr nz, collision_against_a_platform

			;;collision_against_a_player:
			;;There is collision, delete both of the entities and call man_game_pre_finish
			call man_game_pre_finish_game
			ret

		collision_against_a_bullet: 
			ld hl, #bullet_explosion
			ld e_anim_b1(ix), l
			ld e_anim_b2(ix), h
			call man_entity_set_type_to_dying_animation
			push ix
			
			;;Destroy the second bullet
			ld__ix_iy
			ld hl, #bullet_explosion
			ld e_anim_b1(ix), l
			ld e_anim_b2(ix), h
			call man_entity_set_type_to_dying_animation
			
			pop ix
	
			ret
		
		collision_against_a_platform:
			;;Set the bullet to be destroyed
			ld hl, #bullet_explosion
			ld e_anim_b1(ix), l
			ld e_anim_b2(ix), h
			call man_entity_set_type_to_dying_animation

			ret

	no_collision_bullet:
		INCREMENT_REGISTER_2_BYTES iy, sizeof_e

		dec d
		jp nz, loop_collision_bullet

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Update the collision for all the entities matching with the signature
;; Modifies: A, C, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
signature_collision = (e_cmp_collider)
sys_collision_update::
	ld hl, #sys_collision_update_one_entity

	;;C will contain the signature for the man_entity_forall_matching
	ld  a, #signature_collision
	ld c, a

	call man_entity_forall_matching
ret
