;;-----------------------------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 "input.h.s"
.include "cpctelera.h.s"

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

;;Systems
.include "sys/music.h.s"

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

;;Globals
.include "global/global.h.s"

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


;;====================================================================
;; PUBLIC VARIABLES
;;====================================================================
jump_force::	.db #0xF7

;;====================================================================
;; KEY ACTIONS MAPPING
;;====================================================================
player1_no_shoot_key_actions:
	.dw Key_A, 			move_left
	.dw Joy0_Left,		move_left
	.dw Key_D, 			move_right
	.dw Joy0_Right,		move_right
	.dw Key_W, 			jump
	.dw Joy0_Up,		jump
	.dw Key_V,			shoot
	.dw Joy0_Fire1,		shoot
	.dw #0

player1_shoot_key_actions_right:
	.dw Key_A, 			stop_bullet_velocity
	.dw Joy0_Left, 		stop_bullet_velocity
	.dw Key_D, 			boost_bullet_velocity
	.dw Joy0_Right, 	boost_bullet_velocity
	.dw #0

player1_shoot_key_actions_left:
	.dw Key_A, 			boost_bullet_velocity
	.dw Joy0_Left, 		boost_bullet_velocity
	.dw Key_D, 			stop_bullet_velocity
	.dw Joy0_Right, 	stop_bullet_velocity
	.dw #0

player2_no_shoot_key_actions:
	.dw Key_CursorLeft,  move_left
	.dw Joy1_Left,		 move_left
	.dw Key_CursorRight, move_right
	.dw Joy1_Right,		 move_right
	.dw Key_CursorUp,  	 jump
	.dw Joy1_Up,		 jump
	.dw Key_Return,		 shoot
	.dw Joy1_Fire1,		 shoot
	.dw #0

player2_shoot_key_actions_right:
	.dw Key_CursorLeft, stop_bullet_velocity
	.dw Joy1_Left, 		stop_bullet_velocity
	.dw Key_CursorRight,boost_bullet_velocity
	.dw Joy1_Right, 	boost_bullet_velocity
	.dw #0

player2_shoot_key_actions_left:
	.dw Key_CursorLeft, boost_bullet_velocity
	.dw Joy1_Left, 		boost_bullet_velocity
	.dw Key_CursorRight,stop_bullet_velocity
	.dw Joy1_Right, 	stop_bullet_velocity
	.dw #0

;;====================================================================
;; FUNCTIONS 
;;====================================================================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the entity's memory direction we want to update the input 
;; Objetive: Update the input for one entity.
;;
;; Modifies: de
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_input_update_one_entity:
	ld de, #position_after_input_behaviour
	push de

	;;Jump into the input_behaviour of the entity
	ld l, e_input_bhv_b1(ix)
	ld h, e_input_bhv_b2(ix)

	jp (hl)
	position_after_input_behaviour:
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Update the input for all the entities matching with the signature
;; Modifies: HL, A, C
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
signature_input = (e_cmp_movable | e_cmp_render | e_cmp_input)
sys_input_update::
	ld hl, #sys_input_update_one_entity

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

	call man_entity_forall_matching

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IY: should contain the key actions - 4
;; Objetive: Loop through all the key actions given in IY, calling
;; the method asigned to the action
;;
;; Modifies: IY, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
loop_through_key_actions:
loop_keys:
	INCREMENT_REGISTER_2_BYTES iy, 4

	call sys_input_can_player_jump

	ld  l, 0(iy)
	ld  h, 1(iy)

	;;Check if Key == null == 0
	ld  a, l            ;; A = H | L
	or  h
	ret z               ;;IF A == 0, Key == null, ret

	;;Check if key is pressed
	call cpct_isKeyPressed_asm
	jr z, loop_keys

	push iy

	;;Key is pressed, execute action
	ld hl, #position_after_input_function
	push hl

	ld  l, 2(iy)    ;; / HL = action function pointer
	ld  h, 3(iy)    ;; 
	jp  (hl)
position_after_input_function:
	pop iy
	jr loop_keys

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should containi the memory direction of the player
;; Objetive: Check if the jump key was released to allow the player to jump
;; Modifies: HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sys_input_can_player_jump:

	IS_ENTITY_GIVEN_TYPE_IX e_type_player1
	jr nz, input_player_1
	
	;;input_player_2
	ld hl, #Joy1_Up
	call cpct_isKeyPressed_asm
	ret nz

	ld hl, #Key_CursorUp
	call cpct_isKeyPressed_asm
	ret nz

	ld e_was_jump_pressed(ix), #0
	ret

	input_player_1:
	ld hl, #Joy0_Up
	call cpct_isKeyPressed_asm
	ret nz

	ld hl, #Key_W
	call cpct_isKeyPressed_asm
	ret nz

	ld e_was_jump_pressed(ix), #0

ret


;;===================================================================
;; INPUT BEHAVIOURS
;;===================================================================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Creates the input behaviour given a key_action to loop through the keys
;; Modifies: IY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.macro CREATE_INPUT_BEHAVIOUR _name, _key_action
	_name::
		;;Reset velocity before scan the keyboard
		ld e_vel_x(ix), #0x00

		ld iy, #_key_action - 4
		call loop_through_key_actions
	ret
.endm

CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player1_no_shoot, player1_no_shoot_key_actions
CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player1_shoot_right, player1_shoot_key_actions_right
CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player1_shoot_left, player1_shoot_key_actions_left
CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player2_no_shoot, player2_no_shoot_key_actions
CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player2_shoot_right, player2_shoot_key_actions_right
CREATE_INPUT_BEHAVIOUR sys_input_behaviour_player2_shoot_left, player2_shoot_key_actions_left


;;===================================================================
;; KEY ACTIONS FUNCTIONS
;;===================================================================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Set the velocity of the entity to -1
;; 			 Set the facing_right to false (-1)
;; Modifies: 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

move_left:
	
	ld  e_vel_x(ix), 		#-1
	ld  e_facing_right(ix), #-1 

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: Set the velocity of the entity to 1
;; 			 Set the facing_right to true (1)
;; Modifies: 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
move_right:

	ld  e_vel_x(ix), 		#1
	ld  e_facing_right(ix), #1  

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: In case the entity is allowed to jump,
;; set the values to jump
;; Modifies: ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jump:
	ld a, e_is_grounded(ix)
	IS_EQUALS 1
	ret nz

	ld a, e_was_jump_pressed(ix)
	IS_EQUALS 1
	ret z

	ld e_was_jump_pressed(ix), #1

	;;If it's grounded
	ld a, (#jump_force)
	ld e_vel_y(ix), a
	ld e_is_grounded(ix), #0
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  -
;; Objetive: In case the entity is allowed to shoot,
;; say to the game manager "Hey! create a bullet! from entity (player) values"
;; Modifies: -
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
shoot:

	ld de,  #bullet_tmpl
	call man_game_create_template_bullet
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the memory direction of the player
;; Objetive: In case the entity is a bullet, increase its velocity,
;; (3 is the highest velocity allowed)
;; Modifies: a 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
boost_bullet_velocity:
	ld  c, e_bullet_ref_b1(ix)
	ld 	b, e_bullet_ref_b2(ix)

	ld  a, b		;;Is the bullet reference null
	cp #00
	ret z

	ld  a, (bc)		;;Is the type of the bullet invalid
	cp #e_type_invalid
	ret z

	;;BC contains the memory direction for the bullet ref of the player

	;;Copying BC into IY to use the index structure, now IY contains the memory direction of the bullet
	ld__iy_bc

	ld 	a, e_facing_right(iy)
	IS_EQUALS -1
	jr z, bullet_facing_left_increase

	;;bullet_facing_right
	ld e_vel_x(iy), #2
	ret

	bullet_facing_left_increase:
	ld e_vel_x(iy), #-2

ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the memory direction of the player
;; Objetive: In case the entity is a bullet, decrease its velocity,
;; (0 is the lowest velocity allowed)
;; Modifies: a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
stop_bullet_velocity:
	ld  c, e_bullet_ref_b1(ix)
	ld 	b, e_bullet_ref_b2(ix)

	ld  a, b		;;Is the bullet reference null
	cp #00
	ret z

	ld  a, (bc)		;;Is the type of the bullet invalid
	cp #e_type_invalid
	ret z

	;;BC contains the memory direction for the bullet ref of the player

	;;Copying BC into IY to use the index structure, now IY contains the memory direction of the bullet
	ld__iy_bc

	ld e_vel_x(iy), #0
ret