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)
|
|
|
|
{
|
|
|
|
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];
|
|
|
|
str_format(buf, sizeof(buf), "%s team has captured the flag!", fi^1 ? "Blue" : "Red");
|
|
|
|
game.send_broadcast(buf, -1);
|
|
|
|
|
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++)
|
|
|
|
{
|
2008-11-04 16:35:48 +00:00
|
|
|
if(!close_characters[i]->alive || close_characters[i]->player->team == -1)
|
|
|
|
continue;
|
|
|
|
|
2008-11-04 07:20:24 +00:00
|
|
|
int collision = col_intersect_line(f->pos, close_characters[i]->pos, NULL);
|
|
|
|
if(!collision && 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-04 07:20:24 +00:00
|
|
|
else if(!collision)
|
2007-09-25 23:03:15 +00:00
|
|
|
{
|
|
|
|
// take the flag
|
2007-12-11 21:08:21 +00:00
|
|
|
if(f->at_stand)
|
|
|
|
teamscore[fi^1]++;
|
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;
|
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);
|
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));
|
2007-09-25 23:03:15 +00:00
|
|
|
flag->x = (int)pos.x;
|
|
|
|
flag->y = (int)pos.y;
|
|
|
|
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
|
|
|
}
|