2008-08-27 19:50:33 +00:00
# include <engine/e_client_interface.h>
2008-08-27 15:48:50 +00:00
# include <base/math.hpp>
# include <game/collision.hpp>
# include <game/client/gameclient.hpp>
# include <game/client/component.hpp>
2008-08-30 22:38:56 +00:00
# include <game/client/components/chat.hpp>
# include <game/client/components/menus.hpp>
2008-08-27 15:48:50 +00:00
# include "controls.hpp"
CONTROLS : : CONTROLS ( )
{
}
static void con_key_input_state ( void * result , void * user_data )
{
( ( int * ) user_data ) [ 0 ] = console_arg_int ( result , 0 ) ;
}
static void con_key_input_counter ( void * result , void * user_data )
{
int * v = ( int * ) user_data ;
if ( ( ( * v ) & 1 ) ! = console_arg_int ( result , 0 ) )
( * v ) + + ;
* v & = INPUT_STATE_MASK ;
}
2008-08-27 20:04:07 +00:00
struct INPUTSET
{
CONTROLS * controls ;
int * variable ;
int value ;
} ;
static void con_key_input_set ( void * result , void * user_data )
2008-08-27 15:48:50 +00:00
{
2008-08-27 20:04:07 +00:00
INPUTSET * set = ( INPUTSET * ) user_data ;
2008-08-27 15:48:50 +00:00
if ( console_arg_int ( result , 0 ) )
2008-08-27 20:04:07 +00:00
* set - > variable = set - > value ;
2008-08-27 15:48:50 +00:00
}
static void con_key_input_nextprev_weapon ( void * result , void * user_data )
{
2008-08-27 20:04:07 +00:00
INPUTSET * set = ( INPUTSET * ) user_data ;
con_key_input_counter ( result , set - > variable ) ;
set - > controls - > input_data . wanted_weapon = 0 ;
}
2008-08-27 15:48:50 +00:00
2008-09-04 21:36:44 +00:00
void CONTROLS : : on_console_init ( )
2008-08-27 15:48:50 +00:00
{
// game commands
2009-01-24 14:10:26 +00:00
MACRO_REGISTER_COMMAND ( " +left " , " " , CFGFLAG_CLIENT , con_key_input_state , & input_direction_left , " Move left " ) ;
MACRO_REGISTER_COMMAND ( " +right " , " " , CFGFLAG_CLIENT , con_key_input_state , & input_direction_right , " Move right " ) ;
MACRO_REGISTER_COMMAND ( " +jump " , " " , CFGFLAG_CLIENT , con_key_input_state , & input_data . jump , " Jump " ) ;
MACRO_REGISTER_COMMAND ( " +hook " , " " , CFGFLAG_CLIENT , con_key_input_state , & input_data . hook , " Hook " ) ;
MACRO_REGISTER_COMMAND ( " +fire " , " " , CFGFLAG_CLIENT , con_key_input_counter , & input_data . fire , " Fire " ) ;
2008-08-27 15:48:50 +00:00
2009-01-24 14:10:26 +00:00
{ static INPUTSET set = { this , & input_data . wanted_weapon , 1 } ; MACRO_REGISTER_COMMAND ( " +weapon1 " , " " , CFGFLAG_CLIENT , con_key_input_set , ( void * ) & set , " Switch to hammer " ) ; }
{ static INPUTSET set = { this , & input_data . wanted_weapon , 2 } ; MACRO_REGISTER_COMMAND ( " +weapon2 " , " " , CFGFLAG_CLIENT , con_key_input_set , ( void * ) & set , " Switch to gun " ) ; }
{ static INPUTSET set = { this , & input_data . wanted_weapon , 3 } ; MACRO_REGISTER_COMMAND ( " +weapon3 " , " " , CFGFLAG_CLIENT , con_key_input_set , ( void * ) & set , " Switch to shotgun " ) ; }
{ static INPUTSET set = { this , & input_data . wanted_weapon , 4 } ; MACRO_REGISTER_COMMAND ( " +weapon4 " , " " , CFGFLAG_CLIENT , con_key_input_set , ( void * ) & set , " Switch to grenade " ) ; }
{ static INPUTSET set = { this , & input_data . wanted_weapon , 5 } ; MACRO_REGISTER_COMMAND ( " +weapon5 " , " " , CFGFLAG_CLIENT , con_key_input_set , ( void * ) & set , " Switch to rifle " ) ; }
2008-08-27 20:04:07 +00:00
2009-01-24 14:10:26 +00:00
{ static INPUTSET set = { this , & input_data . next_weapon , 0 } ; MACRO_REGISTER_COMMAND ( " +nextweapon " , " " , CFGFLAG_CLIENT , con_key_input_nextprev_weapon , ( void * ) & set , " Switch to next weapon " ) ; }
{ static INPUTSET set = { this , & input_data . prev_weapon , 0 } ; MACRO_REGISTER_COMMAND ( " +prevweapon " , " " , CFGFLAG_CLIENT , con_key_input_nextprev_weapon , ( void * ) & set , " Switch to previous weapon " ) ; }
2008-08-27 15:48:50 +00:00
}
2008-08-31 21:50:14 +00:00
void CONTROLS : : on_message ( int msg , void * rawmsg )
{
if ( msg = = NETMSGTYPE_SV_WEAPONPICKUP )
{
NETMSG_SV_WEAPONPICKUP * msg = ( NETMSG_SV_WEAPONPICKUP * ) rawmsg ;
if ( config . cl_autoswitch_weapons )
input_data . wanted_weapon = msg - > weapon + 1 ;
}
}
2008-08-27 15:48:50 +00:00
int CONTROLS : : snapinput ( int * data )
{
static NETOBJ_PLAYER_INPUT last_data = { 0 } ;
static int64 last_send_time = 0 ;
2009-01-10 13:34:01 +00:00
bool send = false ;
2008-08-27 15:48:50 +00:00
// update player state
2008-08-30 22:38:56 +00:00
if ( gameclient . chat - > is_active ( ) )
2008-08-27 15:48:50 +00:00
input_data . player_state = PLAYERSTATE_CHATTING ;
2008-08-30 22:38:56 +00:00
else if ( gameclient . menus - > is_active ( ) )
2008-08-27 15:48:50 +00:00
input_data . player_state = PLAYERSTATE_IN_MENU ;
else
2008-08-30 22:38:56 +00:00
input_data . player_state = PLAYERSTATE_PLAYING ;
2009-01-10 13:34:01 +00:00
if ( last_data . player_state ! = input_data . player_state )
send = true ;
2008-08-27 15:48:50 +00:00
last_data . player_state = input_data . player_state ;
// we freeze the input if chat or menu is activated
2008-08-30 22:38:56 +00:00
if ( input_data . player_state ! = PLAYERSTATE_PLAYING )
2008-08-27 15:48:50 +00:00
{
last_data . direction = 0 ;
last_data . hook = 0 ;
last_data . jump = 0 ;
input_data = last_data ;
2008-10-20 22:53:42 +00:00
input_direction_left = 0 ;
input_direction_right = 0 ;
2008-08-27 15:48:50 +00:00
mem_copy ( data , & input_data , sizeof ( input_data ) ) ;
2009-01-10 13:34:01 +00:00
// send once a second just to be sure
if ( time_get ( ) > last_send_time + time_freq ( ) )
send = true ;
2008-08-30 22:38:56 +00:00
}
2009-01-10 13:34:01 +00:00
else
2008-08-27 15:48:50 +00:00
{
2009-01-10 13:34:01 +00:00
input_data . target_x = ( int ) mouse_pos . x ;
input_data . target_y = ( int ) mouse_pos . y ;
if ( ! input_data . target_x & & ! input_data . target_y )
input_data . target_y = 1 ;
// set direction
input_data . direction = 0 ;
if ( input_direction_left & & ! input_direction_right )
input_data . direction = - 1 ;
if ( ! input_direction_left & & input_direction_right )
input_data . direction = 1 ;
// stress testing
if ( config . dbg_stress )
{
float t = client_localtime ( ) ;
mem_zero ( & input_data , sizeof ( input_data ) ) ;
input_data . direction = ( ( int ) t / 2 ) & 1 ;
input_data . jump = ( ( int ) t ) ;
input_data . fire = ( ( int ) ( t * 10 ) ) ;
input_data . hook = ( ( int ) ( t * 2 ) ) & 1 ;
input_data . wanted_weapon = ( ( int ) t ) % NUM_WEAPONS ;
input_data . target_x = ( int ) ( sinf ( t * 3 ) * 100.0f ) ;
input_data . target_y = ( int ) ( cosf ( t * 3 ) * 100.0f ) ;
}
// check if we need to send input
if ( input_data . direction ! = last_data . direction ) send = true ;
else if ( input_data . jump ! = last_data . jump ) send = true ;
else if ( input_data . fire ! = last_data . fire ) send = true ;
else if ( input_data . hook ! = last_data . hook ) send = true ;
else if ( input_data . player_state ! = last_data . player_state ) send = true ;
else if ( input_data . wanted_weapon ! = last_data . wanted_weapon ) send = true ;
else if ( input_data . next_weapon ! = last_data . next_weapon ) send = true ;
else if ( input_data . prev_weapon ! = last_data . prev_weapon ) send = true ;
// send at at least 10hz
2009-01-21 00:05:07 +00:00
if ( time_get ( ) > last_send_time + time_freq ( ) / 25 )
2009-01-10 13:34:01 +00:00
send = true ;
2008-08-27 15:48:50 +00:00
}
2009-01-10 13:34:01 +00:00
// copy and return size
2008-08-27 15:48:50 +00:00
last_data = input_data ;
2009-01-10 13:34:01 +00:00
2008-08-27 15:48:50 +00:00
if ( ! send )
return 0 ;
last_send_time = time_get ( ) ;
mem_copy ( data , & input_data , sizeof ( input_data ) ) ;
return sizeof ( input_data ) ;
}
2008-09-13 05:57:11 +00:00
void CONTROLS : : on_render ( )
{
// update target pos
2009-01-17 17:06:24 +00:00
if ( ! ( gameclient . snap . gameobj & & gameclient . snap . gameobj - > paused | | gameclient . snap . spectate ) )
2008-11-16 15:39:22 +00:00
target_pos = gameclient . local_character_pos + mouse_pos ;
2008-09-13 05:57:11 +00:00
}
2008-08-27 15:48:50 +00:00
bool CONTROLS : : on_mousemove ( float x , float y )
{
2008-11-16 15:39:22 +00:00
if ( gameclient . snap . gameobj & & gameclient . snap . gameobj - > paused )
return false ;
2008-08-27 15:48:50 +00:00
mouse_pos + = vec2 ( x , y ) ; // TODO: ugly
//
float camera_max_distance = 200.0f ;
float follow_factor = config . cl_mouse_followfactor / 100.0f ;
float deadzone = config . cl_mouse_deadzone ;
float mouse_max = min ( camera_max_distance / follow_factor + deadzone , ( float ) config . cl_mouse_max_distance ) ;
//vec2 camera_offset(0, 0);
2008-09-09 15:50:41 +00:00
if ( gameclient . snap . spectate )
2008-08-27 15:48:50 +00:00
{
if ( mouse_pos . x < 200.0f ) mouse_pos . x = 200.0f ;
if ( mouse_pos . y < 200.0f ) mouse_pos . y = 200.0f ;
if ( mouse_pos . x > col_width ( ) * 32 - 200.0f ) mouse_pos . x = col_width ( ) * 32 - 200.0f ;
if ( mouse_pos . y > col_height ( ) * 32 - 200.0f ) mouse_pos . y = col_height ( ) * 32 - 200.0f ;
target_pos = mouse_pos ;
}
else
{
float l = length ( mouse_pos ) ;
if ( l > mouse_max )
{
mouse_pos = normalize ( mouse_pos ) * mouse_max ;
l = mouse_max ;
}
//float offset_amount = max(l-deadzone, 0.0f) * follow_factor;
//if(l > 0.0001f) // make sure that this isn't 0
//camera_offset = normalize(mouse_pos)*offset_amount;
}
return true ;
}