2007-11-25 19:42:40 +00:00
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
2008-01-19 10:57:25 +00:00
# include <engine/e_server_interface.h>
2008-08-17 08:52:24 +00:00
# include <game/mapitems.hpp>
2008-08-14 18:25:44 +00:00
# include <game/server/entities/character.hpp>
# include <game/server/player.hpp>
# include <game/server/gamecontext.hpp>
# include "ctf.hpp"
2007-09-25 23:03:15 +00:00
2008-06-12 10:51:48 +00:00
GAMECONTROLLER_CTF : : GAMECONTROLLER_CTF ( )
2007-09-25 23:03:15 +00:00
{
2008-03-29 15:21:16 +00:00
flags [ 0 ] = 0 ;
flags [ 1 ] = 0 ;
2008-08-31 21:50:14 +00:00
gametype = " CTF " ;
2008-08-31 14:37:35 +00:00
game_flags = GAMEFLAG_TEAMS | GAMEFLAG_FLAGS ;
2007-09-25 23:03:15 +00:00
}
2008-06-12 10:51:48 +00:00
bool GAMECONTROLLER_CTF : : on_entity ( int index , vec2 pos )
2008-01-13 11:43:43 +00:00
{
2008-06-12 10:51:48 +00:00
if ( GAMECONTROLLER : : on_entity ( index , pos ) )
2008-01-13 11:43:43 +00:00
return true ;
int team = - 1 ;
if ( index = = ENTITY_FLAGSTAND_RED ) team = 0 ;
if ( index = = ENTITY_FLAGSTAND_BLUE ) team = 1 ;
if ( team = = - 1 )
return false ;
2008-06-12 10:51:48 +00:00
FLAG * f = new FLAG ( team ) ;
2008-01-13 11:43:43 +00:00
f - > stand_pos = pos ;
f - > pos = pos ;
flags [ team ] = f ;
return true ;
}
2008-07-06 11:21:21 +00:00
int GAMECONTROLLER_CTF : : on_character_death ( class CHARACTER * victim , class PLAYER * killer , int weaponid )
2007-09-25 23:03:15 +00:00
{
2008-07-06 11:21:21 +00:00
GAMECONTROLLER : : on_character_death ( victim , killer , weaponid ) ;
2007-11-18 23:29:34 +00:00
int had_flag = 0 ;
2007-09-25 23:03:15 +00:00
// drop flags
for ( int fi = 0 ; fi < 2 ; fi + + )
{
2008-06-12 10:51:48 +00:00
FLAG * f = flags [ fi ] ;
2008-10-05 15:40:36 +00:00
if ( f & & killer & & f - > carrying_character = = killer - > get_character ( ) )
2007-11-18 23:29:34 +00:00
had_flag | = 2 ;
2008-07-06 11:21:21 +00:00
if ( f & & f - > carrying_character = = victim )
2007-11-18 23:29:34 +00:00
{
2008-07-06 11:21:21 +00:00
game . create_sound_global ( SOUND_CTF_DROP ) ;
2007-11-26 19:32:02 +00:00
f - > drop_tick = server_tick ( ) ;
2008-07-06 11:21:21 +00:00
f - > carrying_character = 0 ;
2007-12-13 22:56:33 +00:00
f - > vel = vec2 ( 0 , 0 ) ;
2007-12-11 21:19:52 +00:00
2007-12-13 22:17:36 +00:00
if ( killer & & killer - > team ! = victim - > team )
2007-12-11 21:19:52 +00:00
killer - > score + + ;
2007-11-18 23:29:34 +00:00
had_flag | = 1 ;
}
2007-09-25 23:03:15 +00:00
}
2007-11-18 23:29:34 +00:00
return had_flag ;
2007-09-25 23:03:15 +00:00
}
2008-06-12 10:51:48 +00:00
void GAMECONTROLLER_CTF : : tick ( )
2007-09-25 23:03:15 +00:00
{
2008-06-12 10:51:48 +00:00
GAMECONTROLLER : : tick ( ) ;
2007-11-26 20:47:49 +00:00
2008-01-17 23:09:49 +00:00
do_team_score_wincheck ( ) ;
2007-09-25 23:03:15 +00:00
for ( int fi = 0 ; fi < 2 ; fi + + )
{
2008-06-12 10:51:48 +00:00
FLAG * f = flags [ fi ] ;
2007-09-25 23:03:15 +00:00
2007-12-09 09:47:05 +00:00
if ( ! f )
continue ;
2008-10-18 20:37:41 +00:00
// flag hits death-tile, reset it
if ( col_get ( ( int ) f - > pos . x , ( int ) f - > pos . y ) & COLFLAG_DEATH )
{
2009-01-21 00:00:04 +00:00
game . create_sound_global ( SOUND_CTF_RETURN ) ;
2008-10-18 20:37:41 +00:00
f - > reset ( ) ;
continue ;
}
2007-09-25 23:03:15 +00:00
//
2008-07-06 11:21:21 +00:00
if ( f - > carrying_character )
2007-09-25 23:03:15 +00:00
{
// update flag position
2008-07-06 11:21:21 +00:00
f - > pos = f - > carrying_character - > pos ;
2007-09-25 23:03:15 +00:00
2008-03-29 15:21:16 +00:00
if ( flags [ fi ^ 1 ] & & flags [ fi ^ 1 ] - > at_stand )
2007-09-25 23:03:15 +00:00
{
2007-12-19 21:03:29 +00:00
if ( distance ( f - > pos , flags [ fi ^ 1 ] - > pos ) < 32 )
2007-09-25 23:03:15 +00:00
{
// CAPTURE! \o/
2007-12-11 21:08:21 +00:00
teamscore [ fi ^ 1 ] + = 100 ;
2008-07-06 11:21:21 +00:00
f - > carrying_character - > player - > score + = 5 ;
2008-01-30 13:15:58 +00:00
2008-07-06 11:21:21 +00:00
dbg_msg ( " game " , " flag_capture player='%d:%s' " ,
f - > carrying_character - > player - > client_id ,
server_clientname ( f - > carrying_character - > player - > client_id ) ) ;
2008-01-30 13:15:58 +00:00
2008-09-13 19:53:13 +00:00
char buf [ 512 ] ;
2008-11-08 15:17:59 +00:00
float capture_time = ( server_tick ( ) - f - > grab_tick ) / ( float ) server_tickspeed ( ) ;
if ( capture_time < = 60 )
{
str_format ( buf , sizeof ( buf ) , " the %s flag was captured by %s (%d.%s%d seconds) " , fi ? " blue " : " red " , server_clientname ( f - > carrying_character - > player - > client_id ) , ( int ) capture_time % 60 , ( ( int ) ( capture_time * 100 ) % 100 ) < 10 ? " 0 " : " " , ( int ) ( capture_time * 100 ) % 100 ) ;
}
else
{
str_format ( buf , sizeof ( buf ) , " the %s flag was captured by %s " , fi ? " blue " : " red " , server_clientname ( f - > carrying_character - > player - > client_id ) ) ;
}
game . send_chat ( - 1 , - 2 , buf ) ;
2007-09-25 23:03:15 +00:00
for ( int i = 0 ; i < 2 ; i + + )
flags [ i ] - > reset ( ) ;
2007-11-27 19:32:35 +00:00
2008-07-06 11:21:21 +00:00
game . create_sound_global ( SOUND_CTF_CAPTURE ) ;
2007-09-25 23:03:15 +00:00
}
}
}
else
{
2008-07-06 11:21:21 +00:00
CHARACTER * close_characters [ MAX_CLIENTS ] ;
int num = game . world . find_entities ( f - > pos , 32.0f , ( ENTITY * * ) close_characters , MAX_CLIENTS , NETOBJTYPE_CHARACTER ) ;
2007-09-25 23:03:15 +00:00
for ( int i = 0 ; i < num ; i + + )
{
2009-01-11 10:26:17 +00:00
if ( ! close_characters [ i ] - > alive | | close_characters [ i ] - > player - > team = = - 1 | | col_intersect_line ( f - > pos , close_characters [ i ] - > pos , NULL , NULL ) )
2008-11-04 16:35:48 +00:00
continue ;
2008-11-08 09:02:35 +00:00
if ( close_characters [ i ] - > team = = f - > team )
2007-09-25 23:03:15 +00:00
{
// return the flag
2007-09-26 07:31:14 +00:00
if ( ! f - > at_stand )
2007-11-27 19:32:35 +00:00
{
2008-07-06 11:21:21 +00:00
CHARACTER * chr = close_characters [ i ] ;
chr - > player - > score + = 1 ;
2008-01-30 13:15:58 +00:00
2008-07-06 11:21:21 +00:00
dbg_msg ( " game " , " flag_return player='%d:%s' " ,
chr - > player - > client_id ,
server_clientname ( chr - > player - > client_id ) ) ;
2008-01-30 13:15:58 +00:00
2008-07-06 11:21:21 +00:00
game . create_sound_global ( SOUND_CTF_RETURN ) ;
2007-09-26 07:31:14 +00:00
f - > reset ( ) ;
2007-11-27 19:32:35 +00:00
}
2007-09-25 23:03:15 +00:00
}
2008-11-08 09:02:35 +00:00
else
2007-09-25 23:03:15 +00:00
{
// take the flag
2007-12-11 21:08:21 +00:00
if ( f - > at_stand )
2008-11-08 15:17:59 +00:00
{
2007-12-11 21:08:21 +00:00
teamscore [ fi ^ 1 ] + + ;
2008-11-08 15:17:59 +00:00
f - > grab_tick = server_tick ( ) ;
}
2007-09-25 23:03:15 +00:00
f - > at_stand = 0 ;
2008-07-06 11:21:21 +00:00
f - > carrying_character = close_characters [ i ] ;
f - > carrying_character - > player - > score + = 1 ;
2008-01-30 13:15:58 +00:00
2008-07-06 11:21:21 +00:00
dbg_msg ( " game " , " flag_grab player='%d:%s' " ,
f - > carrying_character - > player - > client_id ,
server_clientname ( f - > carrying_character - > player - > client_id ) ) ;
2007-12-15 15:35:50 +00:00
for ( int c = 0 ; c < MAX_CLIENTS ; c + + )
{
2008-09-23 18:08:19 +00:00
if ( ! game . players [ c ] )
2007-12-15 15:35:50 +00:00
continue ;
2008-09-23 18:08:19 +00:00
if ( game . players [ c ] - > team = = fi )
game . create_sound_global ( SOUND_CTF_GRAB_EN , game . players [ c ] - > client_id ) ;
2007-12-15 15:35:50 +00:00
else
2008-09-23 18:08:19 +00:00
game . create_sound_global ( SOUND_CTF_GRAB_PL , game . players [ c ] - > client_id ) ;
2007-12-15 15:35:50 +00:00
}
2007-09-25 23:03:15 +00:00
break ;
}
}
2008-07-06 11:21:21 +00:00
if ( ! f - > carrying_character & & ! f - > at_stand )
2007-09-25 23:03:15 +00:00
{
2008-01-19 10:57:25 +00:00
if ( server_tick ( ) > f - > drop_tick + server_tickspeed ( ) * 30 )
2007-11-27 19:32:35 +00:00
{
2008-07-06 11:21:21 +00:00
game . create_sound_global ( SOUND_CTF_RETURN ) ;
2007-11-26 19:32:02 +00:00
f - > reset ( ) ;
2007-11-27 19:32:35 +00:00
}
2007-11-26 19:32:02 +00:00
else
{
2008-07-06 11:21:21 +00:00
f - > vel . y + = game . world . core . tuning . gravity ;
2007-11-26 19:32:02 +00:00
move_box ( & f - > pos , & f - > vel , vec2 ( f - > phys_size , f - > phys_size ) , 0.5f ) ;
}
2007-09-25 23:03:15 +00:00
}
}
}
}
2007-10-28 11:30:25 +00:00
// Flag
2008-06-12 10:51:48 +00:00
FLAG : : FLAG ( int _team )
: ENTITY ( NETOBJTYPE_FLAG )
2007-09-25 23:03:15 +00:00
{
team = _team ;
proximity_radius = phys_size ;
2008-07-06 11:21:21 +00:00
carrying_character = 0x0 ;
2008-11-08 15:17:59 +00:00
grab_tick = 0 ;
2007-09-25 23:03:15 +00:00
reset ( ) ;
// TODO: should this be done here?
2008-07-06 11:21:21 +00:00
game . world . insert_entity ( this ) ;
2007-09-25 23:03:15 +00:00
}
2008-06-12 10:51:48 +00:00
void FLAG : : reset ( )
2007-09-25 23:03:15 +00:00
{
2008-10-05 15:40:36 +00:00
carrying_character = 0x0 ;
2007-09-25 23:03:15 +00:00
at_stand = 1 ;
pos = stand_pos ;
2007-12-13 22:56:33 +00:00
vel = vec2 ( 0 , 0 ) ;
2008-11-08 15:17:59 +00:00
grab_tick = 0 ;
2007-09-25 23:03:15 +00:00
}
2008-06-12 10:51:48 +00:00
void FLAG : : snap ( int snapping_client )
2007-09-25 23:03:15 +00:00
{
2008-02-24 16:03:58 +00:00
NETOBJ_FLAG * flag = ( NETOBJ_FLAG * ) snap_new_item ( NETOBJTYPE_FLAG , team , sizeof ( NETOBJ_FLAG ) ) ;
2009-05-31 09:44:20 +00:00
flag - > x = ( int ) pos . x ;
flag - > y = ( int ) pos . y ;
2007-09-25 23:03:15 +00:00
flag - > team = team ;
2007-11-18 22:20:35 +00:00
flag - > carried_by = - 1 ;
2007-09-25 23:03:15 +00:00
2007-11-18 23:29:34 +00:00
if ( at_stand )
flag - > carried_by = - 2 ;
2008-11-04 13:19:05 +00:00
else if ( carrying_character & & carrying_character - > player )
2008-07-06 11:21:21 +00:00
flag - > carried_by = carrying_character - > player - > client_id ;
2007-09-25 23:03:15 +00:00
}