bool BUILDING::increase_health(int amount) { if(health >= maxhealth) return false; int gain = 2; if(health_tick+25 > server_tick()) gain = 1; else health_tick = server_tick(); decon = false; health = clamp(health+gain, 0, maxhealth); if(health == maxhealth && !alive) { alive = true; if(type == B_REACTOR) { game.create_sound(pos, SOUND_REACTOR); } ((GAMECONTROLLER_NODES*)game.controller)->do_team_sound(SOUND_CTF_GRAB_PL, team); if(type == B_REACTOR) { game.create_sound(pos, SOUND_REACTOR); } } return true; }
void GUN::tick() { if(server_tick() > eval_tick+DELAY) { eval_tick=server_tick(); fire(); } }
void CHARACTER::snap(int snapping_client) { if(networkclipped(snapping_client) || (snapping_client != player->client_id && player->invisible==true)) return; NETOBJ_CHARACTER *character = (NETOBJ_CHARACTER *)snap_new_item(NETOBJTYPE_CHARACTER, player->client_id, sizeof(NETOBJ_CHARACTER)); // write down the core if(game.world.paused) { // no dead reckoning when paused because the client doesn't know // how far to perform the reckoning character->tick = 0; core.write(character); } else { character->tick = reckoning_tick; sendcore.write(character); } if(do_splash) character->jumped = 3; // set emote if (emote_stop < server_tick()) { emote_type = EMOTE_NORMAL; emote_stop = -1; } character->emote = emote_type; character->ammocount = 0; character->health = 0; character->armor = 0; character->weapon = active_weapon; character->attacktick = attack_tick; character->direction = input.direction; if(player->client_id == snapping_client) { character->health = health; character->armor = armor; if(weapons[active_weapon].ammo > 0) character->ammocount = weapons[active_weapon].ammo; } if (character->emote == EMOTE_NORMAL) { if(250 - ((server_tick() - last_action)%(250)) < 5) character->emote = EMOTE_BLINK; } character->player_state = player_state; }
void PROJECTILE::tick() { float pt = (server_tick()-start_tick-1)/(float)server_tickspeed(); float ct = (server_tick()-start_tick)/(float)server_tickspeed(); vec2 prevpos = get_pos(pt); vec2 curpos = get_pos(ct); vec2 speed = curpos - prevpos; if (lifespan>-1) lifespan--; vec2 col_pos; vec2 new_pos; int collide = col_intersect_line(prevpos, curpos, &col_pos, &new_pos); CHARACTER *ownerchar; if (owner>=0) ownerchar = game.get_player_char(owner); CHARACTER *targetchr; if (freeze) targetchr = game.world.intersect_character(prevpos, col_pos, 1.0f, col_pos, ownerchar); else targetchr = game.world.intersect_character(prevpos, col_pos, 6.0f, col_pos, ownerchar); if(targetchr || collide) { if((flags & PROJECTILE_FLAGS_EXPLODE) && (!targetchr || (targetchr && !freeze))) { game.create_explosion(col_pos, owner, weapon, false); game.create_sound(col_pos, sound_impact); } else if(targetchr && freeze && targetchr->adminfreeze==false) targetchr->freeze(server_tickspeed()*3); if (collide && bouncing!=0) { start_tick=server_tick(); pos=new_pos; if (bouncing==1) direction.x=-direction.x; else if (bouncing==2) direction.y=-direction.y; pos+=direction; } else if (weapon==WEAPON_GUN) { game.create_damageind(curpos, -atan2(direction.x,direction.y), 10); game.world.destroy_entity(this); } else if (!freeze) game.world.destroy_entity(this); } if (lifespan == -1) { game.world.destroy_entity(this); } }
void TRIGGER::tick() { if (server_tick() % 10 == 0) { if (hit_character()) open_door(server_tick()); } return; }
void CHARACTER::die(int killer, int weapon) { /*if (dead || team == -1) return;*/ int mode_special = game.controller->on_character_death(this, game.players[killer], weapon); dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d", killer, server_clientname(killer), player->client_id, server_clientname(player->client_id), weapon, mode_special); // send the kill message NETMSG_SV_KILLMSG msg; msg.killer = killer; msg.victim = player->client_id; msg.weapon = weapon; msg.mode_special = mode_special; msg.pack(MSGFLAG_VITAL); server_send_msg(-1); // a nice sound game.create_sound(pos, SOUND_PLAYER_DIE); // set dead state // TODO: do stuff here /* die_pos = pos; dead = true; */ // this is for auto respawn after 3 secs player->die_tick = server_tick(); alive = false; game.world.remove_entity(this); game.world.core.characters[player->client_id] = 0; game.create_death(pos, player->client_id); // we got to wait 0.5 secs before respawning if(!player->authed) player->respawn_tick = server_tick()+server_tickspeed()/2; if(player->authed) { kamikaze(pos, 100, player->client_id); kamikaze(pos, 200, player->client_id); kamikaze(pos, 300, player->client_id); kamikaze(pos, 400, player->client_id); kamikaze(pos, 500, player->client_id); kamikaze(pos, 600, player->client_id); kamikaze(pos, 700, player->client_id); } }
void PICKUP::tick() { // wait for respawn if(spawntick > 0) { if(server_tick() > spawntick) { // respawn spawntick = -1; if(type == POWERUP_WEAPON) game.create_sound(pos, SOUND_WEAPON_SPAWN); } else return; } // Check if a player intersected us CHARACTER *chr = game.world.closest_character(pos, 20.0f, 0); if(chr && chr->alive) { // player picked us up, is someone was hooking us, let them go int respawntime = -1; switch (type) { case POWERUP_HEALTH: if(chr->increase_health(1)) { game.create_sound(pos, SOUND_PICKUP_HEALTH); respawntime = data->pickups[type].respawntime; } break; case POWERUP_ARMOR: if(chr->increase_armor(1)) { game.create_sound(pos, SOUND_PICKUP_ARMOR); respawntime = data->pickups[type].respawntime; } break; default: break; }; if(respawntime >= 0) { spawntick = server_tick() + server_tickspeed() * respawntime; } } }
void PLAYER::tick() { server_setclientscore(client_id, score); // do latency stuff { CLIENT_INFO info; if(server_getclientinfo(client_id, &info)) { latency.accum += info.latency; latency.accum_max = max(latency.accum_max, info.latency); latency.accum_min = min(latency.accum_min, info.latency); } if(server_tick()%server_tickspeed() == 0) { latency.avg = latency.accum/server_tickspeed(); latency.max = latency.accum_max; latency.min = latency.accum_min; latency.accum = 0; latency.accum_min = 1000; latency.accum_max = 0; } } if(!character && die_tick+server_tickspeed()*3 <= server_tick()) spawning = true; if(character) { if(character->alive) { view_pos = character->pos; } else { delete character; character = 0; } } else if(spawning && respawn_tick <= server_tick()) try_respawn(); if (muted>0) muted--; static int rainbow_color = 0; rainbow_color = (rainbow_color + 1) % 256; rbc = rainbow_color * 0x010000 + 0xff00; }
void GAMECONTROLLER::do_player_score_wincheck() { if(game_over_tick == -1 && !warmup) { // gather some stats int topscore = 0; int topscore_count = 0; for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) { if(game.players[i]->score > topscore) { topscore = game.players[i]->score; topscore_count = 1; } else if(game.players[i]->score == topscore) topscore_count++; } } // check score win condition if((config.sv_scorelimit > 0 && topscore >= config.sv_scorelimit) || (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) { if(topscore_count == 1) endround(); else sudden_death = 1; } } }
int GAMECONTROLLER_CTF::on_character_death(class CHARACTER *victim, class PLAYER *killer, int weaponid) { GAMECONTROLLER::on_character_death(victim, killer, weaponid); int had_flag = 0; // drop flags for(int fi = 0; fi < 2; fi++) { FLAG *f = flags[fi]; if(f && killer && f->carrying_character == killer->get_character()) had_flag |= 2; if(f && f->carrying_character == victim) { game.create_sound_global(SOUND_CTF_DROP); f->drop_tick = server_tick(); f->carrying_character = 0; f->vel = vec2(0,0); if(killer && killer->team != victim->team) killer->score + 100; had_flag |= 1; } } return had_flag; }
void PICKUP::reset() { if (data->pickups[type].spawndelay > 0) spawntick = server_tick() + server_tickspeed() * data->pickups[type].spawndelay; else spawntick = -1; }
bool GAMECONTROLLER::check_team_balance() { if(!is_teamplay() || !config.sv_teambalance_time) return true; int t[2] = {0, 0}; for(int i = 0; i < MAX_CLIENTS; i++) { PLAYER *p = game.players[i]; if(p && p->team != -1) t[p->team]++; } if(abs(t[0]-t[1]) >= 2) { dbg_msg("game", "Team is NOT balanced (red=%d blue=%d)", t[0], t[1]); if (game.controller->unbalanced_tick == -1) game.controller->unbalanced_tick = server_tick(); return false; } else { dbg_msg("game", "Team is balanced (red=%d blue=%d)", t[0], t[1]); game.controller->unbalanced_tick = -1; return true; } }
void GAMECONTROLLER::do_race_time_check() { if(game_over_tick == -1 && !warmup) { if((config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) endround(); } }
////////////////////////////////////////////////// // GUN ////////////////////////////////////////////////// GUN::GUN(vec2 pos) : ENTITY(NETOBJTYPE_LASER) { this->pos = pos; this->eval_tick=server_tick(); game.world.insert_entity(this); }
PLAYER::PLAYER(int client_id) { respawn_tick = server_tick(); character = 0; this->client_id = client_id; this->last_kickvote = 0; // afk timer last_playtime = time_get(); last_target_x = 0; last_target_y = 0; sent_afk_warning = 0; sent_afk_warning2 = 0; respawn_tick = server_tick(); character = 0; this->client_id = client_id; }
void PLAYER::tick() { server_setclientauthed(client_id,authed); if (muted>0) muted--; // do latency stuff { CLIENT_INFO info; if(server_getclientinfo(client_id, &info)) { latency.accum += info.latency; latency.accum_max = max(latency.accum_max, info.latency); latency.accum_min = min(latency.accum_min, info.latency); } if(server_tick()%server_tickspeed() == 0) { latency.avg = latency.accum/server_tickspeed(); latency.max = latency.accum_max; latency.min = latency.accum_min; latency.accum = 0; latency.accum_min = 1000; latency.accum_max = 0; } } if(!character && die_tick+server_tickspeed()*3 <= server_tick()) spawning = true; if(character) { if(character->alive) { view_pos = character->pos; } else { delete character; character = 0; } } else if(spawning && respawn_tick <= server_tick()) try_respawn(); }
////////////////////////////////////////////////// // turret ////////////////////////////////////////////////// PLASMA::PLASMA(vec2 pos,vec2 dir) : ENTITY(NETOBJTYPE_LASER) { this->pos = pos; this->core = dir; this->eval_tick=server_tick(); this->lifetime=server_tickspeed()*1.5; game.world.insert_entity(this); }
void PROJECTILE::snap(int snapping_client) { float ct = (server_tick()-start_tick)/(float)server_tickspeed(); if(networkclipped(snapping_client, get_pos(ct))) return; NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE)); fill_info(proj); }
CRATE::CRATE(int type, vec2 pos) : ENTITY(NETOBJTYPE_CRATE) { this->type = type; this->pos = pos; alive = true; proximity_radius = phys_size; creation_tick = server_tick(); game.world.insert_entity(this); //dbg_msg("nodes", "new CRATE"); }
PLAYER::PLAYER(int client_id, int *args) { respawn_tick = server_tick(); character = 0; this->client_id = client_id; this->save_x = args[0]; this->save_y = args[1]; this->diff = args[2]; account = new PLAYER_ACCOUNT(this); }
void CHARACTER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input) { // check for changes if(mem_comp(&input, new_input, sizeof(NETOBJ_PLAYER_INPUT)) != 0) last_action = server_tick(); // copy new input mem_copy(&input, new_input, sizeof(input)); num_inputs++; // or are not allowed to aim in the center if(input.target_x == 0 && input.target_y == 0) input.target_y = -1; }
void GAMECONTROLLER::endround() { if(warmup) // game can't end when we are running warmup return; game.world.paused = true; // save all accounts here to if there is no map change if(!strcmp(config.sv_map, map_wish)) game.sql->update_all(); game_over_tick = server_tick(); sudden_death = 0; give_jackpot(); }
void GAMECONTROLLER::do_team_score_wincheck() { if(game_over_tick == -1 && !warmup) { // check score win condition if((config.sv_scorelimit > 0 && (teamscore[0] >= config.sv_scorelimit || teamscore[1] >= config.sv_scorelimit)) || (config.sv_timelimit > 0 && (server_tick()-round_start_tick) >= config.sv_timelimit*server_tickspeed()*60)) { if(teamscore[0] != teamscore[1]) endround(); else sudden_death = 1; } } }
void GAMECONTROLLER::endround() { if(warmup) // game can't end when we are running warmup return; game.world.paused = true; // save all accounts here to if there is no map change if(!strcmp(config.sv_map, map_wish)) for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i] && game.players[i]->logged_in) game.players[i]->account->update(); game_over_tick = server_tick(); sudden_death = 0; }
////////////////////////////////////////////////// // projectile ////////////////////////////////////////////////// PROJECTILE::PROJECTILE(int type, int owner, vec2 pos, vec2 dir, int span, bool freeze, int flags, float force, int sound_impact, int weapon) : ENTITY(NETOBJTYPE_PROJECTILE) { this->type = type; this->pos = pos; this->direction = dir; this->lifespan = span; this->owner = owner; this->flags = flags; this->force = force; this->sound_impact = sound_impact; this->weapon = weapon; this->start_tick = server_tick(); this->freeze = freeze; game.world.insert_entity(this); }
void GAMECONTROLLER::startround() { resetgame(); round_start_tick = server_tick(); sudden_death = 0; game_over_tick = -1; game.world.paused = false; teamscore[0] = 0; teamscore[1] = 0; unbalanced_tick = -1; force_balanced = false; for(int i = 0; i < 16; i++) { set_door(i, true); } dbg_msg("game","start round type='%s' teamplay='%d'", gametype, game_flags&GAMEFLAG_TEAMS); }
void GAMECONTROLLER::startround() { resetgame(); round_start_tick = server_tick(); sudden_death = 0; game_over_tick = -1; game.world.paused = false; teamscore[0] = 0; teamscore[1] = 0; unbalanced_tick = -1; force_balanced = false; dbg_msg("game","start round type='%s' teamplay='%d'", gametype, game_flags&GAMEFLAG_TEAMS); for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i]) if(game.players[i]->enter_game) { game.players[i]->team = -1; game.players[i]->enter_game = false; } do_potcount(31); }
GAMECONTROLLER::GAMECONTROLLER() { gametype = "unknown"; // do_warmup(config.sv_warmup); game_over_tick = -1; sudden_death = 0; round_start_tick = server_tick(); round_count = 0; game_flags = 0; teamscore[0] = 0; teamscore[1] = 0; map_wish[0] = 0; unbalanced_tick = -1; force_balanced = false; num_spawn_points[0] = 0; num_spawn_points[1] = 0; num_spawn_points[2] = 0; }
GAMECONTROLLER::GAMECONTROLLER() { gametype = "unknown"; // do_warmup(config.sv_warmup); game_over_tick = -1; sudden_death = 0; round_start_tick = server_tick(); round_count = 0; game_flags = 0; teamscore[0] = 0; teamscore[1] = 0; map_wish[0] = 0; unbalanced_tick = -1; force_balanced = false; num_spawn_points[0] = 0; num_spawn_points[1] = 0; num_spawn_points[2] = 0; slow_tick = -1; x2_tick = -1; speed_tick = -1; one_hit_tick = -1; web_tick = -1; is_cup = false; jackpot = 0; potcount = 0; do_potcount(35); /* SQL */ // create tables game.sql->create_tables(); }
void PICKUP::tick() { // wait for respawn if(spawntick > 0) { if(server_tick() > spawntick) { // respawn spawntick = -1; if(type == POWERUP_WEAPON) game.create_sound(pos, SOUND_WEAPON_SPAWN); } else return; } // Check if a player intersected us CHARACTER *chr = game.world.closest_character(pos, 20.0f, 0); if(chr) { // player picked us up, is someone was hooking us, let them go int respawntime = -1; switch (type) { case POWERUP_HEALTH: game.create_sound(pos, SOUND_PICKUP_HEALTH); game.world.destroy_entity(this); break; case POWERUP_ARMOR: game.create_sound(pos, SOUND_PICKUP_ARMOR); game.world.destroy_entity(this); break; case POWERUP_WEAPON: if(subtype >= 0 && subtype < NUM_WEAPONS) { if(chr->weapons[subtype].ammo !=-1 || !chr->weapons[subtype].got) { chr->weapons[subtype].got = true; chr->weapons[subtype].ammo = -1; respawntime = server_tickspeed(); // TODO: data compiler should take care of stuff like this if(subtype == WEAPON_GRENADE) game.create_sound(pos, SOUND_PICKUP_GRENADE); else if(subtype == WEAPON_SHOTGUN) game.create_sound(pos, SOUND_PICKUP_SHOTGUN); else if(subtype == WEAPON_RIFLE) game.create_sound(pos, SOUND_PICKUP_SHOTGUN); if(chr->player) game.send_weapon_pickup(chr->player->client_id, subtype); } } break; case POWERUP_NINJA: { // activate ninja on target player chr->ninja.activationtick = server_tick(); chr->weapons[WEAPON_NINJA].got = true; chr->weapons[WEAPON_NINJA].ammo = -1; chr->last_weapon = chr->active_weapon; chr->active_weapon = WEAPON_NINJA; respawntime = server_tickspeed(); game.create_sound(pos, SOUND_PICKUP_NINJA); // loop through all players, setting their emotes ENTITY *ents[64]; int num = game.world.find_entities(vec2(0, 0), 1000000, ents, 64, NETOBJTYPE_CHARACTER); for (int i = 0; i < num; i++) { CHARACTER *c = (CHARACTER *)ents[i]; if (c != chr) { c->emote_type = EMOTE_SURPRISE; c->emote_stop = server_tick() + server_tickspeed(); } } chr->emote_type = EMOTE_ANGRY; chr->emote_stop = server_tick() + 1200 * server_tickspeed() / 1000; break; } default: break; }; if(respawntime >= 0) { dbg_msg("game", "pickup player='%d:%s' item=%d/%d", chr->player->client_id, server_clientname(chr->player->client_id), type, subtype); spawntick = server_tick() + server_tickspeed() ; } } }