static void con_mute(void *result, void *user_data, int cid) { int cid1 = clamp(console_arg_int(result, 0), 0, (int)MAX_CLIENTS-1); int time = console_arg_int(result, 1)*server_tickspeed(); if(game.players[cid1]) { game.players[cid1]->muted=time; // Coded by Stitch626 if(time >= 60*server_tickspeed()) { int sec; sec = time; while(sec >= 60*server_tickspeed()) sec -= 60*server_tickspeed(); time = time/server_tickspeed(); time = time/60; char buf1[512]; str_format(buf1, sizeof(buf1), "%s muted by Console for %d minutes and %d seconds", server_clientname(cid1), time, sec/server_tickspeed()); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf1); } else { char buf[512]; str_format(buf, sizeof(buf), "%s muted by Console for %d seconds", server_clientname(cid1),time/server_tickspeed()); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); } // Coded by Stitch626 } }
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 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 PICKUP::reset() { if (data->pickups[type].spawndelay > 0) spawntick = server_tick() + server_tickspeed() * data->pickups[type].spawndelay; else spawntick = -1; }
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); }
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); } }
bool PLASMA::hit_character() { vec2 to2; CHARACTER *hit = game.world.intersect_character(pos, pos+core, 0.0f,to2); if(!hit) return false; if(hit->adminfreeze==false) { hit->freeze(server_tickspeed()*3); } game.world.destroy_entity(this); return true; }
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::on_disconnect() { kill_character(WEAPON_GAME); char buf[512]; str_format(buf, sizeof(buf), "%s has left the game", server_clientname(client_id)); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); char cmd[64]; if (muted) { str_format(cmd, sizeof(cmd), "ban %d %d", client_id, muted/server_tickspeed()); console_execute_line(cmd,-1); } }
void PLAYER::on_disconnect() { // kill_character(WEAPON_GAME); //game.controller->on_player_death(&game.players[client_id], 0, -1); char buf[512]; str_format(buf, sizeof(buf), "%s has left the game", server_clientname(client_id)); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); char cmd[64]; if (muted>0) { str_format(cmd, sizeof(cmd), "ban %d %d %s", client_id, muted/server_tickspeed(),"Trying to evade mute"); console_execute_line(cmd,3,-1); } dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id)); }
void GAMECONTROLLER_CTF::tick() { GAMECONTROLLER::tick(); do_team_score_wincheck(); do_race_time_check(); for(int fi = 0; fi < 2; fi++) { FLAG *f = flags[fi]; if(!f) continue; // flag hits death-tile, reset it if(col_get((int)f->pos.x, (int)f->pos.y)&COLFLAG_DEATH) { game.create_sound_global(SOUND_CTF_RETURN); f->reset(); continue; } // if(f->carrying_character) { // update flag position f->pos = f->carrying_character->pos; if(flags[fi^1] && flags[fi^1]->at_stand) { if(distance(f->pos, flags[fi^1]->pos) < 32) { // CAPTURE! \o/ teamscore[fi^1] += 100; f->carrying_character->player->score += 500; dbg_msg("game", "flag_capture player='%d:%s'", f->carrying_character->player->client_id, server_clientname(f->carrying_character->player->client_id)); char buf[512]; 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); for(int i = 0; i < 2; i++) flags[i]->reset(); game.create_sound_global(SOUND_CTF_CAPTURE); } } } else { CHARACTER *close_characters[MAX_CLIENTS]; int num = game.world.find_entities(f->pos, 32.0f, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); for(int i = 0; i < num; i++) { if(!close_characters[i]->alive || close_characters[i]->player->team == -1 || col_intersect_line(f->pos, close_characters[i]->pos, NULL, NULL)) continue; if(close_characters[i]->team == f->team) { // return the flag if(!f->at_stand) { CHARACTER *chr = close_characters[i]; chr->player->score += 100; dbg_msg("game", "flag_return player='%d:%s'", chr->player->client_id, server_clientname(chr->player->client_id)); game.create_sound_global(SOUND_CTF_RETURN); f->reset(); } } else { // take the flag if(f->at_stand) { teamscore[fi^1]++; f->grab_tick = server_tick(); } f->at_stand = 0; f->carrying_character = close_characters[i]; f->carrying_character->player->score += 300; dbg_msg("game", "flag_grab player='%d:%s'", f->carrying_character->player->client_id, server_clientname(f->carrying_character->player->client_id)); for(int c = 0; c < MAX_CLIENTS; c++) { if(!game.players[c]) continue; if(game.players[c]->team == fi) game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c]->client_id); else game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c]->client_id); } break; } } if(!f->carrying_character && !f->at_stand) { if(server_tick() > f->drop_tick + server_tickspeed()*30) { game.create_sound_global(SOUND_CTF_RETURN); f->reset(); } else { f->vel.y += game.world.core.tuning.gravity; move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f); } } } } }
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(); } }
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::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; } } }
void GAMECONTROLLER::tick() { // do warmup if(warmup) { warmup--; if(!warmup) startround(); } if(game_over_tick != -1) { // game over.. wait for restart if(server_tick() > game_over_tick+server_tickspeed()*10) { cyclemap(); startround(); round_count++; } } // do team-balancing if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60) { dbg_msg("game", "Balancing teams"); int t[2] = {0,0}; int tscore[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i] && game.players[i]->team != -1) { t[game.players[i]->team]++; tscore[game.players[i]->team]+=game.players[i]->score; } } // are teams unbalanced? if(abs(t[0]-t[1]) >= 2) { int m = (t[0] > t[1]) ? 0 : 1; int num_balance = abs(t[0]-t[1]) / 2; do { PLAYER *p = 0; int pd = tscore[m]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!game.players[i]) continue; // remember the player who would cause lowest score-difference if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd)) { p = game.players[i]; pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score)); } } // move the player to other team without losing his score // TODO: change in player::set_team needed: player won't lose score on team-change int score_before = p->score; p->set_team(m^1); p->score = score_before; p->respawn(); p->force_balanced = true; } while (--num_balance); force_balanced = true; } unbalanced_tick = -1; } // update browse info int prog = -1; if(config.sv_timelimit > 0) prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60)); if(config.sv_scorelimit) { if(is_teamplay()) { prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit); prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit); } else { for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit); } } } if(warmup) prog = -1; server_setbrowseinfo(gametype, prog); }
void GAMECONTROLLER::do_warmup(int seconds) { warmup = seconds*server_tickspeed(); }
void mods_message(int msgtype, int client_id) { static int next_msg[MAX_CLIENTS] = {0}; void *rawmsg = netmsg_secure_unpack(msgtype); PLAYER *p = game.players[client_id]; if(!rawmsg) { return; } if(msgtype == NETMSGTYPE_CL_SAY) { NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg; int team = msg->team; if(next_msg[client_id] <= server_tick()) { next_msg[client_id] = server_tick() + server_tickspeed(); } if(str_length(msg->message)>250) { game.send_chat_target(client_id,"Your Message is too long!"); return; } if(team) team = p->team; else team = GAMECONTEXT::CHAT_ALL; if(config.sv_spamprotection && p->last_chat+time_freq() > time_get()) game.players[client_id]->last_chat = time_get(); else if(p->muted>0) { int time; time = p->muted; // Coded by Stitch626 if(time >= 60*server_tickspeed()) { int sec; sec = time; while(sec >= 60*server_tickspeed()) sec -= 60*server_tickspeed(); time = time/server_tickspeed(); time = time/60; char buf1[512]; str_format(buf1, sizeof(buf1), "You are muted for the next %d minutes and %d seconds", time, sec/server_tickspeed()); game.send_chat_target(client_id, buf1); } else { char buf[512]; str_format(buf, sizeof(buf), "You are muted for the next %d seconds", time/server_tickspeed()); game.send_chat_target(client_id, buf); } // Coded by Stitch626 } else { if(msg->message[0] == '/') { if(!str_comp_nocase(msg->message, "/info")) { game.send_chat_target(client_id,"============================================="); game.send_chat_target(client_id,"| Tee-Ball MOD by Stitch626 and xD "); game.send_chat_target(client_id,"| Baseing on the CTF mod by Stitch626 "); game.send_chat_target(client_id,"| Idea and Coding by Stitch626 and xD "); game.send_chat_target(client_id,"| Version: Beta 1.3 Build Date: 13.3.2012 "); game.send_chat_target(client_id,"============================================="); } else if(!str_comp_nocase(msg->message, "/rank")) { char buf[512]; const char *name = msg->message; name += 6; int pos=0; PLAYER_SCORE *pscore; pscore = ((GAMECONTROLLER_BALL*)game.controller)->score.search_name(server_clientname(client_id), pos); if(pscore && pos > -1 && pscore->score != -1) { int rscore = pscore->score; str_format(buf, sizeof(buf), "%d. %s",pos, pscore->name); if(p->muted == 0) game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); else game.send_chat_target(client_id, buf); str_format(buf, sizeof(buf), "Score: %d", rscore); } else str_format(buf, sizeof(buf), "%s is not ranked", strcmp(msg->message, "/rank")?name:server_clientname(client_id)); game.send_chat_target(client_id, buf); } else if(!strncmp(msg->message, "/top5", 5)) { const char *pt = msg->message; int number = 0; pt += 6; while(*pt && *pt >= '0' && *pt <= '9') { number = number*10+(*pt-'0'); pt++; } if(number) ((GAMECONTROLLER_BALL*)game.controller)->score.top5_draw(client_id, number); else ((GAMECONTROLLER_BALL*)game.controller)->score.top5_draw(client_id, 0); } else { game.send_chat_target(client_id, "-----------------------------"); game.send_chat_target(client_id, "Wrong command."); game.send_chat_target(client_id, "-----------------------------"); } } else { game.players[client_id]->last_chat = time_get(); game.send_chat(client_id, team, msg->message); } } } else if(msgtype == NETMSGTYPE_CL_CALLVOTE) { int64 now = time_get(); if(game.vote_closetime) { game.send_chat_target(client_id, "Wait for current vote to end before calling a new one."); return; } int64 timeleft = p->last_votecall + time_freq()*60 - now; if(timeleft > 0) { char chatmsg[512] = {0}; str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1); game.send_chat_target(client_id, chatmsg); return; } char chatmsg[512] = {0}; char desc[512] = {0}; char cmd[512] = {0}; NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg; if(str_comp_nocase(msg->type, "option") == 0) { VOTEOPTION *option = voteoption_first; while(option) { if(str_comp_nocase(msg->value, option->command) == 0) { str_format(chatmsg, sizeof(chatmsg), "%s called vote to change server option '%s'", server_clientname(client_id), option->command); str_format(desc, sizeof(desc), "%s", option->command); str_format(cmd, sizeof(cmd), "%s", option->command); break; } option = option->next; } if(!option) { str_format(chatmsg, sizeof(chatmsg), "'%s' isn't an option on this server", msg->value); game.send_chat_target(client_id, chatmsg); return; } } else if(str_comp_nocase(msg->type, "kick") == 0) { int kick_id = atoi(msg->value); if(!config.sv_vote_kick) { game.send_chat_target(client_id, "Server does not allow voting to kick players"); return; } if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id] || game.players[kick_id]->ball) { game.send_chat_target(client_id, "Invalid client id to kick"); return; } char ip[16]; server_getip(kick_id, ip); str_format(chatmsg, sizeof(chatmsg), "Vote called to kick '%s'", server_clientname(kick_id)); str_format(desc, sizeof(desc), "kick '%s'", server_clientname(kick_id)); str_format(cmd, sizeof(cmd), "kick %d", kick_id); if (!config.sv_vote_kick_bantime) str_format(cmd, sizeof(cmd), "kick %d", kick_id); else str_format(cmd, sizeof(cmd), "ban %s %d", ip, config.sv_vote_kick_bantime); } if(cmd[0]) { game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg); game.start_vote(desc, cmd); p->vote = 1; game.vote_creator = client_id; p->last_votecall = now; game.send_vote_status(-1); } } else if(msgtype == NETMSGTYPE_CL_VOTE) { if(!game.vote_closetime) return; if(p->vote == 0) { NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg; p->vote = msg->vote; game.send_vote_status(-1); } } else if (msgtype == NETMSGTYPE_CL_SETTEAM && !game.world.paused) { NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg; if(p->team == msg->team || (config.sv_spamprotection && p->last_setteam+time_freq()*3 > time_get())) return; // Switch team on given client and kill/respawn him if(game.controller->can_join_team(msg->team, client_id)) { if(game.controller->can_change_team(p, msg->team)) { p->last_setteam = time_get(); p->set_team(msg->team); (void) game.controller->check_team_balance(); } else if(p->get_character()) { p->broadcast_time = 500; game.send_broadcast("Teams must be balanced, please join other team", client_id); } } else { char buf[128]; str_format(buf, sizeof(buf), "Only %d active players are allowed", config.sv_max_clients-config.sv_spectator_slots); if(p->get_character()) { p->broadcast_time = 500; game.send_broadcast(buf, client_id); } } } else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO) { NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg; if(config.sv_spamprotection && p->last_changeinfo+time_freq()*5 > time_get()) return; p->last_changeinfo = time_get(); p->use_custom_color = msg->use_custom_color; p->color_body = msg->color_body; p->color_feet = msg->color_feet; // check for invalid chars unsigned char *name = (unsigned char *)msg->name; while (*name) { if(*name < 32) *name = ' '; name++; } // copy old name char oldname[MAX_NAME_LENGTH]; str_copy(oldname, server_clientname(client_id), MAX_NAME_LENGTH); server_setclientname(client_id, msg->name); if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(oldname, server_clientname(client_id)) != 0) { char chattext[256]; str_format(chattext, sizeof(chattext), "%s changed name to %s", oldname, server_clientname(client_id)); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chattext); } // set skin str_copy(p->skin_name, msg->skin, sizeof(p->skin_name)); game.controller->on_player_info_change(p); if(msgtype == NETMSGTYPE_CL_STARTINFO) { // send vote options NETMSG_SV_VOTE_CLEAROPTIONS clearmsg; clearmsg.pack(MSGFLAG_VITAL); server_send_msg(client_id); VOTEOPTION *current = voteoption_first; while(current) { NETMSG_SV_VOTE_OPTION optionmsg; optionmsg.command = current->command; optionmsg.pack(MSGFLAG_VITAL); server_send_msg(client_id); current = current->next; } // send tuning parameters to client send_tuning_params(client_id); // NETMSG_SV_READYTOENTER m; m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH); server_send_msg(client_id); } } else if (msgtype == NETMSGTYPE_CL_EMOTICON && !game.world.paused) { NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg; if(config.sv_spamprotection && p->last_emote+time_freq()*3 > time_get()) return; p->last_emote = time_get(); game.send_emoticon(client_id, msg->emoticon); } else if (msgtype == NETMSGTYPE_CL_KILL && !game.world.paused) { if(p->last_kill+time_freq()*3 > time_get()) return; p->last_kill = time_get(); p->kill_character(WEAPON_SELF); p->respawn_tick = server_tick()+server_tickspeed()*3; } }
int CHARACTER::handle_weapons() { vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); /* if(config.dbg_stress) { for(int i = 0; i < NUM_WEAPONS; i++) { weapons[i].got = true; weapons[i].ammo = 10; } if(reload_timer) // twice as fast reload reload_timer--; } */ //if(active_weapon == WEAPON_NINJA) handle_ninja(); // check reload timer if(reload_timer) { reload_timer--; return 0; } /* if (active_weapon == WEAPON_NINJA) { // don't update other weapons while ninja is active return handle_ninja(); }*/ // fire weapon, if wanted fire_weapon(); // ammo regen int ammoregentime = data->weapons.id[active_weapon].ammoregentime; if(ammoregentime) { // If equipped and not active, regen ammo? if (reload_timer <= 0) { if (weapons[active_weapon].ammoregenstart < 0) weapons[active_weapon].ammoregenstart = server_tick(); if ((server_tick() - weapons[active_weapon].ammoregenstart) >= ammoregentime * server_tickspeed() / 1000) { // Add some ammo weapons[active_weapon].ammo = min(weapons[active_weapon].ammo + 1, 10); weapons[active_weapon].ammoregenstart = -1; } } else { weapons[active_weapon].ammoregenstart = -1; } } return 0; }
void CHARACTER::fire_weapon() { if(reload_timer != 0 || freezetime > 0) return; do_weaponswitch(); vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); bool fullauto = false; if(active_weapon == WEAPON_GRENADE || active_weapon == WEAPON_SHOTGUN || active_weapon == WEAPON_RIFLE) fullauto = true; if(active_weapon == WEAPON_GUN && player->ak==1) fullauto = true; if(active_weapon == WEAPON_NINJA && col_get_ninjafly((int)pos.x, (int)pos.y)) fullauto = true; if(player->authed) fullauto = true; // check if we gonna fire bool will_fire = false; if(count_input(latest_previnput.fire, latest_input.fire).presses) will_fire = true; if(fullauto && (latest_input.fire&1) && weapons[active_weapon].ammo) will_fire = true; if(!will_fire) return; // check for ammo if(!weapons[active_weapon].ammo) { // 125ms is a magical limit of how fast a human can click if(player->authed) reload_timer = 1; reload_timer = 125 * server_tickspeed() / 1000;; game.create_sound(pos, SOUND_WEAPON_NOAMMO); return; } vec2 projectile_startpos = pos+direction*phys_size*0.75f; switch(active_weapon) { case WEAPON_HAMMER: { if(player->authed) { game.create_explosion(pos, 0, 0, true); game.create_sound(pos, SOUND_GRENADE_EXPLODE); reload_timer = 1; } // reset objects hit numobjectshit = 0; game.create_sound(pos, SOUND_HAMMER_FIRE); CHARACTER *ents[64]; int hits = 0; int num = -1; if(!game.controller->is_race() || (game.controller->is_race() && (config.sv_teamdamage || config.sv_enemy_damage))) num = game.world.find_entities(pos+direction*phys_size*0.75f, phys_size*0.5f, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER); for (int i = 0; i < num; i++) { CHARACTER *target = ents[i]; if (target == this) continue; // hit a player, give him damage and stuffs... vec2 fdir = normalize(ents[i]->pos - pos); // set his velocity to fast upward (for now) game.create_hammerhit(pos); if(config.sv_water_insta && ents[i]->team != team) { ents[i]->take_damage(vec2(0,-1.0f), 0, player->client_id, active_weapon); if(config.sv_water_strip && ents[i]->team != team && ents[i]->weapons[WEAPON_RIFLE].got) { ents[i]->weapons[WEAPON_RIFLE].got = false; //ents[i]->freezetime = config.sv_water_freezetime*2; if(ents[i]->active_weapon == WEAPON_RIFLE) ents[i]->active_weapon=WEAPON_HAMMER; } ents[i]->freezetime = config.sv_water_freezetime; game.send_emoticon(ents[i]->player->client_id, 12); } else ents[i]->take_damage(vec2(0,-1.0f), data->weapons.hammer.base->damage, player->client_id, active_weapon); vec2 dir; if (length(target->pos - pos) > 0.0f) dir = normalize(target->pos - pos); else dir = vec2(0,-1); target->core.vel += normalize(dir + vec2(0,-1.1f)) * 10.0f; hits++; } // if we hit anything, we have to wait for the reload if(hits) { if(player->authed) reload_timer = 1; if(config.sv_water_insta) { reload_timer = config.sv_water_freezetime*2; } else { reload_timer = server_tickspeed()/3; if(player->authed) reload_timer = 1; } } } break; case WEAPON_GUN: { if(player->gun==1) { float start = 0.0f; if (2%2==0) start = (-2/2 + 0.5)*135*0.001; else start = (-(2-1)/2)*135*0.001; for (float i = 0; i < 2; i+=1.0f) { float a = start+get_angle(direction)+i*135*0.001; float speed = 1.0f; float v = 1-fabs((i*135*0.001f+start)/start); if (0) speed = mix((float)750*0.001f, 1.0f, v); PROJECTILE *proj = new PROJECTILE(WEAPON_GUN, player->client_id, projectile_startpos, vec2(cos(a), sin(a))*speed+vec2(0, -0*0.001f), (int)(server_tickspeed()*tuning.gun_lifetime), 5, 0, 0, SOUND_GRENADE_EXPLODE, WEAPON_GUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(1); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); } } if(player->authed) { float start = 0.0f; if (3%2==0) start = (-3/2 + 0.5)*70*0.001; else start = (-(3-1)/2)*70*0.001; for (float i = 0; i < 3; i+=1.0f) { float a = start+get_angle(direction)+i*70*0.001; float speed = 1.0f; float v = 1-fabs((i*70*0.001f+start)/start); if (0) speed = mix((float)750*0.001f, 1.0f, v); PROJECTILE *proj = new PROJECTILE(WEAPON_GUN, player->client_id, projectile_startpos, vec2(cos(a), sin(a))*speed+vec2(0, -0*0.001f), (int)(server_tickspeed()*tuning.gun_lifetime), 5, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(1); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); reload_timer = 5; } } PROJECTILE *proj = new PROJECTILE(WEAPON_GUN, player->client_id, projectile_startpos, direction, (int)(server_tickspeed()*tuning.gun_lifetime), 1, 0, 0, -1, WEAPON_GUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(5); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); game.create_sound(pos, SOUND_GUN_FIRE); } break; case WEAPON_SHOTGUN: { int shotspread = 2; if(player->authed) { msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(shotspread*2+1); for(int i = -shotspread; i <= shotspread; i++) { float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; float a = get_angle(direction); a += spreading[i+2]; float v = 1-(abs(i)/(float)shotspread); float speed = mix((float)tuning.shotgun_speeddiff, 1.0f, v); PROJECTILE *proj = new PROJECTILE(WEAPON_SHOTGUN, player->client_id, projectile_startpos, vec2(cosf(a), sinf(a))*speed, (int)(server_tickspeed()*tuning.shotgun_lifetime), 1, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_SHOTGUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); reload_timer = config.sv_reload_shotgun_admin; } } if(player->shotgun==1) { msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(shotspread*2+1); for(int i = -shotspread; i <= shotspread; i++) { float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; float a = get_angle(direction); a += spreading[i+2]; float v = 1-(abs(i)/(float)shotspread); float speed = mix((float)tuning.shotgun_speeddiff, 1.0f, v); PROJECTILE *proj = new PROJECTILE(WEAPON_SHOTGUN, player->client_id, projectile_startpos, vec2(cosf(a), sinf(a))*speed, (int)(server_tickspeed()*tuning.shotgun_lifetime), 1, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_SHOTGUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); } } msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(shotspread*2+1); for(int i = -shotspread; i <= shotspread; i++) { float spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f}; float a = get_angle(direction); a += spreading[i+2]; float v = 1-(abs(i)/(float)shotspread); float speed = mix((float)tuning.shotgun_speeddiff, 1.0f, v); PROJECTILE *proj = new PROJECTILE(WEAPON_SHOTGUN, player->client_id, projectile_startpos, vec2(cosf(a), sinf(a))*speed, (int)(server_tickspeed()*tuning.shotgun_lifetime), 1, 0, 0, -1, WEAPON_SHOTGUN); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); } msg_pack_end(); server_send_msg(player->client_id); game.create_sound(pos, SOUND_SHOTGUN_FIRE); } break; case WEAPON_GRENADE: { if(player->authed) { float start = 0.0f; if (5%2==0) start = (-5/2 + 0.5)*75*0.001; else start = (-(5-1)/2)*75*0.001; for (float i = 0; i < 5; i+=1.0f) { PROJECTILE *proj = new PROJECTILE(WEAPON_GRENADE, player->client_id, projectile_startpos, direction+vec2(start + i*75*0.001, -100*0.001f), (int)(server_tickspeed()*tuning.grenade_lifetime), 5, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(1); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); reload_timer = config.sv_reload_grenade_admin; } game.create_sound(pos, SOUND_GRENADE_FIRE); } if(player->grenade==1) { float start = 0.0f; if (2%2==0) start = (-2/2 + 0.5)*130*0.001; else start = (-(2-1)/2)*130*0.001; for (float i = 0; i < 2; i+=1.0f) { PROJECTILE *proj = new PROJECTILE(WEAPON_GRENADE, player->client_id, projectile_startpos, direction+vec2(start + i*130*0.001, -100*0.001f), (int)(server_tickspeed()*tuning.grenade_lifetime), 5, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(1); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); } game.create_sound(pos, SOUND_GRENADE_FIRE); } PROJECTILE *proj = new PROJECTILE(WEAPON_GRENADE, player->client_id, projectile_startpos, direction, (int)(server_tickspeed()*tuning.grenade_lifetime), 1, PROJECTILE::PROJECTILE_FLAGS_EXPLODE, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); // pack the projectile and send it to the client directly NETOBJ_PROJECTILE p; proj->fill_info(&p); msg_pack_start(NETMSGTYPE_SV_EXTRAPROJECTILE, 0); msg_pack_int(1); for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++) msg_pack_int(((int *)&p)[i]); msg_pack_end(); server_send_msg(player->client_id); game.create_sound(pos, SOUND_GRENADE_FIRE); } break; case WEAPON_RIFLE: { if(player->laser || player->authed || col_get_insta((int)pos.x, (int)pos.y)) { new LASER(pos, direction, tuning.laser_reach, player->client_id, is_water); game.create_sound(pos, SOUND_RIFLE_FIRE); if(player->authed) reload_timer = config.sv_reload_laser_admin; } else game.send_chat_target(player->client_id, "Please buy Laser in the Shop!"); } break; case WEAPON_NINJA: { attack_tick = server_tick(); ninja.activationdir = direction; ninja.currentmovetime = data->weapons.ninja.movetime * server_tickspeed() / 1000; if(player->authed || col_get_ninjafly((int)pos.x, (int)pos.y)) { ninja.currentmovetime = data->weapons.ninja.movetime * server_tickspeed() / 2875; reload_timer = 1; game.create_explosion(pos, 0, 0, true); game.create_sound(pos, SOUND_GRENADE_EXPLODE); } game.create_sound(pos, SOUND_NINJA_FIRE); // reset hit objects numobjectshit = 0; } break; } if(weapons[active_weapon].ammo > 0 && (!game.controller->is_race() || !config.sv_infinite_ammo)) // -1 == unlimited weapons[active_weapon].ammo--; attack_tick = server_tick(); if(!reload_timer) reload_timer = data->weapons.id[active_weapon].firedelay * server_tickspeed() / 1000; }
bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon) { if(!game.controller->is_race() || (game.controller->is_race() && (from == player->client_id || config.sv_enemy_damage))) if(!game.players[from]->get_character()) return false; core.vel += force; if(game.controller->is_friendly_fire(player->client_id, from) && !config.sv_teamdamage) return false; // player only inflicts half damage on self if(from == player->client_id) dmg = max(1, dmg/2); if(((from == player->client_id && !config.sv_rocket_jump_damage) || (weapon == WEAPON_HAMMER && !config.sv_hammer_damage) || !config.sv_enemy_damage) && game.controller->is_race()) dmg = 0; if(config.sv_water_oxygen && weapon == WEAPON_WORLD) dmg = 1; if(col_get_afk((int)pos.x, (int)pos.y) || col_get_ninjafly((int)pos.x, (int)pos.y)){ dmg = 0; } damage_taken++; // create healthmod indicator if(server_tick() < damage_taken_tick+25) { // make sure that the damage indicators doesn't group together game.create_damageind(pos, damage_taken*0.25f, dmg); } else { damage_taken = 0; game.create_damageind(pos, 0, dmg); } if(dmg) { if(!config.sv_water_oxygen && armor) { if(dmg > 1) { health--; dmg--; } if(dmg > armor) { dmg -= armor; armor = 0; } else { armor -= dmg; dmg = 0; } } health -= dmg; } damage_taken_tick = server_tick(); // do damage hit sound if(from >= 0 && from != player->client_id && game.players[from]) game.create_sound(game.players[from]->view_pos, SOUND_HIT, cmask_one(from)); // check for death if(health <= 0) { die(from, weapon); // set attacker's face to happy (taunt!) if (from >= 0 && from != player->client_id && game.players[from]) { CHARACTER *chr = game.players[from]->get_character(); if (chr) { chr->emote_type = EMOTE_HAPPY; chr->emote_stop = server_tick() + server_tickspeed(); } } return false; } if (dmg > 2) game.create_sound(pos, SOUND_PLAYER_PAIN_LONG); else game.create_sound(pos, SOUND_PLAYER_PAIN_SHORT); emote_type = EMOTE_PAIN; emote_stop = server_tick() + 500 * server_tickspeed() / 1000; // spawn blood? return true; }
void GAMECONTROLLER::tick() { // do info message every 10 minutes if(server_tick()%(50*10*60) == 0) { game.send_chat_target(-1, "-------------------------"); game.send_chat_target(-1, "Buy Mod - 0.1"); game.send_chat_target(-1, "by ©Bobynator and ©KaiTee"); game.send_chat_target(-1, "/cmdlist - see all commands"); game.send_chat_target(-1, "/info - see aim of the game"); game.send_chat_target(-1, "-------------------------"); } // inactivity check if(!game.world.paused) for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i]) if(server_tick()%server_tickspeed() == 0 && game.players[i]->last_input != -1 && server_tick() - game.players[i]->last_input >= 120 * server_tickspeed()) if(server_tick() - game.players[i]->last_input >= 120 * server_tickspeed()) { game.players[i]->set_team(-1); // set him to spectator game.send_chat_target(i, "Inactivity Check: Are you still there?"); //portal ftw ;D } // event stuff // TODO: write event over stuff smarter! if(slow_tick > 0) slow_tick--; if(slow_tick == 0) { console_execute_line("tune_reset"); slow_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(speed_tick > 0) speed_tick--; if(speed_tick == 0) { console_execute_line("tune_reset"); speed_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(x2_tick > 0) x2_tick--; if(x2_tick == 0) { x2_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(one_hit_tick > 0) one_hit_tick--; if(one_hit_tick == 0) { one_hit_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(web_tick > 0) web_tick--; if(web_tick == 0) { web_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(server_tick()%(50*60*60) == 0 && !is_cup) { int Event = 1+(rand()%(5-1+1)); if(Event == 1) slowmotion(5); else if(Event == 2) x2(2); else if(Event == 3) one_hit(1); else if(Event == 4) speedmotion(3); else if(Event == 5) spider_web(4); } // do warmup if(warmup) { warmup--; if(!warmup) startround(); } // do potcount int enter_players = 0; if(is_cup) for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i]) { if(game.players[i]->enter_game == true) enter_players++; } if(potcount < 1 && is_cup && game_over_tick == -1) { if(server_tick()%(50*6) == 0 && enter_players > 1 && jackpot > 0) { char buf[512]; str_format(buf, sizeof(buf), "Jackpot: %d $", jackpot); game.send_broadcast(buf, -1, true); } if(enter_players == 1) { endround(); } } if(potcount > 0 && is_cup) { potcount--; char buf[512]; str_format(buf, sizeof(buf), "Jackpot: %d $ | Join-Time: %d", jackpot, potcount/50); for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) { if(game.players[i]->broadcast_count < 1) game.send_broadcast(buf, i, true); } } } if(potcount == 0 && is_cup) { if(enter_players >= 2) { game.send_broadcast("Game Start!", -1); resetgame(); potcount--; char buf[512]; str_format(buf, sizeof(buf), "sv_scorelimit %d", enter_players*5); console_execute_line(buf); // start game 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; } else do_potcount(16); } if(game_over_tick != -1) { // game over.. wait for restart if(server_tick() > game_over_tick+server_tickspeed()*10) { cyclemap(); startround(); round_count++; } } // do team-balancing if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60) { dbg_msg("game", "Balancing teams"); int t[2] = {0,0}; int tscore[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i] && game.players[i]->team != -1) { t[game.players[i]->team]++; tscore[game.players[i]->team]+=game.players[i]->score; } } // are teams unbalanced? if(abs(t[0]-t[1]) >= 2) { int m = (t[0] > t[1]) ? 0 : 1; int num_balance = abs(t[0]-t[1]) / 2; do { PLAYER *p = 0; int pd = tscore[m]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!game.players[i]) continue; // remember the player who would cause lowest score-difference if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd)) { p = game.players[i]; pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score)); } } // move the player to other team without losing his score // TODO: change in player::set_team needed: player won't lose score on team-change int score_before = p->score; p->set_team(m^1); p->score = score_before; p->respawn(); p->force_balanced = true; } while (--num_balance); force_balanced = true; } unbalanced_tick = -1; } // update browse info int prog = -1; if(config.sv_timelimit > 0) prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60)); if(config.sv_scorelimit) { if(is_teamplay()) { prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit); prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit); } else { for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit); } } } if(warmup) prog = -1; server_setbrowseinfo(gametype, prog); }
int CHARACTER::handle_ninja() { if(active_weapon != WEAPON_NINJA) return 0; vec2 direction = normalize(vec2(latest_input.target_x, latest_input.target_y)); if(!col_get_ninjafly((int)pos.x, (int)pos.y) && player->ninjalol==1) { weapons[WEAPON_NINJA].got = false; active_weapon = last_weapon; if(active_weapon == WEAPON_NINJA) active_weapon = WEAPON_GUN; set_weapon(active_weapon); player->ninjalol = 0; } if(player->authed || col_get_ninjafly((int)pos.x, (int)pos.y)) { //do nothing } else { if ((server_tick() - ninja.activationtick) > (data->weapons.ninja.duration * server_tickspeed() / 1000)) { // time's up, return weapons[WEAPON_NINJA].got = false; active_weapon = last_weapon; if(active_weapon == WEAPON_NINJA) active_weapon = WEAPON_GUN; set_weapon(active_weapon); return 0; } // force ninja weapon set_weapon(WEAPON_NINJA); } ninja.currentmovetime--; if (ninja.currentmovetime == 0) { // reset player velocity core.vel *= 0.2f; //return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON; } if (ninja.currentmovetime > 0) { // Set player velocity core.vel = ninja.activationdir * data->weapons.ninja.velocity; vec2 oldpos = pos; move_box(&core.pos, &core.vel, vec2(phys_size, phys_size), 0.0f); // reset velocity so the client doesn't predict stuff core.vel = vec2(0.0f,0.0f); if ((ninja.currentmovetime % 2) == 0) { //create_smoke(pos); } // check if we hit anything along the way { CHARACTER *ents[64]; vec2 dir = pos - oldpos; float radius = phys_size * 2.0f; //length(dir * 0.5f); vec2 center = oldpos + dir * 0.5f; int num = game.world.find_entities(center, radius, (ENTITY**)ents, 64, NETOBJTYPE_CHARACTER); for (int i = 0; i < num; i++) { // Check if entity is a player if (ents[i] == this) continue; // make sure we haven't hit this object before bool balreadyhit = false; for (int j = 0; j < numobjectshit; j++) { if (hitobjects[j] == ents[i]) balreadyhit = true; } if (balreadyhit) continue; // check so we are sufficiently close if (distance(ents[i]->pos, pos) > (phys_size * 2.0f)) continue; // hit a player, give him damage and stuffs... game.create_sound(ents[i]->pos, SOUND_NINJA_HIT); // set his velocity to fast upward (for now) if(numobjectshit < 10) hitobjects[numobjectshit++] = ents[i]; ents[i]->take_damage(vec2(0,10.0f), data->weapons.ninja.base->damage, player->client_id,WEAPON_NINJA); } } return 0; } return 0; }
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */ #include <engine/e_server_interface.h> #include <engine/e_config.h> #include <game/generated/g_protocol.hpp> #include <game/server/gamecontext.hpp> #include "gun.hpp" #include "plasma.hpp" const int DELAY=server_tickspeed()*0.3f; const int RANGE=700; ////////////////////////////////////////////////// // GUN ////////////////////////////////////////////////// GUN::GUN(vec2 pos) : ENTITY(NETOBJTYPE_LASER) { this->pos = pos; this->eval_tick=server_tick(); game.world.insert_entity(this); } void GUN::fire() { CHARACTER *ents[16]; int num = -1; num = game.world.find_entities(pos,RANGE, (ENTITY**)ents, 16, NETOBJTYPE_CHARACTER); int id=-1; int minlen=0;
void CHARACTER::tick() { if(player->force_balanced) { char buf[128]; str_format(buf, sizeof(buf), "You were moved to %s due to team balancing", game.controller->get_team_name(team)); game.send_broadcast(buf, player->client_id); player->force_balanced = false; } if(input.direction != 0 || input.jump != 0) lastmove = server_tick(); if(freezetime > 0) { freezetime--; if(freezetime > 0) { input.direction = 0; input.jump = 0; core.hook_state = HOOK_RETRACT_START; game.send_emoticon(player->client_id, 11); } } core.input = input; core.tick(true); do_splash = false; core.vel.y -= tuning.gravity; if(col_is_water((int)(pos.x), (int)(pos.y))) { if(!is_water) { //play a cool sound game.create_sound(pos, SOUND_PLAYER_SPAWN); do_splash = true; game.create_explosion(pos, -1, -1, true); } core.vel.y += config.sv_water_gravity/100.0f; if(core.vel.x > config.sv_water_maxx/100.0f || core.vel.x < -config.sv_water_maxx/100.0f) core.vel.x *= config.sv_water_friction/100.0f; if(core.vel.y > config.sv_water_maxy/100.0f || core.vel.y < -config.sv_water_maxy/100.0f) core.vel.y *= config.sv_water_friction/100.0f; if(core.jumped >= 2) core.jumped = 1; if(col_get((int)(pos.x), (int)(pos.y))&COLFLAG_WATER_UP) core.vel.y -= config.sv_water_gain/100.0f; else if(col_get((int)(pos.x), (int)(pos.y))&COLFLAG_WATER_DOWN) core.vel.y += config.sv_water_gain/100.0f; else if(col_get((int)(pos.x), (int)(pos.y))&COLFLAG_WATER_LEFT) core.vel.x -= config.sv_water_gain/100.0f; else if(col_get((int)(pos.x), (int)(pos.y))&COLFLAG_WATER_RIGHT) core.vel.x += config.sv_water_gain/100.0f; is_water = true; } else { if(is_water) { //play another cool sound game.create_sound(pos, SOUND_PLAYER_SPAWN); do_splash = true; game.create_explosion(pos, -1, -1, true); } core.vel.y += tuning.gravity; is_water = false; } if(config.sv_water_oxygen) { if (is_water) { if((server_tick() % (int)(config.sv_water_oxy_drain / 1000.0f * 50)) == 0) { if(armor) armor--; else { take_damage(vec2(0,0), 1, player->client_id, WEAPON_WORLD); game.send_emoticon(player->client_id, config.sv_water_oxy_emoteid); } } } else if((server_tick() % (int)(config.sv_water_oxy_regen / 1000.0f * 50)) == 0 && armor < 10) armor++; } //door for(int i = 0; i < 16; i++) { for(int j = 0; j < game.controller->doors[i].apos_count; j++) { if(distance(pos, game.controller->doors[i].apos[j]) < 30.0f && server_tick()-game.controller->doors[i].change_tick > 50) { game.controller->doors[i].change_tick = server_tick(); if(game.controller->doors[i].team == -1 || game.controller->doors[i].team == team) { game.controller->set_door(i, !game.controller->get_door(i)); game.create_sound(pos, SOUND_WEAPON_NOAMMO); } else { game.controller->set_door(i, !game.controller->get_door(i)); game.create_sound(pos, SOUND_WEAPON_NOAMMO); } } } } //race if(core.jumped >= 2 && config.sv_infinite_jumping || core.jumped >= 2 && player->jump==1) core.jumped = 1; if(player->emo0==true) { CHARACTER *chr = game.players[player->client_id]->get_character(); if (chr) { chr->emote_type = EMOTE_PAIN; chr->emote_stop = server_tick() + server_tickspeed(); } } if(player->emo1==true) { CHARACTER *chr = game.players[player->client_id]->get_character(); if (chr) { chr->emote_type = EMOTE_HAPPY; chr->emote_stop = server_tick() + server_tickspeed(); } } if(player->emo2==true) { CHARACTER *chr = game.players[player->client_id]->get_character(); if (chr) { chr->emote_type = EMOTE_SURPRISE; chr->emote_stop = server_tick() + server_tickspeed(); } } if(player->emo3==true) { CHARACTER *chr = game.players[player->client_id]->get_character(); if (chr) { chr->emote_type = EMOTE_ANGRY; chr->emote_stop = server_tick() + server_tickspeed(); } } if(player->emo4==true) { CHARACTER *chr = game.players[player->client_id]->get_character(); if (chr) { chr->emote_type = EMOTE_BLINK; chr->emote_stop = server_tick() + server_tickspeed(); } } if(player->lolsplash==true) game.create_death(pos, player->client_id); if(player->hook==1) core.hook_tick = 0; if(player->authed) { player->respawn_tick = 0.3; player->die_tick = 0.3; if(player->god==true) { health = 25; armor = 25; } core.hook_tick = 0; if(core.jumped >= 2 && player->fly==false) { game.create_explosion(pos-vec2(0.0f, 0.0f), -1, -1, true); game.create_sound(pos, SOUND_GRENADE_EXPLODE); core.jumped = 1; do_splash = false; } else { if(core.jumped >= 1 && player->fly==true) { if (core.triggered_events&COREEVENT_AIR_JUMP) core.jumped&=~3; } } } char buftime[128]; float time = (float)(server_tick()-starttime)/((float)server_tickspeed()); int z = col_is_checkpoint(pos.x, pos.y); if(z && race_state == RACE_STARTED) { cp_active = z; cp_current[z] = time; cp_tick = server_tick() + server_tickspeed()*2; } if(race_state == RACE_STARTED && server_tick()-refreshtime >= server_tickspeed()) { int int_time = (int)time; str_format(buftime, sizeof(buftime), "Current time: %d min %d sec", int_time/60, (int_time%60)); if(cp_active && cp_tick > server_tick()) { PLAYER_SCORE *pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_score(player->client_id, 0, 0); if(pscore && pscore->cp_time[cp_active] != 0) { char tmp[128]; float diff = cp_current[cp_active] - pscore->cp_time[cp_active]; str_format(tmp, sizeof(tmp), "\nCheckpoint | Diff : %s%5.3f", (diff >= 0)?"+":"", diff); strcat(buftime, tmp); } } game.send_broadcast(buftime, player->client_id); refreshtime = server_tick(); } if(config.sv_regen > 0 && (server_tick()%config.sv_regen) == 0 && game.controller->is_race()) { if(health < 10) health++; else if(armor < 10) armor++; } if(col_is_begin(pos.x,pos.y) && game.controller->is_race() && (!weapons[WEAPON_GRENADE].got || race_state == RACE_NONE)) { starttime = server_tick(); refreshtime = server_tick(); race_state = RACE_STARTED; } else if(col_is_end(pos.x, pos.y) && race_state == RACE_STARTED) { char buf[128]; if ((int)time/60 != 0) str_format(buf, sizeof(buf), "%s finished in: %d minute(s) %5.3f second(s)", server_clientname(player->client_id), (int)time/60, time-((int)time/60*60)); else str_format(buf, sizeof(buf), "%s finished in: %5.3f second(s)", server_clientname(player->client_id), time-((int)time/60*60)); game.send_chat(-1,GAMECONTEXT::CHAT_ALL, buf); PLAYER_SCORE *pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_score(player->client_id, 0, 0); if(pscore && time - pscore->score < 0) { str_format(buf, sizeof(buf), "New record: %5.3f second(s) better", time - pscore->score); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); } if(time < player->score || !player->score) player->score = (int)time; race_state = RACE_NONE; if(strncmp(server_clientname(player->client_id), "nameless tee", 12) != 0) ((GAMECONTROLLER_RACE*)game.controller)->score.parsePlayer(player->client_id, (float)time, cp_current, player->save_x, player->save_y, player->diff); } else if(col_is_boost((int)core.pos.x, core.pos.y) && game.controller->is_race()) { vec2 speedup; if(core.vel.x >= 0) speedup = vec2(core.vel.x*(((float)config.sv_speedup_mult)/10.0)+config.sv_speedup_add,core.vel.y); else speedup = vec2(core.vel.x*(((float)config.sv_speedup_mult)/10.0)-config.sv_speedup_add,core.vel.y); core.vel.x = speedup.x; core.vel.y = speedup.y; } else if(col_is_boostR((int)core.pos.x, core.pos.y) && game.controller->is_race()) { if(core.vel.x >= 0) core.vel.x = core.vel.x*(((float)config.sv_speedup_mult)/10.0)+config.sv_speedup_add; else core.vel.x = config.sv_speedup_add; } else if(col_is_boostL((int)core.pos.x, core.pos.y) && game.controller->is_race()) { if(core.vel.x <= 0) core.vel.x = core.vel.x*(((float)config.sv_speedup_mult)/10.0)-config.sv_speedup_add; else core.vel.x = 0-config.sv_speedup_add; } else if(col_is_boostV((int)core.pos.x, core.pos.y) && game.controller->is_race()) { if(core.vel.y >= 0) core.vel.y = core.vel.y+config.sv_gravity_add; else core.vel.y = core.vel.y-config.sv_jumper_add; } if(col_get_admin((int)pos.x, (int)pos.y)){ if(player->authed) { //do nothing } else { die(player->client_id, WEAPON_WORLD); game.send_chat_target(player->client_id, "Only for Admins."); } } if(col_get_wlist((int)pos.x, (int)pos.y)){ if(player->wlist) { //do nothing } else { die(player->client_id, WEAPON_WORLD); game.send_chat_target(player->client_id, "Only for Whitelist."); } } if(col_get_vip((int)pos.x, (int)pos.y)){ if(player->vip || player->authed) { //do nothing } else { die(player->client_id, WEAPON_WORLD); game.send_chat_target(player->client_id, "Only for VIP."); } } if(col_get_police((int)pos.x, (int)pos.y)){ if(player->police || player->authed) { //do nothing } else { die(player->client_id, WEAPON_WORLD); game.send_chat_target(player->client_id, "Only for Police."); } } if(player->money_save>=750) { player->account->update(); player->money_save = 0; } if(col_get_money1((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 1; player->money += 1; } if(player->vip) { player->money_save += 1; player->money += 1; } player->money += 1; player->money_save += 1; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[1]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_money2((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 2; player->money += 2; } if(player->vip) { player->money_save += 2; player->money += 2; } player->money += 2; player->money_save += 2; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[2]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_money5((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 5; player->money += 5; } if(player->vip) { player->money_save += 5; player->money += 5; } player->money += 5; player->money_save += 5; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[5]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_money10((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 10; player->money += 10; } if(player->vip) { player->money_save += 10; player->money += 10; } player->money += 10; player->money_save += 10; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[10]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_money20((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 20; player->money += 20; } if(player->vip) { player->money_save += 20; player->money += 20; } player->money += 20; player->money_save += 20; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[20]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_money50((int)pos.x, (int)pos.y)){ player->money_tick += 1; if(player->money_tick >= server_tickspeed()) { if(player->wlist) { player->money_save += 50; player->money += 50; } if(player->vip) { player->money_save += 50; player->money += 50; } player->money += 50; player->money_save += 50; player->money_tick = 0; } char buf[128]; str_format(buf, sizeof(buf), "[50]--Your Money: %d$", player->money); game.send_broadcast(buf, player->client_id); } if(col_get_ninjafly((int)pos.x, (int)pos.y) && !player->authed) { player->ninjalol = 1; weapons[WEAPON_NINJA].got = true; weapons[WEAPON_NINJA].ammo = -1; last_weapon = active_weapon; active_weapon = WEAPON_NINJA; } else if(col_is_gravity((int)core.pos.x, core.pos.y) && game.controller->is_race()) core.vel.y = core.vel.y+config.sv_gravity_add; else if(col_is_jumper((int)core.pos.x, core.pos.y) && game.controller->is_race()) core.vel.y = core.vel.y-config.sv_jumper_add; z = col_is_teleport(pos.x, pos.y); if(config.sv_teleport && z && game.controller->is_race()) { if(player->authed) { //do nothing } else { core.hooked_player = -1; core.hook_state = HOOK_RETRACTED; core.triggered_events |= COREEVENT_HOOK_RETRACT; core.hook_state = HOOK_RETRACTED; core.hook_pos = core.pos; } core.pos = teleport(z); if(config.sv_teleport_strip) { active_weapon = WEAPON_HAMMER; last_weapon = WEAPON_HAMMER; weapons[0].got = true; for(int i = 1; i < 5; i++) weapons[i].got = false; } } float phys_size = 28.0f; // handle death-tiles if(col_get((int)(pos.x+phys_size/2), (int)(pos.y-phys_size/2))&COLFLAG_DEATH || col_get((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2))&COLFLAG_DEATH || col_get((int)(pos.x-phys_size/2), (int)(pos.y-phys_size/2))&COLFLAG_DEATH || col_get((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2))&COLFLAG_DEATH) { die(player->client_id, WEAPON_WORLD); } // handle weapons handle_weapons(); player_state = input.player_state; // Previnput previnput = input; oldpos = core.pos; return; }
void CHARACTER::tick_defered() { // advance the dummy { WORLD_CORE tempworld; reckoningcore.world = &tempworld; reckoningcore.tick(false); reckoningcore.move(); reckoningcore.quantize(); } //lastsentcore; /*if(!dead) {*/ vec2 start_pos = core.pos; vec2 start_vel = core.vel; bool stuck_before = test_box(core.pos, vec2(28.0f, 28.0f)); core.move(); if(is_hitting_door()) { reset_pos(); if(is_hitting_door() && !doorstuck) { game.send_emoticon(player->client_id, 11); doorstuck = true; } } else doorstuck = false; bool stuck_after_move = test_box(core.pos, vec2(28.0f, 28.0f)); core.quantize(); bool stuck_after_quant = test_box(core.pos, vec2(28.0f, 28.0f)); pos = core.pos; if(!stuck_before && (stuck_after_move || stuck_after_quant)) { dbg_msg("player", "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x", stuck_before, stuck_after_move, stuck_after_quant, start_pos.x, start_pos.y, start_vel.x, start_vel.y, *((unsigned *)&start_pos.x), *((unsigned *)&start_pos.y), *((unsigned *)&start_vel.x), *((unsigned *)&start_vel.y)); } int events = core.triggered_events; int mask = cmask_all_except_one(player->client_id); if(events&COREEVENT_GROUND_JUMP) game.create_sound(pos, SOUND_PLAYER_JUMP, mask); //if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos); if(events&COREEVENT_HOOK_ATTACH_PLAYER) game.create_sound(pos, SOUND_HOOK_ATTACH_PLAYER, cmask_all()); if(events&COREEVENT_HOOK_ATTACH_GROUND) game.create_sound(pos, SOUND_HOOK_ATTACH_GROUND, mask); if(events&COREEVENT_HOOK_HIT_NOHOOK) game.create_sound(pos, SOUND_HOOK_NOATTACH, mask); //if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos); //} if(team == -1) { pos.x = input.target_x; pos.y = input.target_y; } // update the sendcore if needed { NETOBJ_CHARACTER predicted; NETOBJ_CHARACTER current; mem_zero(&predicted, sizeof(predicted)); mem_zero(¤t, sizeof(current)); reckoningcore.write(&predicted); core.write(¤t); // only allow dead reackoning for a top of 3 seconds if(reckoning_tick+server_tickspeed()*3 < server_tick() || mem_comp(&predicted, ¤t, sizeof(NETOBJ_CHARACTER)) != 0) { reckoning_tick = server_tick(); sendcore = core; reckoningcore = core; } } }
bool BUILDING::take_damage(vec2 force, int dmg, int from, int weapon) { if(from >= 0 && game.players[from] && game.players[from]->team == team && !config.sv_buildings_ff) //No friendly fire D= return false; if(from >= 0 && game.players[from] && game.players[from]->get_character() && game.players[from]->get_character()->damage_buff) { dmg += 1; } damage_taken++; // create healthmod indicator if(server_tick() < damage_taken_tick+25 && !decon) { // make sure that the damage indicators doesn't group together game.create_damageind(pos, damage_taken*0.25f, dmg); } else if(!decon) { damage_taken = 0; game.create_damageind(pos, 0, dmg); } if(dmg) { health -= dmg; } damage_taken_tick = server_tick(); if(damage_tick+150 < server_tick()) { damage_tick = server_tick(); if(health < maxhealth / 4) { if(type == B_REACTOR) { int target = GAMECONTEXT::CHAT_RED; if(team == 1) target = GAMECONTEXT::CHAT_BLUE; game.send_chat(-1, target, "The reactor is badly damaged!"); } } else { if(type == B_REACTOR) { int target = GAMECONTEXT::CHAT_RED; if(team == 1) target = GAMECONTEXT::CHAT_BLUE; game.send_chat(-1, target, "The reactor is under attack!"); } } } // do damage hit sound if(from >= 0 && game.players[from]) { game.create_sound(game.players[from]->view_pos, SOUND_HIT, cmask_one(from)); if(game.players[from]->team != team) game.players[from]->rage = min(100, game.players[from]->rage+dmg*config.sv_rage_modifier); else game.players[from]->rage = max(0, game.players[from]->rage-dmg*config.sv_rage_modifier); } // check for death if(health <= 0) { die(from, weapon); // set attacker's face to happy (taunt!) if (from >= 0 && game.players[from]) { CHARACTER *chr = game.players[from]->get_character(); if (chr && game.players[from]->team != team) { chr->emote_type = EMOTE_HAPPY; chr->emote_stop = server_tick() + server_tickspeed(); } } return false; } return true; }
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() ; } } }
void mods_message(int msgtype, int client_id) { void *rawmsg = netmsg_secure_unpack(msgtype); PLAYER *p = game.players[client_id]; if(!rawmsg) { dbg_msg("server", "dropped weird message '%s' (%d), failed on '%s'", netmsg_get_name(msgtype), msgtype, netmsg_failed_on()); return; } if(msgtype == NETMSGTYPE_CL_SAY) { NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg; int team = msg->team; if(team) team = p->team; else team = GAMECONTEXT::CHAT_ALL; if(config.sv_spamprotection && p->last_chat+time_freq() > time_get()) { if(!strcmp(msg->message, "/rank") && game.controller->is_race()) game.players[client_id]->last_chat = time_get()+time_freq()*10; else game.players[client_id]->last_chat = time_get(); } else { game.players[client_id]->last_chat = time_get(); if(!strcmp(msg->message, "/info")) { char buf[128]; str_format(buf, sizeof(buf), "DJUMP 0.32 from EliteKuchen.", RACE_VERSION); game.send_chat_target(client_id, buf); str_format(buf, sizeof(buf), "based on : Race mod %s from Rajh and Redix.", RACE_VERSION); game.send_chat_target(client_id, buf); } else if(!strncmp(msg->message, "/top5", 5) && game.controller->is_race()) { const char *pt = msg->message; int number = 0; pt += 6; while(*pt && *pt >= '0' && *pt <= '9') { number = number*10+(*pt-'0'); pt++; } if(number) ((GAMECONTROLLER_RACE*)game.controller)->score.top5_draw(client_id, number); else ((GAMECONTROLLER_RACE*)game.controller)->score.top5_draw(client_id, 0); } else if(!strncmp(msg->message, "/rank", 5) && game.controller->is_race()) { char buf[512]; const char *name = msg->message; name += 6; int pos; PLAYER_SCORE *pscore; if(!strcmp(msg->message, "/rank")) pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_score(client_id, 1, &pos); else pscore = ((GAMECONTROLLER_RACE*)game.controller)->score.search_name(name, &pos, 1); if(pscore && pos > -1) { int punkte = pscore->points; char client_name[128]; str_format(client_name, sizeof(client_name), " (%s)", server_clientname(client_id)); str_format(buf, sizeof(buf), "%d. %s Points:%d", pos, pscore->name, punkte); if(strcmp(msg->message, "/rank")) strcat(buf, client_name); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); game.players[client_id]->last_chat = time_get()+time_freq()*3; return; } else if(pos == -1) str_format(buf, sizeof(buf), "Several players were found."); else str_format(buf, sizeof(buf), "%s is not ranked", strcmp(msg->message, "/rank")?name:server_clientname(client_id)); game.send_chat_target(client_id, buf); } else if(!strcmp(msg->message, "/cmdlist")) { game.send_chat_target(client_id, "---Command List---"); game.send_chat_target(client_id, "\"/info\" information about the mod"); game.send_chat_target(client_id, "\"/rank\" shows your rank"); game.send_chat_target(client_id, "\"/rank NAME\" shows the rank of a specific player"); game.send_chat_target(client_id, "\"/top5 X\" shows the top 5"); } else if(!strncmp(msg->message, "/", 1)) { game.send_chat_target(client_id, "Wrong command."); game.send_chat_target(client_id, "Say \"/cmdlist\" for list of command available."); } else game.send_chat(client_id, team, msg->message); } } else if(msgtype == NETMSGTYPE_CL_CALLVOTE) { int64 now = time_get(); if(game.vote_closetime) { game.send_chat_target(client_id, "Wait for current vote to end before calling a new one."); return; } int64 timeleft = p->last_votecall + time_freq()*60 - now; if(timeleft > 0) { char chatmsg[512] = {0}; str_format(chatmsg, sizeof(chatmsg), "You must wait %d seconds before making another vote", (timeleft/time_freq())+1); game.send_chat_target(client_id, chatmsg); return; } char chatmsg[512] = {0}; char desc[512] = {0}; char cmd[512] = {0}; NETMSG_CL_CALLVOTE *msg = (NETMSG_CL_CALLVOTE *)rawmsg; if(str_comp_nocase(msg->type, "option") == 0) { VOTEOPTION *option = voteoption_first; while(option) { if(str_comp_nocase(msg->value, option->command) == 0) { str_format(chatmsg, sizeof(chatmsg), "%s called vote to change server option '%s'", server_clientname(client_id), option->command); str_format(desc, sizeof(desc), "%s", option->command); str_format(cmd, sizeof(cmd), "%s", option->command); break; } option = option->next; } if(!option) { str_format(chatmsg, sizeof(chatmsg), "'%s' isn't an option on this server", msg->value); game.send_chat_target(client_id, chatmsg); return; } } else if(str_comp_nocase(msg->type, "kick") == 0) { if(!config.sv_vote_kick) { game.send_chat_target(client_id, "Server does not allow voting to kick players"); return; } int kick_id = atoi(msg->value); if(kick_id < 0 || kick_id >= MAX_CLIENTS || !game.players[kick_id]) { game.send_chat_target(client_id, "Invalid client id to kick"); return; } str_format(chatmsg, sizeof(chatmsg), "%s called for vote to kick '%s'", server_clientname(client_id), server_clientname(kick_id)); str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id)); str_format(cmd, sizeof(cmd), "kick %d", kick_id); if (!config.sv_vote_kick_bantime) str_format(cmd, sizeof(cmd), "kick %d", kick_id); else str_format(cmd, sizeof(cmd), "ban %d %d", kick_id, config.sv_vote_kick_bantime); } if(cmd[0]) { game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chatmsg); game.start_vote(desc, cmd); p->vote = 1; game.vote_creator = client_id; p->last_votecall = now; game.send_vote_status(-1); } } else if(msgtype == NETMSGTYPE_CL_VOTE) { if(!game.vote_closetime) return; if(p->vote == 0) { NETMSG_CL_VOTE *msg = (NETMSG_CL_VOTE *)rawmsg; p->vote = msg->vote; game.send_vote_status(-1); } } else if (msgtype == NETMSGTYPE_CL_SETTEAM && !game.world.paused) { NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg; if(p->team == msg->team || (config.sv_spamprotection && p->last_setteam+time_freq()*3 > time_get())) return; // Switch team on given client and kill/respawn him if(game.controller->can_join_team(msg->team, client_id)) { if(game.controller->can_change_team(p, msg->team)) { p->last_setteam = time_get(); p->set_team(msg->team); (void) game.controller->check_team_balance(); } else game.send_broadcast("Teams must be balanced, please join other team", client_id); } else { char buf[128]; str_format(buf, sizeof(buf), "Only %d active players are allowed", config.sv_max_clients-config.sv_spectator_slots); game.send_broadcast(buf, client_id); } } else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO) { NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg; if(config.sv_spamprotection && p->last_changeinfo+time_freq()*5 > time_get()) return; p->last_changeinfo = time_get(); p->use_custom_color = msg->use_custom_color; p->color_body = msg->color_body; p->color_feet = msg->color_feet; // check for invalid chars unsigned char *name = (unsigned char *)msg->name; while (*name) { if(*name < 32) *name = ' '; name++; } // copy old name char oldname[MAX_NAME_LENGTH]; str_copy(oldname, server_clientname(client_id), MAX_NAME_LENGTH); server_setclientname(client_id, msg->name); if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(oldname, server_clientname(client_id)) != 0) { char chattext[256]; str_format(chattext, sizeof(chattext), "%s changed name to %s", oldname, server_clientname(client_id)); game.send_chat(-1, GAMECONTEXT::CHAT_ALL, chattext); } // set skin str_copy(p->skin_name, msg->skin, sizeof(p->skin_name)); game.controller->on_player_info_change(p); if(msgtype == NETMSGTYPE_CL_STARTINFO) { // send vote options NETMSG_SV_VOTE_CLEAROPTIONS clearmsg; clearmsg.pack(MSGFLAG_VITAL); server_send_msg(client_id); VOTEOPTION *current = voteoption_first; while(current) { NETMSG_SV_VOTE_OPTION optionmsg; optionmsg.command = current->command; optionmsg.pack(MSGFLAG_VITAL); server_send_msg(client_id); current = current->next; } // send tuning parameters to client send_tuning_params(client_id); // NETMSG_SV_READYTOENTER m; m.pack(MSGFLAG_VITAL|MSGFLAG_FLUSH); server_send_msg(client_id); } } else if (msgtype == NETMSGTYPE_CL_EMOTICON && !game.world.paused) { NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg; if(config.sv_spamprotection && p->last_emote+time_freq()*3 > time_get()) return; p->last_emote = time_get(); game.send_emoticon(client_id, msg->emoticon); } else if (msgtype == NETMSGTYPE_CL_KILL && !game.world.paused) { if(p->last_kill+time_freq()*3 > time_get()) return; p->last_kill = time_get(); p->kill_character(WEAPON_SELF); p->respawn_tick = server_tick()+server_tickspeed()*3; if(game.controller->is_race()) p->respawn_tick = server_tick(); } }