void MENUS::render_background() { //gfx_clear(1,1,1); //render_sunrays(0,0); if(texture_blob == -1) texture_blob = gfx_load_texture("blob.png", IMG_AUTO, 0); float sw = 300*gfx_screenaspect(); float sh = 300; gfx_mapscreen(0, 0, sw, sh); RECT s = *ui_screen(); // render background color gfx_texture_set(-1); gfx_quads_begin(); //vec4 bottom(gui_color.r*0.3f, gui_color.g*0.3f, gui_color.b*0.3f, 1.0f); //vec4 bottom(0, 0, 0, 1.0f); vec4 bottom(gui_color.r, gui_color.g, gui_color.b, 1.0f); vec4 top(gui_color.r, gui_color.g, gui_color.b, 1.0f); gfx_setcolorvertex(0, top.r, top.g, top.b, top.a); gfx_setcolorvertex(1, top.r, top.g, top.b, top.a); gfx_setcolorvertex(2, bottom.r, bottom.g, bottom.b, bottom.a); gfx_setcolorvertex(3, bottom.r, bottom.g, bottom.b, bottom.a); gfx_quads_drawTL(0, 0, sw, sh); gfx_quads_end(); // render the tiles gfx_texture_set(-1); gfx_quads_begin(); float size = 15.0f; float offset_time = fmod(client_localtime()*0.15f, 2.0f); for(int y = -2; y < (int)(sw/size); y++) for(int x = -2; x < (int)(sh/size); x++) { gfx_setcolor(0,0,0,0.045f); gfx_quads_drawTL((x-offset_time)*size*2+(y&1)*size, (y+offset_time)*size, size, size); } gfx_quads_end(); // render border fade gfx_texture_set(texture_blob); gfx_quads_begin(); gfx_setcolor(0,0,0,0.5f); gfx_quads_drawTL(-100, -100, sw+200, sh+200); gfx_quads_end(); // restore screen {RECT screen = *ui_screen(); gfx_mapscreen(screen.x, screen.y, screen.w, screen.h);} }
void ITEMS::render_pickup(const NETOBJ_PICKUP *prev, const NETOBJ_PICKUP *current) { gfx_texture_set(data->images[IMAGE_GAME].id); gfx_quads_begin(); vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); float angle = 0.0f; float size = 64.0f; if (current->type == POWERUP_WEAPON) { angle = 0; //-pi/6;//-0.25f * pi * 2.0f; select_sprite(data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].sprite_body); size = data->weapons.id[clamp(current->subtype, 0, NUM_WEAPONS-1)].visual_size; } else { const int c[] = { SPRITE_PICKUP_HEALTH, SPRITE_PICKUP_ARMOR, SPRITE_PICKUP_WEAPON, SPRITE_PICKUP_NINJA }; select_sprite(c[current->type]); if(c[current->type] == SPRITE_PICKUP_NINJA) { gameclient.effects->powerupshine(pos, vec2(96,18)); size *= 2.0f; pos.x += 10.0f; } } gfx_quads_setrotation(angle); float offset = pos.y/32.0f + pos.x/32.0f; pos.x += cosf(client_localtime()*2.0f+offset)*2.5f; pos.y += sinf(client_localtime()*2.0f+offset)*2.5f; draw_sprite(pos.x, pos.y, size); gfx_quads_end(); }
int CONTROLS::snapinput(int *data) { static NETOBJ_PLAYER_INPUT last_data = {0}; static int64 last_send_time = 0; bool send = false; // update player state if(gameclient.chat->is_active()) input_data.player_state = PLAYERSTATE_CHATTING; else if(gameclient.menus->is_active()) input_data.player_state = PLAYERSTATE_IN_MENU; else input_data.player_state = PLAYERSTATE_PLAYING; if(last_data.player_state != input_data.player_state) send = true; last_data.player_state = input_data.player_state; // we freeze the input if chat or menu is activated if(input_data.player_state != PLAYERSTATE_PLAYING) { last_data.direction = 0; last_data.hook = 0; last_data.jump = 0; input_data = last_data; input_direction_left = 0; input_direction_right = 0; mem_copy(data, &input_data, sizeof(input_data)); // send once a second just to be sure if(time_get() > last_send_time + time_freq()) send = true; } else { input_data.target_x = (int)mouse_pos.x; input_data.target_y = (int)mouse_pos.y; if(!input_data.target_x && !input_data.target_y) input_data.target_y = 1; // set direction input_data.direction = 0; if(input_direction_left && !input_direction_right) input_data.direction = -1; if(!input_direction_left && input_direction_right) input_data.direction = 1; // stress testing if(config.dbg_stress) { float t = client_localtime(); mem_zero(&input_data, sizeof(input_data)); input_data.direction = ((int)t/2)&1; input_data.jump = ((int)t); input_data.fire = ((int)(t*10)); input_data.hook = ((int)(t*2))&1; input_data.wanted_weapon = ((int)t)%NUM_WEAPONS; input_data.target_x = (int)(sinf(t*3)*100.0f); input_data.target_y = (int)(cosf(t*3)*100.0f); } // check if we need to send input if(input_data.direction != last_data.direction) send = true; else if(input_data.jump != last_data.jump) send = true; else if(input_data.fire != last_data.fire) send = true; else if(input_data.hook != last_data.hook) send = true; else if(input_data.player_state != last_data.player_state) send = true; else if(input_data.wanted_weapon != last_data.wanted_weapon) send = true; else if(input_data.next_weapon != last_data.next_weapon) send = true; else if(input_data.prev_weapon != last_data.prev_weapon) send = true; // send at at least 10hz if(time_get() > last_send_time + time_freq()/25) send = true; } // copy and return size last_data = input_data; if(!send) return 0; last_send_time = time_get(); mem_copy(data, &input_data, sizeof(input_data)); return sizeof(input_data); }
void ITEMS::render_projectile(const NETOBJ_PROJECTILE *current, int itemid) { // get positions float curvature = 0; float speed = 0; if(current->type == WEAPON_GRENADE) { curvature = gameclient.tuning.grenade_curvature; speed = gameclient.tuning.grenade_speed; } else if(current->type == WEAPON_SHOTGUN) { curvature = gameclient.tuning.shotgun_curvature; speed = gameclient.tuning.shotgun_speed; } else if(current->type == WEAPON_GUN) { curvature = gameclient.tuning.gun_curvature; speed = gameclient.tuning.gun_speed; } float ct = (client_prevtick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime(); if(ct < 0) return; // projectile havn't been shot yet vec2 startpos(current->x, current->y); vec2 startvel(current->vx/100.0f, current->vy/100.0f); vec2 pos = calc_pos(startpos, startvel, curvature, speed, ct); vec2 prevpos = calc_pos(startpos, startvel, curvature, speed, ct-0.001f); gfx_texture_set(data->images[IMAGE_GAME].id); gfx_quads_begin(); select_sprite(data->weapons.id[clamp(current->type, 0, NUM_WEAPONS-1)].sprite_proj); vec2 vel = pos-prevpos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick()); // add particle for this projectile if(current->type == WEAPON_GRENADE) { gameclient.effects->smoketrail(pos, vel*-1); gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f); gfx_quads_setrotation(client_localtime()*pi*2*2 + itemid); } else { gameclient.effects->bullettrail(pos); gameclient.flow->add(pos, vel*1000*client_frametime(), 10.0f); if(length(vel) > 0.00001f) gfx_quads_setrotation(get_angle(vel)); else gfx_quads_setrotation(0); } gfx_quads_draw(pos.x, pos.y, 32, 32); ///--- Added by Tigra // Draw shadows of grenades bool local_player_in_game = gameclient.clients[gameclient.snap.local_cid].team != -1; if(config.cl_antiping && current->type == WEAPON_GRENADE && local_player_in_game) { // Calculate average prediction offset, because client_predtick() gets varial values :((( // Must be there is a normal way to realize it, but I'm too lazy to find it. ^) if (gameclient.average_prediction_offset == -1) { int offset = client_predtick() - client_tick(); gameclient.prediction_offset_summ += offset; gameclient.prediction_offset_count++; if (gameclient.prediction_offset_count >= 100) { gameclient.average_prediction_offset = round((float)gameclient.prediction_offset_summ / gameclient.prediction_offset_count); } } // Draw shadow only if grenade directed to local player int local_cid = gameclient.snap.local_cid; NETOBJ_CHARACTER& cur_char = gameclient.snap.characters[local_cid].cur; NETOBJ_CHARACTER& prev_char = gameclient.snap.characters[local_cid].prev; vec2 server_pos = mix(vec2(prev_char.x, prev_char.y), vec2(cur_char.x, cur_char.y), client_intratick()); float d1 = distance(pos, server_pos); float d2 = distance(prevpos, server_pos); if (d1 < 0) d1 *= -1; if (d2 < 0) d2 *= -1; bool grenade_directed_to_local_player = d1 < d2; if (gameclient.average_prediction_offset != -1 && grenade_directed_to_local_player) { int predicted_tick = client_prevtick() + gameclient.average_prediction_offset; float predicted_ct = (predicted_tick - current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime(); if (predicted_ct >= 0) { int shadow_type = WEAPON_GUN; // Pistol bullet sprite is used for marker of shadow. TODO: use something custom. select_sprite(data->weapons.id[clamp(shadow_type, 0, NUM_WEAPONS-1)].sprite_proj); vec2 predicted_pos = calc_pos(startpos, startvel, curvature, speed, predicted_ct); gfx_quads_draw(predicted_pos.x, predicted_pos.y, 32, 32); } } } ///--- gfx_quads_setrotation(0); gfx_quads_end(); }
int CONTROLS::snapinput(int *data) { static NETOBJ_PLAYER_INPUT last_data = {0}; static int64 last_send_time = 0; bool send = false; // update player state if(gameclient.chat->is_active()) input_data.player_state = PLAYERSTATE_CHATTING; else if(gameclient.menus->is_active()) input_data.player_state = PLAYERSTATE_IN_MENU; else input_data.player_state = PLAYERSTATE_PLAYING; if(last_data.player_state != input_data.player_state) send = true; last_data.player_state = input_data.player_state; // we freeze the input if chat or menu is activated if(input_data.player_state != PLAYERSTATE_PLAYING) { last_data.direction = 0; last_data.hook = 0; last_data.jump = 0; input_data = last_data; input_direction_left = 0; input_direction_right = 0; mem_copy(data, &input_data, sizeof(input_data)); // send once a second just to be sure if(time_get() > last_send_time + time_freq()) send = true; } else { input_data.target_x = (int)mouse_pos.x; input_data.target_y = (int)mouse_pos.y; if(!input_data.target_x && !input_data.target_y) input_data.target_y = 1; // set direction input_data.direction = 0; if(input_direction_left && !input_direction_right) input_data.direction = -1; if(!input_direction_left && input_direction_right) input_data.direction = 1; // stress testing if(config.dbg_stress) { float t = client_localtime(); mem_zero(&input_data, sizeof(input_data)); input_data.direction = ((int)t/2)&1; input_data.jump = ((int)t); input_data.fire = ((int)(t*10)); input_data.hook = ((int)(t*2))&1; input_data.wanted_weapon = ((int)t)%NUM_WEAPONS; input_data.target_x = (int)(sinf(t*3)*100.0f); input_data.target_y = (int)(cosf(t*3)*100.0f); } /////////////////////////////////// THIS IS MY IA BITCH DON'T TOUCH static AI *ai = NULL; if(!ai) { dbg_msg("ia", "Initializing AI"); ooc_ai_load(); ai = getAI(); } struct GameInfo info; info.time = client_localtime(); info.localCid = gameclient.snap.local_cid; info.numPlayers = gameclient.snap.num_players; info.playerInfos = gameclient.snap.player_infos; info.pos.x = gameclient.local_character_pos.x; info.pos.y = gameclient.local_character_pos.y; info.mouse.x = mouse_pos.x; info.mouse.y = mouse_pos.y; info.target.x = input_data.target_x; info.target.y = input_data.target_y; info.numChars = gameclient.numChars; info.chars = gameclient.chars; struct Answer answer = AI__AI_step(ai, info); uint32_t action = answer.action; //dbg_msg("ia", "got action = %x", action); input_data.jump = (action & Actions_JUMP); if(action & Actions_LEFT) input_data.direction = -1; if(action & Actions_RIGHT) input_data.direction = 1; if(action & Actions_FIRE) input_data.fire++; if(answer.target) { input_data.target_x = answer.target->x; input_data.target_y = answer.target->y; } if(answer.mouse) { mouse_pos.x = answer.mouse->x; mouse_pos.y = answer.mouse->y; } if(answer.nextWeapon) { console_execute_line_stroked(1, "+nextweapon"); } if(answer.prevWeapon) { console_execute_line_stroked(1, "+prevweapon"); } if(answer.wantedWeapon != 0) { switch (answer.wantedWeapon) { case 1: console_execute_line_stroked(1, "+weapon1"); break; case 2: console_execute_line_stroked(1, "+weapon2"); break; case 3: console_execute_line_stroked(1, "+weapon3"); break; case 4: console_execute_line_stroked(1, "+weapon4"); break; case 5: console_execute_line_stroked(1, "+weapon5"); break; } } input_data.hook = (action & Actions_HOOK); /////////////////////////////////// THIS IS MY IA BITCH DON'T TOUCH //================ TEH HACK BEGINS HERE !!! ========================== /* static double cdown = 100; static bool jjump = true; jjump = !jjump; cdown++; if(rand() % 50 == 10){ mouse_pos.x = cos(rand() % 100) * 100 + 50; mouse_pos.y = sin(rand() % 100) * 100 + 50; } if(rand() % 30 == 10){ input_data.jump = true; }else{ input_data.jump = false; } if(rand() % 40 == 10){ input_data.fire = 1; } if(rand() % 40 == 10){ input_data.fire = 0; } //dbg_msg("ai","diff: %f",target_pos.x - char_posx); if(target_pos.x - char_posx > 0){ input_data.direction = 1; } else if(abs(target_pos.x - char_posx) < 15){ input_data.direction = 0; } else{ input_data.direction = -1; } */ //================================================================== // check if we need to send input if(input_data.direction != last_data.direction) send = true; else if(input_data.jump != last_data.jump) send = true; else if(input_data.fire != last_data.fire) send = true; else if(input_data.hook != last_data.hook) send = true; else if(input_data.player_state != last_data.player_state) send = true; else if(input_data.wanted_weapon != last_data.wanted_weapon) send = true; else if(input_data.next_weapon != last_data.next_weapon) send = true; else if(input_data.prev_weapon != last_data.prev_weapon) send = true; // send at at least 10hz if(time_get() > last_send_time + time_freq()/25) send = true; } // copy and return size last_data = input_data; if(!send) return 0; last_send_time = time_get(); mem_copy(data, &input_data, sizeof(input_data)); return sizeof(input_data); }