示例#1
0
void PLAYERS::render_player(
	const NETOBJ_CHARACTER *prev_char,
	const NETOBJ_CHARACTER *player_char,
	const NETOBJ_PLAYER_INFO *prev_info,
	const NETOBJ_PLAYER_INFO *player_info
	)
{
	NETOBJ_CHARACTER prev;
	NETOBJ_CHARACTER player;
	prev = *prev_char;
	player = *player_char;

	NETOBJ_PLAYER_INFO info = *player_info;
	TEE_RENDER_INFO render_info = gameclient.clients[info.cid].render_info;

	// check for teamplay modes
	bool new_tick = gameclient.new_tick;

	// check for ninja	
	if ( player.weapon == WEAPON_NINJA ) {
		// change the skin for the player to the ninja
		int skin = gameclient.skins->find("x_ninja");
		
		if (skin != -1) {
			render_info.texture = gameclient.skins->get( skin )->org_texture;
			render_info.color_body = vec4( 1,1,1,1 );
			render_info.color_feet = vec4( 1,1,1,1 );
		}	
	}
	
	// set size
	render_info.size = 64.0f;

	float intratick = client_intratick();
	
	if(player.health < 0) // dont render dead players
		return;

	float angle = mix((float)prev.angle, (float)player.angle, intratick)/256.0f;
	
	//float angle = 0;
	
	// just use the direct input if it's local player we are rendering
	if(info.local && client_state() != CLIENTSTATE_DEMOPLAYBACK)
		angle = get_angle(gameclient.controls->mouse_pos);
	
	// use preditect players if needed
	if(info.local && config.cl_predict && client_state() != CLIENTSTATE_DEMOPLAYBACK)
	{
		if ( gameclient.snap.local_character && ( gameclient.snap.local_character->health >= 0 ) ) {
			// apply predicted results
			gameclient.predicted_char.write(&player);
			gameclient.predicted_prev_char.write(&prev);
			intratick = client_predintratick();
			new_tick = gameclient.new_predicted_tick;
		}
	}
	
	vec2 direction = get_direction((int)(angle*256.0f));
	vec2 position = mix(vec2(prev.x, prev.y), vec2(player.x, player.y), intratick);
	vec2 vel = mix(vec2(prev.vx/256.0f, prev.vy/256.0f), vec2(player.vx/256.0f, player.vy/256.0f), intratick);
	
	gameclient.flow->add(position, vel*100.0f, 10.0f);
	
	render_info.got_airjump = player.jumped&2?0:1;
	
	
	// detect events
	if(new_tick)
	{
		// detect air jump
		if(!render_info.got_airjump && !(prev.jumped&2))
			gameclient.effects->air_jump(position);
	}

	if(prev.health < 0) // Don't flicker from previous position
		position = vec2(player.x, player.y);

	bool stationary = player.vx < 1 && player.vx > -1;
	bool inair = col_check_point(player.x, player.y+16) == 0;
	bool want_other_dir = (player.direction == -1 && vel.x > 0) || (player.direction == 1 && vel.x < 0);

	// evaluate animation
	float walk_time = fmod(position.x, 100.0f)/100.0f;
	ANIMSTATE state;
	state.set(&data->animations[ANIM_BASE], 0);

	if(inair)
		state.add(&data->animations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
	else if(stationary)
		state.add(&data->animations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
	else if(!want_other_dir)
		state.add(&data->animations[ANIM_WALK], walk_time, 1.0f);

	if (player.weapon == WEAPON_HAMMER)
	{
		float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime();
		state.add(&data->animations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f);
	}
	if (player.weapon == WEAPON_NINJA)
	{
		float ct = (client_prevtick()-player.attacktick)/(float)SERVER_TICK_SPEED + client_ticktime();
		state.add(&data->animations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f);
	}
	
	// do skidding
	if(!inair && want_other_dir && length(vel*50) > 500.0f)
	{
		static int64 skid_sound_time = 0;
		if(time_get()-skid_sound_time > time_freq()/10)
		{
			gameclient.sounds->play(SOUNDS::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, position);
			skid_sound_time = time_get();
		}
		
		gameclient.effects->skidtrail(
			position+vec2(-player.direction*6,12),
			vec2(-player.direction*100*length(vel),-50)
		);
	}

	// draw hook
	if (prev.hook_state>0 && player.hook_state>0)
	{
		gfx_texture_set(data->images[IMAGE_GAME].id);
		gfx_quads_begin();
		//gfx_quads_begin();

		vec2 pos = position;
		vec2 hook_pos;
		
		if(player_char->hooked_player != -1)
		{
			if(gameclient.snap.local_info && player_char->hooked_player == gameclient.snap.local_info->cid)
			{
				hook_pos = mix(vec2(gameclient.predicted_prev_char.pos.x, gameclient.predicted_prev_char.pos.y),
					vec2(gameclient.predicted_char.pos.x, gameclient.predicted_char.pos.y), client_predintratick());
			}
			else
				hook_pos = mix(vec2(prev_char->hook_x, prev_char->hook_y), vec2(player_char->hook_x, player_char->hook_y), client_intratick());
		}
		else
			hook_pos = mix(vec2(prev.hook_x, prev.hook_y), vec2(player.hook_x, player.hook_y), intratick);

		float d = distance(pos, hook_pos);
		vec2 dir = normalize(pos-hook_pos);

		gfx_quads_setrotation(get_angle(dir)+pi);

		// render head
		select_sprite(SPRITE_HOOK_HEAD);
		gfx_quads_draw(hook_pos.x, hook_pos.y, 24,16);

		// render chain
		select_sprite(SPRITE_HOOK_CHAIN);
		int i = 0;
		for(float f = 24; f < d && i < 1024; f += 24, i++)
		{
			vec2 p = hook_pos + dir*f;
			gfx_quads_draw(p.x, p.y,24,16);
		}

		gfx_quads_setrotation(0);
		gfx_quads_end();

		render_hand(&render_info, position, normalize(hook_pos-pos), -pi/2, vec2(20, 0));
	}

	// draw gun
	{
		gfx_texture_set(data->images[IMAGE_GAME].id);
		gfx_quads_begin();
		gfx_quads_setrotation(state.attach.angle*pi*2+angle);

		// normal weapons
		int iw = clamp(player.weapon, 0, NUM_WEAPONS-1);
		select_sprite(data->weapons.id[iw].sprite_body, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);

		vec2 dir = direction;
		float recoil = 0.0f;
		vec2 p;
		if (player.weapon == WEAPON_HAMMER)
		{
			// Static position for hammer
			p = position + vec2(state.attach.x, state.attach.y);
			p.y += data->weapons.id[iw].offsety;
			// if attack is under way, bash stuffs
			if(direction.x < 0)
			{
				gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
				p.x -= data->weapons.id[iw].offsetx;
			}
			else
			{
				gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
			}
			draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);
		}
		else if (player.weapon == WEAPON_NINJA)
		{
			p = position;
			p.y += data->weapons.id[iw].offsety;

			if(direction.x < 0)
			{
				gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
				p.x -= data->weapons.id[iw].offsetx;
				gameclient.effects->powerupshine(p+vec2(32,0), vec2(32,12));
			}
			else
			{
				gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
				gameclient.effects->powerupshine(p-vec2(32,0), vec2(32,12));
			}
			draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);

			// HADOKEN
			if ((client_tick()-player.attacktick) <= (SERVER_TICK_SPEED / 6) && data->weapons.id[iw].num_sprite_muzzles)
			{
				int itex = rand() % data->weapons.id[iw].num_sprite_muzzles;
				float alpha = 1.0f;
				if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex])
				{
					vec2 dir = vec2(player_char->x,player_char->y) - vec2(prev_char->x, prev_char->y);
					dir = normalize(dir);
					float hadokenangle = get_angle(dir);
					gfx_quads_setrotation(hadokenangle);
					//float offsety = -data->weapons[iw].muzzleoffsety;
					select_sprite(data->weapons.id[iw].sprite_muzzles[itex], 0);
					vec2 diry(-dir.y,dir.x);
					p = position;
					float offsetx = data->weapons.id[iw].muzzleoffsetx;
					p -= dir * offsetx;
					draw_sprite(p.x, p.y, 160.0f);
				}
			}
		}
		else
		{
			// TODO: should be an animation
			recoil = 0;
			float a = (client_tick()-player.attacktick+intratick)/5.0f;
			if(a < 1)
				recoil = sinf(a*pi);
			p = position + dir * data->weapons.id[iw].offsetx - dir*recoil*10.0f;
			p.y += data->weapons.id[iw].offsety;
			draw_sprite(p.x, p.y, data->weapons.id[iw].visual_size);
		}

		if (player.weapon == WEAPON_GUN || player.weapon == WEAPON_SHOTGUN)
		{
			// check if we're firing stuff
			if(data->weapons.id[iw].num_sprite_muzzles)//prev.attackticks)
			{
				float alpha = 0.0f;
				int phase1tick = (client_tick() - player.attacktick);
				if (phase1tick < (data->weapons.id[iw].muzzleduration + 3))
				{
					float t = ((((float)phase1tick) + intratick)/(float)data->weapons.id[iw].muzzleduration);
					alpha = LERP(2.0, 0.0f, min(1.0f,max(0.0f,t)));
				}

				int itex = rand() % data->weapons.id[iw].num_sprite_muzzles;
				if (alpha > 0.0f && data->weapons.id[iw].sprite_muzzles[itex])
				{
					float offsety = -data->weapons.id[iw].muzzleoffsety;
					select_sprite(data->weapons.id[iw].sprite_muzzles[itex], direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
					if(direction.x < 0)
						offsety = -offsety;

					vec2 diry(-dir.y,dir.x);
					vec2 muzzlepos = p + dir * data->weapons.id[iw].muzzleoffsetx + diry * offsety;

					draw_sprite(muzzlepos.x, muzzlepos.y, data->weapons.id[iw].visual_size);
				}
			}
		}
		gfx_quads_end();

		switch (player.weapon)
		{
			case WEAPON_GUN: render_hand(&render_info, p, direction, -3*pi/4, vec2(-15, 4)); break;
			case WEAPON_SHOTGUN: render_hand(&render_info, p, direction, -pi/2, vec2(-5, 4)); break;
			case WEAPON_GRENADE: render_hand(&render_info, p, direction, -pi/2, vec2(-4, 7)); break;
		}

	}

	// render the "shadow" tee
	if(info.local && config.debug)
	{
		vec2 ghost_position = mix(vec2(prev_char->x, prev_char->y), vec2(player_char->x, player_char->y), client_intratick());
		TEE_RENDER_INFO ghost = render_info;
		ghost.color_body.a = 0.5f;
		ghost.color_feet.a = 0.5f;
		render_tee(&state, &ghost, player.emote, direction, ghost_position); // render ghost
	}

	render_info.size = 64.0f; // force some settings
	render_info.color_body.a = 1.0f;
	render_info.color_feet.a = 1.0f;
	
	render_tee(&state, &render_info, player.emote, direction, position);

	if(player.player_state == PLAYERSTATE_CHATTING)
	{
		gfx_texture_set(data->images[IMAGE_EMOTICONS].id);
		gfx_quads_begin();
		select_sprite(SPRITE_DOTDOT);
		gfx_quads_draw(position.x + 24, position.y - 40, 64,64);
		gfx_quads_end();
	}

	if (gameclient.clients[info.cid].emoticon_start != -1 && gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() > client_tick())
	{
		gfx_texture_set(data->images[IMAGE_EMOTICONS].id);
		gfx_quads_begin();

		int since_start = client_tick() - gameclient.clients[info.cid].emoticon_start;
		int from_end = gameclient.clients[info.cid].emoticon_start + 2 * client_tickspeed() - client_tick();

		float a = 1;

		if (from_end < client_tickspeed() / 5)
			a = from_end / (client_tickspeed() / 5.0);

		float h = 1;
		if (since_start < client_tickspeed() / 10)
			h = since_start / (client_tickspeed() / 10.0);

		float wiggle = 0;
		if (since_start < client_tickspeed() / 5)
			wiggle = since_start / (client_tickspeed() / 5.0);

		float wiggle_angle = sin(5*wiggle);

		gfx_quads_setrotation(pi/6*wiggle_angle);

		gfx_setcolor(1.0f,1.0f,1.0f,a);
		// client_datas::emoticon is an offset from the first emoticon
		select_sprite(SPRITE_OOP + gameclient.clients[info.cid].emoticon);
		gfx_quads_draw(position.x, position.y - 23 - 32*h, 64, 64*h);
		gfx_quads_end();
	}
}
示例#2
0
void KILLMESSAGES::on_render()
{
	if(config.cl_render_kill && !config.cl_clear_all)
	{
		float width = 400*3.0f*gfx_screenaspect();
		float height = 400*3.0f;

		gfx_mapscreen(0, 0, width*1.5f, height*1.5f);
		float startx = width*1.5f-10.0f;
		float y = 20.0f;

		for(int i = 0; i < killmsg_max; i++)
		{

			int r = (killmsg_current+i+1)%killmsg_max;
			if(client_tick() > killmsgs[r].tick+50*10)
			continue;

			float font_size = 36.0f;
			float killername_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].killer].name, -1);
			float victimname_w = gfx_text_width(0, font_size, gameclient.clients[killmsgs[r].victim].name, -1);

			float x = startx;

			// render victim name
			x -= victimname_w;
			gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].victim].name, -1);

			// render victim tee
			x -= 24.0f;
		
			if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS)
			{
				if(killmsgs[r].mode_special&1)
				{
					gfx_blend_normal();
					if(config.tc_colored_flags)
						gfx_texture_set(data->images[IMAGE_GAME_GRAY].id);
					else
						gfx_texture_set(data->images[IMAGE_GAME].id);
					gfx_quads_begin();
	
					if(gameclient.clients[killmsgs[r].victim].team == 0) select_sprite(SPRITE_FLAG_BLUE);
					else select_sprite(SPRITE_FLAG_RED);
					if(config.tc_colored_flags)
					{
						vec3 col = TeecompUtils::getTeamColor(1-gameclient.clients[killmsgs[r].victim].team,
							gameclient.snap.local_info->team,
							config.tc_colored_tees_team1, config.tc_colored_tees_team2,
							config.tc_colored_tees_method);
						gfx_setcolor(col.r, col.g, col.b, 1.0f);
					}
				
					float size = 56.0f;
					gfx_quads_drawTL(x, y-16, size/2, size);
					gfx_quads_end();					
				}
			}
		
			// anti rainbow
			TEE_RENDER_INFO victim = gameclient.clients[killmsgs[r].victim].render_info;
			
			if(config.cl_anti_rainbow && (gameclient.clients[killmsgs[r].victim].color_change_count > config.cl_anti_rainbow_count))
			{
				if(config.tc_force_skin_team1)
					victim.texture = gameclient.skins->get(max(0, gameclient.skins->find(config.tc_forced_skin1)))->org_texture;
				else
					victim.texture = gameclient.skins->get(gameclient.clients[killmsgs[r].victim].skin_id)->org_texture;
				victim.color_body = vec4(1,1,1,1);
				victim.color_feet = vec4(1,1,1,1);
			}

			render_tee(ANIMSTATE::get_idle(), &victim, EMOTE_PAIN, vec2(-1,0), vec2(x, y+28));
			x -= 32.0f;
		
			// render weapon
			x -= 44.0f;
			if (killmsgs[r].weapon >= 0)
			{
				gfx_texture_set(data->images[IMAGE_GAME].id);
				gfx_quads_begin();
				select_sprite(data->weapons.id[killmsgs[r].weapon].sprite_body);
				draw_sprite(x, y+28, 96);
				gfx_quads_end();
			}
			x -= 52.0f;

			if(killmsgs[r].victim != killmsgs[r].killer)
			{
				if(gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_FLAGS)
				{
					if(killmsgs[r].mode_special&2)
					{
						gfx_blend_normal();
						if(config.tc_colored_flags)
							gfx_texture_set(data->images[IMAGE_GAME_GRAY].id);
						else
							gfx_texture_set(data->images[IMAGE_GAME].id);
						gfx_quads_begin();

						if(gameclient.clients[killmsgs[r].killer].team == 0) select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
						else select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
						if(config.tc_colored_flags)
						{
							vec3 col = TeecompUtils::getTeamColor(1-gameclient.clients[killmsgs[r].killer].team,
								gameclient.snap.local_info->team,
								config.tc_colored_tees_team1, config.tc_colored_tees_team2,
								config.tc_colored_tees_method);
							gfx_setcolor(col.r, col.g, col.b, 1.0f);
						}
					
						float size = 56.0f;
						gfx_quads_drawTL(x-56, y-16, size/2, size);
							gfx_quads_end();				
					}
				}				
			
				// anti rainbow
				TEE_RENDER_INFO killer = gameclient.clients[killmsgs[r].killer].render_info;
				
				if(config.cl_anti_rainbow && (gameclient.clients[killmsgs[r].killer].color_change_count > config.cl_anti_rainbow_count))
				{
					if(config.tc_force_skin_team1)
						killer.texture = gameclient.skins->get(max(0, gameclient.skins->find(config.tc_forced_skin1)))->org_texture;
					else
						killer.texture = gameclient.skins->get(gameclient.clients[killmsgs[r].killer].skin_id)->org_texture;
					killer.color_body = vec4(1,1,1,1);
					killer.color_feet = vec4(1,1,1,1);
 				}
				
				// render killer tee
				x -= 24.0f;
				render_tee(ANIMSTATE::get_idle(), &killer, EMOTE_ANGRY, vec2(1,0), vec2(x, y+28));
				x -= 32.0f;

				// render killer name
				x -= killername_w;
				gfx_text(0, x, y, font_size, gameclient.clients[killmsgs[r].killer].name, -1);
			}

			y += 44;
		}
	}
}
示例#3
0
void HUD::render_goals()
{
	// TODO: split this up into these:
	// render_gametimer
	// render_suddendeath
	// render_scorehud
	// render_warmuptimer
	
	int gameflags = gameclient.snap.gameobj->flags;
	
	float whole = 300*gfx_screenaspect();
	float half = whole/2.0f;


	gfx_mapscreen(0,0,300*gfx_screenaspect(),300);
	if(!gameclient.snap.gameobj->sudden_death)
	{
		char buf[32];
		int time = 0;
		if(gameclient.snap.gameobj->time_limit)
		{
			time = gameclient.snap.gameobj->time_limit*60 - ((client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed());

			if(gameclient.snap.gameobj->game_over)
				time  = 0;
		}
		else
			time = (client_tick()-gameclient.snap.gameobj->round_start_tick)/client_tickspeed();

		if(config.cl_render_time && !config.cl_clear_hud && !config.cl_clear_all)
		{
			str_format(buf, sizeof(buf), "%d:%02d", time /60, time %60);
			float w = gfx_text_width(0, 16, buf, -1);
			gfx_text(0, half-w/2, 2, 16, buf, -1);
		}
	}

	if((config.cl_render_time && !config.cl_clear_hud && !config.cl_clear_all) && gameclient.snap.gameobj->sudden_death)
	{
		const char *text = "Sudden Death";
		float w = gfx_text_width(0, 16, text, -1);
		gfx_text(0, half-w/2, 2, 16, text, -1);
	}

	// render small score hud
	if((config.cl_render_score && !config.cl_clear_hud && !config.cl_clear_all) && !(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) && (gameflags&GAMEFLAG_TEAMS))
	{
		for(int t = 0; t < 2; t++)
		{
			gfx_blend_normal();
			gfx_texture_set(-1);
			gfx_quads_begin();
			if(!config.tc_hud_match)
			{
				if(t == 0)
					gfx_setcolor(1,0,0,0.25f);
				else
					gfx_setcolor(0,0,1,0.25f);
			}
			else
			{
				vec3 col = TeecompUtils::getTeamColor(t, gameclient.snap.local_info->team,
					config.tc_colored_tees_team1, config.tc_colored_tees_team2, config.tc_colored_tees_method);
				gfx_setcolor(col.r, col.g, col.b, 0.25f);
			}

			draw_round_rect(whole-40, 300-40-15+t*20, 50, 18, 5.0f);
			gfx_quads_end();

			char buf[32];
			str_format(buf, sizeof(buf), "%d", t?gameclient.snap.gameobj->teamscore_blue:gameclient.snap.gameobj->teamscore_red);
			float w = gfx_text_width(0, 14, buf, -1);
			
			if(gameflags&GAMEFLAG_FLAGS)
			{
				gfx_text(0, whole-20-w/2+5, 300-40-15+t*20, 14, buf, -1);
				if(gameclient.snap.flags[t])
				{
					if(gameclient.snap.flags[t]->carried_by == -2 || (gameclient.snap.flags[t]->carried_by == -1 && ((client_tick()/10)&1)))
					{
						gfx_blend_normal();
						if(config.tc_colored_flags)
							gfx_texture_set(data->images[IMAGE_GAME_GRAY].id);
						else
							gfx_texture_set(data->images[IMAGE_GAME].id);
						gfx_quads_begin();

						if(t == 0) select_sprite(SPRITE_FLAG_RED);
						else select_sprite(SPRITE_FLAG_BLUE);
						
						if(config.tc_colored_flags)
						{
							vec3 col = TeecompUtils::getTeamColor(t,
								gameclient.snap.local_info->team,
								config.tc_colored_tees_team1,
								config.tc_colored_tees_team2,
								config.tc_colored_tees_method);
							gfx_setcolor(col.r, col.g, col.b, 1.0f);
						}

						float size = 16;					
						gfx_quads_drawTL(whole-40+5, 300-40-15+t*20+1, size/2, size);
						gfx_quads_end();
					}
					else if(gameclient.snap.flags[t]->carried_by >= 0)
					{
						int id = gameclient.snap.flags[t]->carried_by%MAX_CLIENTS;
						const char *name = gameclient.clients[id].name;
						float w = gfx_text_width(0, 10, name, -1);
						gfx_text(0, whole-40-5-w, 300-40-15+t*20+2, 10, name, -1);
						TEE_RENDER_INFO info = gameclient.clients[id].render_info;
						info.size = 18.0f;
						
						render_tee(ANIMSTATE::get_idle(), &info, EMOTE_NORMAL, vec2(1,0),
							vec2(whole-40+10, 300-40-15+9+t*20+1));
					}
				}
			}
			else
				gfx_text(0, whole-20-w/2, 300-40-15+t*20, 14, buf, -1);
		}
	}

	// render warmup timer
	if((config.cl_render_warmup && !config.cl_clear_all) && gameclient.snap.gameobj->warmup)
	{
		char buf[256];
		float w = gfx_text_width(0, 24, "Warmup", -1);
		gfx_text(0, 150*gfx_screenaspect()+-w/2, 50, 24, "Warmup", -1);

		int seconds = gameclient.snap.gameobj->warmup/SERVER_TICK_SPEED;
		if(seconds < 5)
			str_format(buf, sizeof(buf), "%d.%d", seconds, (gameclient.snap.gameobj->warmup*10/SERVER_TICK_SPEED)%10);
		else
			str_format(buf, sizeof(buf), "%d", seconds);
		w = gfx_text_width(0, 24, buf, -1);
		gfx_text(0, 150*gfx_screenaspect()+-w/2, 75, 24, buf, -1);
	}	
}
示例#4
0
void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const char *title)
{
	//float ystart = y;
	float h = 750.0f;

	gfx_blend_normal();
	gfx_texture_set(-1);
	gfx_quads_begin();
	gfx_setcolor(0,0,0,0.5f);
	draw_round_rect(x-10.f, y-10.f, w, h, 17.0f);
	gfx_quads_end();

	// render title
	if(!title)
	{
		if(gameclient.snap.gameobj->game_over)
			title = "Game Over";
		else
			title = "Score Board";
	}

	float tw = gfx_text_width(0, 48, title, -1);

	if(team == -1)
	{
		gfx_text(0, x+w/2-tw/2, y, 48, title, -1);
	}
	else
	{
		gfx_text(0, x+10, y, 48, title, -1);

		if(gameclient.snap.gameobj)
		{
			char buf[128];
			int score = team ? gameclient.snap.gameobj->teamscore_blue : gameclient.snap.gameobj->teamscore_red;
			str_format(buf, sizeof(buf), "%d", score);
			tw = gfx_text_width(0, 48, buf, -1);
			gfx_text(0, x+w-tw-30, y, 48, buf, -1);
		}
	}

	y += 54.0f;

	// find players
	const NETOBJ_PLAYER_INFO *players[MAX_CLIENTS] = {0};
	int num_players = 0;
	for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++)
	{
		SNAP_ITEM item;
		const void *data = snap_get_item(SNAP_CURRENT, i, &item);

		if(item.type == NETOBJTYPE_PLAYER_INFO)
		{
			const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
			if(info->team == team)
			{
				players[num_players] = info;
				num_players++;
			}
		}
	}

	// sort players
	for(int k = 0; k < num_players; k++) // ffs, bubblesort
	{
		for(int i = 0; i < num_players-k-1; i++)
		{
			if(players[i]->score < players[i+1]->score)
			{
				const NETOBJ_PLAYER_INFO *tmp = players[i];
				players[i] = players[i+1];
				players[i+1] = tmp;
			}
		}
	}

	// render headlines
	gfx_text(0, x+10, y, 24.0f, "Score", -1);
	gfx_text(0, x+125, y, 24.0f, "Name", -1);
	gfx_text(0, x+w-70, y, 24.0f, "Ping", -1);
	y += 29.0f;

	float font_size = 35.0f;
	float line_height = 50.0f;
	float tee_sizemod = 1.0f;
	float tee_offset = 0.0f;
	
	if(num_players > 13)
	{
		font_size = 30.0f;
		line_height = 40.0f;
		tee_sizemod = 0.8f;
		tee_offset = -5.0f;
	}
	
	// render player scores
	for(int i = 0; i < num_players; i++)
	{
		const NETOBJ_PLAYER_INFO *info = players[i];

		// make sure that we render the correct team

		char buf[128];
		if(info->local)
		{
			// background so it's easy to find the local player
			gfx_texture_set(-1);
			gfx_quads_begin();
			gfx_setcolor(1,1,1,0.25f);
			draw_round_rect(x, y, w-20, line_height*0.95f, 17.0f);
			gfx_quads_end();
		}

		str_format(buf, sizeof(buf), "%4d", info->score);
		gfx_text(0, x+60-gfx_text_width(0, font_size,buf,-1), y, font_size, buf, -1);
		
		if(config.cl_scoreboard_client_id)
		{
			str_format(buf, sizeof(buf), "%d | %s", info->cid, gameclient.clients[info->cid].name);
			gfx_text(0, x+128, y, font_size, buf, -1);
		}
		else
		{
			gfx_text(0, x+128, y, font_size, gameclient.clients[info->cid].name, -1);
		}

		str_format(buf, sizeof(buf), "%4d", info->latency);
		float tw = gfx_text_width(0, font_size, buf, -1);
		gfx_text(0, x+w-tw-35, y, font_size, buf, -1);

		// render avatar
		if((gameclient.snap.flags[0] && gameclient.snap.flags[0]->carried_by == info->cid) ||
			(gameclient.snap.flags[1] && gameclient.snap.flags[1]->carried_by == info->cid))
		{
			gfx_blend_normal();
			if(config.tc_colored_flags)
				gfx_texture_set(data->images[IMAGE_GAME_GRAY].id);
			else
				gfx_texture_set(data->images[IMAGE_GAME].id);
			gfx_quads_begin();

			if(info->team == 0) select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X);
			else select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X);
			if(config.tc_colored_flags)
			{
				vec3 col = TeecompUtils::getTeamColor(1-info->team, gameclient.snap.local_info->team, 
					config.tc_colored_tees_team1, config.tc_colored_tees_team2, config.tc_colored_tees_method);
				gfx_setcolor(col.r, col.g, col.b, 1.0f);
			}
			
			float size = 64.0f;
			gfx_quads_drawTL(x+55, y-15, size/2, size);
			gfx_quads_end();
		}
		
		TEE_RENDER_INFO teeinfo = gameclient.clients[info->cid].render_info;
		teeinfo.size *= tee_sizemod;
		render_tee(ANIMSTATE::get_idle(), &teeinfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+tee_offset));

		
		y += line_height;
	}
}