2008-08-27 15:48:50 +00:00
|
|
|
#include <engine/e_client_interface.h>
|
|
|
|
#include <game/generated/g_protocol.hpp>
|
|
|
|
#include <game/generated/gc_data.hpp>
|
|
|
|
|
|
|
|
#include <game/gamecore.hpp> // get_angle
|
|
|
|
#include <game/client/gameclient.hpp>
|
2008-08-30 21:31:01 +00:00
|
|
|
#include <game/client/ui.hpp>
|
2008-10-20 23:46:39 +00:00
|
|
|
#include <game/client/render.hpp>
|
2008-08-27 15:48:50 +00:00
|
|
|
|
|
|
|
#include <game/client/components/flow.hpp>
|
|
|
|
#include <game/client/components/effects.hpp>
|
|
|
|
|
|
|
|
#include "items.hpp"
|
|
|
|
|
|
|
|
void ITEMS::render_projectile(const NETOBJ_PROJECTILE *current, int itemid)
|
|
|
|
{
|
|
|
|
|
|
|
|
// get positions
|
|
|
|
float curvature = 0;
|
|
|
|
float speed = 0;
|
|
|
|
if(current->type == WEAPON_GRENADE)
|
|
|
|
{
|
2008-08-29 05:34:18 +00:00
|
|
|
curvature = gameclient.tuning.grenade_curvature;
|
|
|
|
speed = gameclient.tuning.grenade_speed;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
else if(current->type == WEAPON_SHOTGUN)
|
|
|
|
{
|
2008-08-29 05:34:18 +00:00
|
|
|
curvature = gameclient.tuning.shotgun_curvature;
|
|
|
|
speed = gameclient.tuning.shotgun_speed;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
else if(current->type == WEAPON_GUN)
|
|
|
|
{
|
2008-08-29 05:34:18 +00:00
|
|
|
curvature = gameclient.tuning.gun_curvature;
|
|
|
|
speed = gameclient.tuning.gun_speed;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2008-10-14 12:11:42 +00:00
|
|
|
float ct = (client_prevtick()-current->start_tick)/(float)SERVER_TICK_SPEED + client_ticktime();
|
|
|
|
if(ct < 0)
|
|
|
|
return; // projectile havn't been shot yet
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
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);
|
|
|
|
|
2008-10-14 12:11:42 +00:00
|
|
|
|
|
|
|
gfx_texture_set(data->images[IMAGE_GAME].id);
|
|
|
|
gfx_quads_begin();
|
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
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);
|
|
|
|
gfx_quads_setrotation(0);
|
|
|
|
gfx_quads_end();
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ITEMS::render_flag(const NETOBJ_FLAG *prev, const NETOBJ_FLAG *current)
|
|
|
|
{
|
|
|
|
float angle = 0.0f;
|
|
|
|
float size = 42.0f;
|
|
|
|
|
|
|
|
gfx_blend_normal();
|
|
|
|
gfx_texture_set(data->images[IMAGE_GAME].id);
|
|
|
|
gfx_quads_begin();
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2008-08-29 05:34:18 +00:00
|
|
|
float a = ms / gameclient.tuning.laser_bounce_delay;
|
2008-08-27 15:48:50 +00:00
|
|
|
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(0.075f,0.075f,0.25f,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(0.5f,0.5f,1.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();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ITEMS::on_render()
|
|
|
|
{
|
|
|
|
int num = snap_num_items(SNAP_CURRENT);
|
|
|
|
for(int i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
SNAP_ITEM item;
|
|
|
|
const void *data = snap_get_item(SNAP_CURRENT, i, &item);
|
|
|
|
|
|
|
|
if(item.type == NETOBJTYPE_PROJECTILE)
|
|
|
|
{
|
|
|
|
render_projectile((const NETOBJ_PROJECTILE *)data, item.id);
|
|
|
|
}
|
|
|
|
else if(item.type == NETOBJTYPE_PICKUP)
|
|
|
|
{
|
|
|
|
const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
|
|
|
|
if(prev)
|
|
|
|
render_pickup((const NETOBJ_PICKUP *)prev, (const NETOBJ_PICKUP *)data);
|
|
|
|
}
|
|
|
|
else if(item.type == NETOBJTYPE_LASER)
|
|
|
|
{
|
|
|
|
render_laser((const NETOBJ_LASER *)data);
|
|
|
|
}
|
|
|
|
else if(item.type == NETOBJTYPE_FLAG)
|
|
|
|
{
|
|
|
|
const void *prev = snap_find_item(SNAP_PREV, item.type, item.id);
|
|
|
|
if (prev)
|
|
|
|
render_flag((const NETOBJ_FLAG *)prev, (const NETOBJ_FLAG *)data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// render extra projectiles
|
|
|
|
/*
|
|
|
|
for(int i = 0; i < extraproj_num; i++)
|
|
|
|
{
|
|
|
|
if(extraproj_projectiles[i].start_tick < client_tick())
|
|
|
|
{
|
|
|
|
extraproj_projectiles[i] = extraproj_projectiles[extraproj_num-1];
|
|
|
|
extraproj_num--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
render_projectile(&extraproj_projectiles[i], 0);
|
|
|
|
}*/
|
|
|
|
}
|