// TODO: rewrite this smarter! int col_intersect_line(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision) { float d = distance(pos0, pos1); vec2 last = pos0; for(float f = 0; f < d; f++) { float a = f/d; vec2 pos = mix(pos0, pos1, a); if(col_is_solid(round(pos.x), round(pos.y))) { if(out_collision) *out_collision = pos; if(out_before_collision) *out_before_collision = last; return col_get(round(pos.x), round(pos.y)); } last = pos; } if(out_collision) *out_collision = pos1; if(out_before_collision) *out_before_collision = pos1; return 0; }
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 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; }
int col_is_solid(int x, int y) { return col_get(x,y)&COLFLAG_SOLID; }
void CRATE::tick() { 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(); return; } grounded = is_grounded(); bool was_grounded = grounded; if(!grounded) { //die(); int k = 3; while(!grounded && k-- > 0) { pos.y += 1; grounded = is_grounded(); } } if(grounded && !was_grounded) game.create_sound(pos, SOUND_CRATE_IMPACT); was_grounded = grounded; if(!alive) return; CHARACTER *c = get_nearest(28); GAMECONTROLLER_NODES* gc = (GAMECONTROLLER_NODES*)game.controller; if(c) { dbg_msg("nodes", "activated a crate of type %d", type); char buf[128]; str_format(buf, sizeof(buf), "%s", BUF_NAMES[type]); game.send_broadcast(buf, c->player->client_id); switch(type) { //c->crate = type; //c->crate_tick = server_tick(); case CRATE_HEALTH: { c->health = 10; game.create_sound(pos, SOUND_PICKUP_HEALTH); } break; case CRATE_ARMOR: { c->armor = 10; game.create_sound(pos, SOUND_PICKUP_ARMOR); } break; case CRATE_CONSTRUCTION: { c->crate = CRATE_CONSTRUCTION; c->crate_tick = server_tick(); c->core.frozen = false; /*if(gc->buildings_buffpoints[1-c->team] > 0) { gc->buildings_points[1-c->team] -= gc->buildings_buffpoints[1-c->team]; gc->buildings_buffpoints[1-c->team] = 0; } if(gc->buildings_buffpoints[c->team] == 0) { gc->buildings_points[c->team] += config.sv_buffpoints; gc->buildings_buffpoints[c->team] = config.sv_buffpoints; }*/ } break; case CRATE_BASEBALL: { c->crate = CRATE_BASEBALL; c->crate_tick = server_tick(); c->core.frozen = false; c->active_weapon = WEAPON_HAMMER; } break; case CRATE_FREEZE: { c->crate = 0; //undo crate thingy, only enemies will get this "buff" c->core.frozen = false; CHARACTER *close_characters[MAX_CLIENTS]; int num = game.world.find_entities(c->pos, config.sv_freeze_radius, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); for(int i = 0; i < num; i++) { if(close_characters[i]->player->team != c->player->team) { close_characters[i]->core.frozen = true; close_characters[i]->crate = CRATE_FREEZE; close_characters[i]->crate_tick = server_tick(); close_characters[i]->crate_misc = (int)(frandom() *2); game.create_sound(close_characters[i]->pos, SOUND_CRATE_ICE); } } game.create_sound(pos, SOUND_CRATE_ICE); game.create_effect(pos, 3); } break; case CRATE_EMP: { gc->emp = true; gc->emp_tick = server_tick(); game.create_effect(pos, 2); game.create_sound_global(SOUND_CRATE_EMP, -1); } break; case CRATE_DUCK: { c->core.frozen = true; //c->ill = true; c->crate = CRATE_FREEZE; c->crate_tick = server_tick(); c->crate_misc = (int)(frandom() *2); c->core.hook_state = -1; c->core.hooked_player = -1; game.create_sound(pos, SOUND_CRATE_ICE); } break; case CRATE_BOOM: { game.create_explosion(pos, -4, WEAPON_WORLD, false); game.create_explosion(pos, -4, WEAPON_WORLD, false); game.create_explosion(pos, -4, WEAPON_WORLD, false); game.create_sound(pos, SOUND_GRENADE_EXPLODE); } /*case CRATE_EXPLOSION: { game.create_explosion(pos, -1, WEAPON_WORLD, false); game.create_explosion(pos, -1, WEAPON_WORLD, false); game.create_explosion(pos, -1, WEAPON_WORLD, false); } break; case CRATE_ILLNESS: { c->ill = true; c->infecter = -1; } break; case CRATE_NOGRAV: { c->core.nograv = true; } break; case CRATE_FREEZE: { c->core.frozen = true; } break; case CRATE_STRIP: { c->weapons[WEAPON_GUN].got = 0; c->weapons[WEAPON_GRENADE].got = 0; c->weapons[WEAPON_RIFLE].got = 0; } case CRATE_HEALTH: { c->health = 10; } break; case CRATE_ARMOR: { c->armor = 10; } case CRATE_AMMO: { c->weapons[WEAPON_GUN].ammo = 10; c->weapons[WEAPON_GRENADE].ammo = 10; c->weapons[WEAPON_RIFLE].ammo = 10; } case CRATE_WEAPONS: { c->weapons[WEAPON_GUN].got = 1; c->weapons[WEAPON_GRENADE].got = 1; c->weapons[WEAPON_RIFLE].got = 1; }*/ } die(); return; } if(server_tick() > creation_tick + 20*50) { game.create_explosion(pos, -1, WEAPON_WORLD, true); game.create_sound(pos, SOUND_GRENADE_EXPLODE); die(); } return; }