Пример #1
0
void HUD::render_healthandammo()
{
	//mapscreen_to_group(gacenter_x, center_y, layers_game_group());

	float x = 5;
	float y = 5;

	// render ammo count
	// render gui stuff

	gfx_texture_set(data->images[IMAGE_GAME].id);
	gfx_mapscreen(0,0,width,300);
	
	gfx_quads_begin();
	
	if(config.cl_render_ammo)
	{
		// if weaponstage is active, put a "glow" around the stage ammo
		select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_proj);
		for (int i = 0; i < min(gameclient.snap.local_character->ammocount, 10); i++)
			gfx_quads_drawTL(x+i*12,y+24,10,10);
	}

	gfx_quads_end();

	gfx_quads_begin();
	int h = 0;

	// render health
	if(config.cl_render_hp)
	{
		select_sprite(SPRITE_HEALTH_FULL);
		for(; h < gameclient.snap.local_character->health; h++)
			gfx_quads_drawTL(x+h*12,y,10,10);
 
		select_sprite(SPRITE_HEALTH_EMPTY);
		for(; h < 10; h++)
			gfx_quads_drawTL(x+h*12,y,10,10);
	
		// render armor meter
		h = 0;
		select_sprite(SPRITE_ARMOR_FULL);
		for(; h < gameclient.snap.local_character->armor; h++)
			gfx_quads_drawTL(x+h*12,y+12,10,10);
 
		select_sprite(SPRITE_ARMOR_EMPTY);
		for(; h < 10; h++)
			gfx_quads_drawTL(x+h*12,y+12,10,10);
	}
		gfx_quads_end();
}
Пример #2
0
void PARTICLES::render_group(int group)
{
	gfx_blend_normal();
	//gfx_blend_additive();
	gfx_texture_set(data->images[IMAGE_PARTICLES].id);
	gfx_quads_begin();

	int i = first_part[group];
	while(i != -1)
	{
		select_sprite(particles[i].spr);
		float a = particles[i].life / particles[i].life_span;
		vec2 p = particles[i].pos;
		float size = mix(particles[i].start_size, particles[i].end_size, a);

		gfx_quads_setrotation(particles[i].rot);

		gfx_setcolor(
			particles[i].color.r,
			particles[i].color.g,
			particles[i].color.b,
			particles[i].color.a); // pow(a, 0.75f) * 

		gfx_quads_draw(p.x, p.y, size, size);
		
		i = particles[i].next_part;
	}
	gfx_quads_end();
	gfx_blend_normal();
}
Пример #3
0
void MENUS::ui_draw_browse_icon(int what, const RECT *r)
{
	gfx_texture_set(data->images[IMAGE_BROWSEICONS].id);
	gfx_quads_begin();
	select_sprite(what);
	gfx_quads_drawTL(r->x,r->y,r->w,r->h);
	gfx_quads_end();
}
Пример #4
0
void ITEMS::render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current)
{
	float angle = 0.0f;
	float size = 42.0f;

	if(gameclient.snap.local_info && current->carried_by == gameclient.snap.local_info->cid && config.tc_hide_carrying)
		return;

	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(config.tc_colored_flags && gameclient.snap.local_info)
	{
		vec3 col = TeecompUtils::getTeamColor(current->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);
	}

	if(current->team == 0) // red team
		select_sprite(SPRITE_FLAG_RED);
	else
		select_sprite(SPRITE_FLAG_BLUE);

	gfx_quads_setrotation(angle);

	vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), client_intratick());
	
	// make sure that the flag isn't interpolated between capture and return
	if(prev->carried_by != current->carried_by)
		pos = vec2(current->x, current->y);

	// make sure to use predicted position if we are the carrier
	if(gameclient.snap.local_info && current->carried_by == gameclient.snap.local_info->cid)
		pos = gameclient.local_character_pos;

	gfx_quads_draw(pos.x, pos.y-size*0.75f, size, size*2);
	gfx_quads_end();
}
Пример #5
0
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();
}
Пример #6
0
void HUD::render_cursor()
{
	if(!gameclient.snap.local_character)
		return;
		
	mapscreen_to_group(gameclient.camera->center.x, gameclient.camera->center.y, layers_game_group());
	gfx_texture_set(data->images[IMAGE_GAME].id);
	gfx_quads_begin();

	// render cursor
	select_sprite(data->weapons.id[gameclient.snap.local_character->weapon%NUM_WEAPONS].sprite_cursor);
	float cursorsize = 64;
	draw_sprite(gameclient.controls->target_pos.x, gameclient.controls->target_pos.y, cursorsize);
	gfx_quads_end();
}
Пример #7
0
void PLAYERS::render_hand(TEE_RENDER_INFO *info, vec2 center_pos, vec2 dir, float angle_offset, vec2 post_rot_offset)
{
	// for drawing hand
	//const skin *s = skin_get(skin_id);
	
	float basesize = 10.0f;
	//dir = normalize(hook_pos-pos);

	vec2 hand_pos = center_pos + dir;
	float angle = get_angle(dir);
	if (dir.x < 0)
		angle -= angle_offset;
	else
		angle += angle_offset;

	vec2 dirx = dir;
	vec2 diry(-dir.y,dir.x);

	if (dir.x < 0)
		diry = -diry;

	hand_pos += dirx * post_rot_offset.x;
	hand_pos += diry * post_rot_offset.y;

	//gfx_texture_set(data->images[IMAGE_CHAR_DEFAULT].id);
	gfx_texture_set(info->texture);
	gfx_quads_begin();
	gfx_setcolor(info->color_body.r, info->color_body.g, info->color_body.b, info->color_body.a);

	// two passes
	for (int i = 0; i < 2; i++)
	{
		bool outline = i == 0;

		select_sprite(outline?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0);
		gfx_quads_setrotation(angle);
		gfx_quads_draw(hand_pos.x, hand_pos.y, 2*basesize, 2*basesize);
	}

	gfx_quads_setrotation(0);
	gfx_quads_end();
}
Пример #8
0
void DAMAGEIND::on_render()
{
    gfx_texture_set(data->images[IMAGE_GAME].id);
    gfx_quads_begin();
    for(int i = 0; i < num_items;)
    {
        vec2 pos = mix(items[i].pos+items[i].dir*75.0f, items[i].pos, clamp((items[i].life-0.60f)/0.15f, 0.0f, 1.0f));

        items[i].life -= client_frametime();
        if(items[i].life < 0.0f)
            destroy_i(&items[i]);
        else
        {
            gfx_setcolor(1.0f,1.0f,1.0f, items[i].life/0.1f);
            gfx_quads_setrotation(items[i].startangle + items[i].life * 2.0f);
            select_sprite(SPRITE_STAR1);
            draw_sprite(pos.x, pos.y, 48.0f);
            i++;
        }
    }
    gfx_quads_end();
}
Пример #9
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();
	}
}
Пример #10
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);
	}	
}
Пример #11
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;
		}
	}
}
Пример #12
0
void ITEMS::render_laser(const struct NETOBJ_LASER *current)
{
	vec2 pos = vec2(current->x, current->y);
	vec2 from = vec2(current->from_x, current->from_y);
	vec2 dir = normalize(pos-from);

	float ticks = client_tick() + client_intratick() - current->start_tick;
	float ms = (ticks/50.0f) * 1000.0f;
	float a =  ms / gameclient.tuning.laser_bounce_delay;
	a = clamp(a, 0.0f, 1.0f);
	float ia = 1-a;
	
	vec2 out, border;
	
	gfx_blend_normal();
	gfx_texture_set(-1);
	gfx_quads_begin();
	
	//vec4 inner_color(0.15f,0.35f,0.75f,1.0f);
	//vec4 outer_color(0.65f,0.85f,1.0f,1.0f);

	// do outline
	vec4 outer_color(
		(config.tc_laser_color_outer>>16)/255.0f,
		((config.tc_laser_color_outer>>8)&0xff)/255.0f,
		(config.tc_laser_color_outer&0xff)/255.0f, 1.0f);
	gfx_setcolor(outer_color.r,outer_color.g,outer_color.b,1.0f);
	out = vec2(dir.y, -dir.x) * (7.0f*ia);

	gfx_quads_draw_freeform(
			from.x-out.x, from.y-out.y,
			from.x+out.x, from.y+out.y,
			pos.x-out.x, pos.y-out.y,
			pos.x+out.x, pos.y+out.y
		);

	// do inner	
	vec4 inner_color(
		(config.tc_laser_color_inner>>16)/255.0f,
		((config.tc_laser_color_inner>>8)&0xff)/255.0f,
		(config.tc_laser_color_inner&0xff)/255.0f, 1.0f);
	out = vec2(dir.y, -dir.x) * (5.0f*ia);
	gfx_setcolor(inner_color.r, inner_color.g, inner_color.b, 1.0f); // center
	
	gfx_quads_draw_freeform(
			from.x-out.x, from.y-out.y,
			from.x+out.x, from.y+out.y,
			pos.x-out.x, pos.y-out.y,
			pos.x+out.x, pos.y+out.y
		);
		
	gfx_quads_end();
	
	// render head
	{
		gfx_blend_normal();
		gfx_texture_set(data->images[IMAGE_PARTICLES].id);
		gfx_quads_begin();

		int sprites[] = {SPRITE_PART_SPLAT01, SPRITE_PART_SPLAT02, SPRITE_PART_SPLAT03};
		select_sprite(sprites[client_tick()%3]);
		gfx_quads_setrotation(client_tick());
		gfx_setcolor(outer_color.r,outer_color.g,outer_color.b,1.0f);
		gfx_quads_draw(pos.x, pos.y, 24,24);
		gfx_setcolor(inner_color.r, inner_color.g, inner_color.b, 1.0f);
		gfx_quads_draw(pos.x, pos.y, 20,20);
		gfx_quads_end();
	}
	
	gfx_blend_normal();	
}
Пример #13
0
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();
}
Пример #14
0
/**********************************
Draw a single sprite
if image_file_name is not NULL, this file is used as an image rather than the normal sprite image
**********************************/
static void set_up_sprite(context_t * ctx, const char * image_file_name)
{
	anim_t ** sprite_list;
	anim_t ** sprite_move_list;
	item_t * item;
	int px;
	int py;
	int opx;
	int opy;
	Uint32 current_time;
	int angle;
	int flip;
	int force_flip;
	int move_status;
	char * zoom_str = NULL;
	double zoom = 1.0;
	int sprite_align = ALIGN_CENTER;
	int sprite_offset_y = 0;
	bool force_position = false;

	context_t * player_context = context_get_player();

	if( ctx->map == NULL ) {
		return;
	}
	if( ctx->in_game == false ) {
		return;
	}
	if( strcmp(ctx->map,player_context->map)) {
		return;
	}

	item = item_list_add(&item_list);

	current_time = sdl_get_global_time();

	// Force position when the player has changed map
	if( change_map == true ) {
		ctx->move_start_tick = current_time;
		ctx->animation_tick = current_time;
		force_position = true;
	}
	// Force position when this context has changed map
	if( ctx->change_map == true ) {
		ctx->move_start_tick = current_time;
		ctx->animation_tick = current_time;
		ctx->change_map = false;
		force_position = true;
	}

	if( ctx->animation_tick == 0 ) {
		ctx->animation_tick = current_time;
	}

	if( ctx->cur_pos_px == INT_MAX || ctx->cur_pos_py == INT_MAX ) {
		force_position = true;
	}

	// Detect sprite movement, initiate animation
	if( ctx->pos_changed && force_position == false ) {
		ctx->pos_changed = false;
		ctx->move_start_tick = current_time;
		ctx->start_pos_px = ctx->cur_pos_px;
		ctx->start_pos_py = ctx->cur_pos_py;

		/* flip need to remember previous direction to avoid resetting a
		   east -> west flip when a sprite goes to north for instance.
		   On the contrary rotation must not remember previous state, or
		   the rotation will be wrong.
		   Hence the distinction between orientation (no memory) and
		   direction (memory). */
		ctx->orientation = 0;
		// Compute direction
		if( ctx->pos_tx > ctx->prev_pos_tx ) {
			ctx->direction &= ~WEST;
			ctx->direction |= EAST;
			ctx->orientation |= EAST;
		}
		if( ctx->pos_tx < ctx->prev_pos_tx ) {
			ctx->direction &= ~EAST;
			ctx->direction |= WEST;
			ctx->orientation |= WEST;
		}
		if( ctx->pos_ty > ctx->prev_pos_ty ) {
			ctx->direction &= ~NORTH;
			ctx->direction |= SOUTH;
			ctx->orientation |= SOUTH;
		}
		if( ctx->pos_ty < ctx->prev_pos_ty ) {
			ctx->direction &= ~SOUTH;
			ctx->direction |= NORTH;
			ctx->orientation |= NORTH;
		}
	}

	// Select sprite to display
	sprite_list = select_sprite(ctx,image_file_name);
	if( sprite_list == NULL ) {
		return;
	}
	if( sprite_list[0] == NULL ) {
		free(sprite_list);
		return;
	}
	sprite_move_list = select_sprite_move(ctx,image_file_name);

	// Get position in pixel
	px = map_t2p_x(ctx->pos_tx,ctx->pos_ty,default_layer);
	py = map_t2p_y(ctx->pos_tx,ctx->pos_ty,default_layer);

	// Get per sprite zoom
	if(entry_read_string(CHARACTER_TABLE,ctx->id,&zoom_str,CHARACTER_KEY_ZOOM,NULL) == RET_OK ) {
		zoom = atof(zoom_str);
		free(zoom_str);
	}

	// Align sprite on tile
	entry_read_int(CHARACTER_TABLE,ctx->id,&sprite_align,CHARACTER_KEY_ALIGN,NULL);
	if( sprite_align == ALIGN_CENTER ) {
		px -= ((sprite_list[0]->w*default_layer->map_zoom*zoom)-default_layer->tile_width)/2;
		py -= ((sprite_list[0]->h*default_layer->map_zoom*zoom)-default_layer->tile_height)/2;
	}
	if( sprite_align == ALIGN_LOWER ) {
		px -= ((sprite_list[0]->w*default_layer->map_zoom*zoom)-default_layer->tile_width)/2;
		py -= (sprite_list[0]->h*default_layer->map_zoom*zoom)-default_layer->tile_height ;
	}

	// Add Y offset
	entry_read_int(CHARACTER_TABLE,ctx->id,&sprite_offset_y,CHARACTER_KEY_OFFSET_Y,NULL);
	py += sprite_offset_y;

	// Set sprite to item
	item_set_anim_start_tick(item,ctx->animation_tick);

	if( force_position == true ) {
		ctx->start_pos_px = px;
		ctx->cur_pos_px = px;
		ctx->start_pos_py = py;
		ctx->cur_pos_py = py;
	}

	opx = ctx->start_pos_px;
	opy = ctx->start_pos_py;

	item_set_move(item,opx,opy,px,py,ctx->move_start_tick,VIRTUAL_ANIM_DURATION);
	item_set_save_coordinate(item,&ctx->cur_pos_px,&ctx->cur_pos_py);
	item_set_anim_array(item,sprite_list);
	free(sprite_list);
	item_set_anim_move_array(item,sprite_move_list);
	free(sprite_move_list);

	// Get rotation configuration
	angle = 0;
	if( ctx->orientation & NORTH && ctx->orientation & EAST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_NE_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & SOUTH && ctx->orientation & EAST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_SE_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & SOUTH && ctx->orientation & WEST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_SW_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & NORTH && ctx->orientation & WEST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_NW_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & NORTH ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_N_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & SOUTH ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_S_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & WEST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_W_ROT,NULL);
		item_set_angle(item,(double)angle);
	} else if ( ctx->orientation & EAST ) {
		entry_read_int(CHARACTER_TABLE,ctx->id,&angle,CHARACTER_KEY_DIR_E_ROT,NULL);
		item_set_angle(item,(double)angle);
	}

	// Get flip configuration
	force_flip = 0;
	entry_read_int(CHARACTER_TABLE,ctx->id,&force_flip,CHARACTER_KEY_FORCE_FLIP,NULL);
	move_status = ctx->direction;
	if( force_flip == true ) {
		move_status = ctx->orientation;
	}

	flip = 0;
	if( angle == 0 ) {
		if( move_status & NORTH ) {
			entry_read_int(CHARACTER_TABLE,ctx->id,&flip,CHARACTER_KEY_DIR_N_FLIP,NULL);
		}
		if( move_status & SOUTH ) {
			entry_read_int(CHARACTER_TABLE,ctx->id,&flip,CHARACTER_KEY_DIR_S_FLIP,NULL);
		}
		if( move_status & WEST ) {
			entry_read_int(CHARACTER_TABLE,ctx->id,&flip,CHARACTER_KEY_DIR_W_FLIP,NULL);
		}
		if( move_status & EAST ) {
			entry_read_int(CHARACTER_TABLE,ctx->id,&flip,CHARACTER_KEY_DIR_E_FLIP,NULL);
		}

		switch(flip) {
		case 1:
			item_set_flip(item,SDL_FLIP_HORIZONTAL);
			break;
		case 2:
			item_set_flip(item,SDL_FLIP_VERTICAL);
			break;
		case 3:
			item_set_flip(item,SDL_FLIP_HORIZONTAL|SDL_FLIP_VERTICAL);
			break;
		default:
			item_set_flip(item,SDL_FLIP_NONE);
		}
	}

	item_set_click_left(item,cb_select_sprite,ctx->id,NULL);
	item_set_click_right(item,cb_redo_sprite,item,NULL);

	item_set_zoom_x(item,zoom * default_layer->map_zoom );
	item_set_zoom_y(item,zoom * default_layer->map_zoom );
}
Пример #15
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;
	}
}