Updated stuff

This commit is contained in:
Olle Rosenquist 2007-07-21 19:03:50 +00:00
parent 0c786f6002
commit 4ef0a10bf9
4 changed files with 367 additions and 32 deletions

View file

@ -479,6 +479,31 @@ void modc_newsnapshot()
temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f); temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f);
} }
} }
else if(item.type == EVENT_SPAWN)
{
ev_explosion *ev = (ev_explosion *)data;
vec2 p(ev->x, ev->y);
// center explosion
vec2 v = normalize(vec2(frandom()-0.5f, -frandom()))*(32.0f+frandom()*32.0f);
temp_system.new_particle(p, v, 1.2f, 64.0f, 0, 0.95f);
v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f);
temp_system.new_particle(p, v, 1.2f, 32.0f, 0, 0.95f);
v = normalize(vec2(frandom()-0.5f, -frandom()))*(128.0f+frandom()*128.0f);
temp_system.new_particle(p, v, 1.2f, 16.0f, 0, 0.95f);
for(int i = 0; i < 8; i++)
{
vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(64.0f+frandom()*64.0f);
temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 0, 0.985f);
}
for(int i = 0; i < 8; i++)
{
vec2 v = normalize(vec2(frandom()-0.5f, frandom()-0.5f))*(128.0f+frandom()*256.0f);
temp_system.new_particle(p, v, 0.5f+0.5f*frandom(), 16.0f, 128.0f, 0.985f);
}
}
else if(item.type == EVENT_SOUND) else if(item.type == EVENT_SOUND)
{ {
ev_sound *ev = (ev_sound *)data; ev_sound *ev = (ev_sound *)data;
@ -715,9 +740,14 @@ static void render_player(obj_player *prev, obj_player *player)
if (player->weapon == WEAPON_HAMMER) if (player->weapon == WEAPON_HAMMER)
{ {
float a = clamp((client_tick()-player->attacktick+client_intratick())/7.5f, 0.0f, 1.0f); float a = clamp((client_tick()-player->attacktick+client_intratick())/10.0f, 0.0f, 1.0f);
anim_eval_add(&state, &data->animations[ANIM_HAMMER_SWING], a, 1.0f); anim_eval_add(&state, &data->animations[ANIM_HAMMER_SWING], a, 1.0f);
} }
if (player->weapon == WEAPON_NINJA)
{
float a = clamp((client_tick()-player->attacktick+client_intratick())/40.0f, 0.0f, 1.0f);
anim_eval_add(&state, &data->animations[ANIM_NINJA_SWING], a, 1.0f);
}
// draw hook // draw hook
@ -763,14 +793,40 @@ static void render_player(obj_player *prev, obj_player *player)
vec2 dir = direction; vec2 dir = direction;
float recoil = 0.0f; float recoil = 0.0f;
vec2 p;
if (player->weapon == WEAPON_HAMMER) if (player->weapon == WEAPON_HAMMER)
{ {
// Static position for hammer
p = position;
p.y += data->weapons[iw].offsety;
// if attack is under way, bash stuffs // if attack is under way, bash stuffs
if(direction.x < 0) if(direction.x < 0)
{
gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2); gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
p.x -= data->weapons[iw].offsetx;
}
else else
{
gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2); gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
} }
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
}
else if (player->weapon == WEAPON_NINJA)
{
p = position;
p.y += data->weapons[iw].offsety;
if(direction.x < 0)
{
gfx_quads_setrotation(-pi/2-state.attach.angle*pi*2);
p.x -= data->weapons[iw].offsetx;
}
else
{
gfx_quads_setrotation(-pi/2+state.attach.angle*pi*2);
}
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
}
else else
{ {
// TODO: should be an animation // TODO: should be an animation
@ -778,12 +834,44 @@ static void render_player(obj_player *prev, obj_player *player)
float a = (client_tick()-player->attacktick+client_intratick())/5.0f; float a = (client_tick()-player->attacktick+client_intratick())/5.0f;
if(a < 1) if(a < 1)
recoil = sinf(a*pi); recoil = sinf(a*pi);
p = position + dir * data->weapons[iw].offsetx - dir*recoil*10.0f;
p.y += data->weapons[iw].offsety;
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
} }
vec2 p = position + dir*20.0f - dir*recoil*10.0f; if (player->weapon == WEAPON_TYPE_GUN || player->weapon == WEAPON_TYPE_SHOTGUN)
draw_sprite(p.x, p.y, data->weapons[iw].visual_size); {
// check if we're firing stuff
if (true)///prev->attackticks)
{
float alpha = 0.0f;
int phase1tick = (client_tick() - player->attacktick);
if (phase1tick < (data->weapons[iw].muzzleduration + 3))
{
float intratick = client_intratick();
float t = ((((float)phase1tick) + intratick)/(float)data->weapons[iw].muzzleduration);
alpha = LERP(2.0, 0.0f, min(1.0f,max(0.0f,t)));
}
// TODO: draw muzzleflare int itex = rand() % data->weapons[iw].nummuzzlesprites;
if (alpha > 0.0f && data->weapons[iw].sprite_muzzle[itex].psprite)
{
float offsety = -data->weapons[iw].muzzleoffsety;
select_sprite(data->weapons[iw].sprite_muzzle[itex].psprite, direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
if(direction.x < 0)
offsety = -offsety;
vec2 diry(-dir.y,dir.x);
p += dir * data->weapons[iw].muzzleoffsetx + diry * offsety;
draw_sprite(p.x, p.y, data->weapons[iw].visual_size);
/*gfx_quads_setcolor(1.0f,1.0f,1.0f,alpha);
vec2 diry(-dir.y,dir.x);
p += dir * muzzleparams[player->weapon].offsetx + diry * offsety;
gfx_quads_draw(p.x,p.y,muzzleparams[player->weapon].sizex, muzzleparams[player->weapon].sizey);*/
}
}
}
gfx_quads_end(); gfx_quads_end();
} }

View file

@ -18,6 +18,10 @@ inline float get_angle(baselib::vec2 dir)
return a; return a;
} }
#define LERP(a,b,t) (a + (b-a) * t)
#define min(a, b) ( a > b ? b : a)
#define max(a, b) ( a > b ? a : b)
inline bool col_check_point(float x, float y) { return col_check_point((int)x, (int)y) != 0; } inline bool col_check_point(float x, float y) { return col_check_point((int)x, (int)y) != 0; }
inline bool col_check_point(baselib::vec2 p) { return col_check_point(p.x, p.y); } inline bool col_check_point(baselib::vec2 p) { return col_check_point(p.x, p.y); }
@ -34,6 +38,7 @@ enum
EVENT_DAMAGEINDICATION, EVENT_DAMAGEINDICATION,
EVENT_SOUND, EVENT_SOUND,
EVENT_SMOKE, EVENT_SMOKE,
EVENT_SPAWN,
}; };
enum enum
@ -75,6 +80,11 @@ struct ev_explosion
int x, y; int x, y;
}; };
struct ev_spawn
{
int x, y;
};
struct ev_sound struct ev_sound
{ {
int x, y; int x, y;
@ -152,9 +162,6 @@ enum
POWERUP_TYPE_TIMEFIELD = 4, POWERUP_TYPE_TIMEFIELD = 4,
POWERUP_TYPE_NUMPOWERUPS, POWERUP_TYPE_NUMPOWERUPS,
PLAYER_MAXHEALTH = 10,
PLAYER_MAXARMOR = 10,
MODIFIER_TYPE_NINJA = 0, MODIFIER_TYPE_NINJA = 0,
MODIFIER_TYPE_TIMEFIELD = 1, MODIFIER_TYPE_TIMEFIELD = 1,
MODIFIER_NUMMODIFIERS, MODIFIER_NUMMODIFIERS,

View file

@ -5,6 +5,8 @@
#include "data.h" #include "data.h"
#include "game_server.h" #include "game_server.h"
data_container *data = 0x0;
using namespace baselib; using namespace baselib;
// --------- DEBUG STUFF --------- // --------- DEBUG STUFF ---------
@ -28,6 +30,7 @@ class player* get_player(int index);
void create_damageind(vec2 p, vec2 dir, int amount); void create_damageind(vec2 p, vec2 dir, int amount);
void create_explosion(vec2 p, int owner, int weapon, bool bnodamage); void create_explosion(vec2 p, int owner, int weapon, bool bnodamage);
void create_smoke(vec2 p); void create_smoke(vec2 p);
void create_spawn(vec2 p);
void create_sound(vec2 pos, int sound, int loopflags = 0); void create_sound(vec2 pos, int sound, int loopflags = 0);
class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0); class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0);
@ -339,6 +342,7 @@ game_world world;
gameobject::gameobject() gameobject::gameobject()
: entity(OBJTYPE_GAME) : entity(OBJTYPE_GAME)
{ {
gametype = GAMETYPE_DM;
game_over_tick = -1; game_over_tick = -1;
sudden_death = 0; sudden_death = 0;
round_start_tick = server_tick(); round_start_tick = server_tick();
@ -577,6 +581,8 @@ void player::init()
name[3] = 'b'; name[3] = 'b';
name[4] = 0; name[4] = 0;
client_id = -1; client_id = -1;
extrapowerflags = 0;
ninjaactivationtick = 0;
reset(); reset();
} }
@ -597,7 +603,7 @@ void player::destroy() { }
void player::respawn() void player::respawn()
{ {
health = PLAYER_MAXHEALTH; health = data->playerinfo[gameobj.gametype].maxhealth;
armor = 0; armor = 0;
jumped = 0; jumped = 0;
dead = false; dead = false;
@ -624,7 +630,7 @@ void player::respawn()
weapons[WEAPON_HAMMER].got = true; weapons[WEAPON_HAMMER].got = true;
weapons[WEAPON_HAMMER].ammo = -1; weapons[WEAPON_HAMMER].ammo = -1;
weapons[WEAPON_GUN].got = true; weapons[WEAPON_GUN].got = true;
weapons[WEAPON_GUN].ammo = 10; weapons[WEAPON_GUN].ammo = data->weapons[active_weapon].maxammo;
// TEMP DEBUG // TEMP DEBUG
weapons[WEAPON_ROCKET_BACKPACK].got = true; weapons[WEAPON_ROCKET_BACKPACK].got = true;
@ -633,7 +639,14 @@ void player::respawn()
active_weapon = WEAPON_GUN; active_weapon = WEAPON_GUN;
reload_timer = 0; reload_timer = 0;
// TEMP TEMP TEMP
/*ninjaactivationtick = server_tick();
weapons[WEAPON_NINJA].got = 1;
active_weapon = WEAPON_NINJA;*/
// Create sound and spawn effects
create_sound(pos, SOUND_PLAYER_SPAWN); create_sound(pos, SOUND_PLAYER_SPAWN);
create_spawn(pos);
} }
bool player::is_grounded() bool player::is_grounded()
@ -667,20 +680,111 @@ void player::release_hooks()
} }
} }
void player::handle_weapons() int player::handle_ninja()
{
if ((server_tick() - ninjaactivationtick) > (data->weapons[WEAPON_NINJA].duration * server_tickspeed() / 1000))
{
// time's up, return
active_weapon = WEAPON_GUN;
return 0;
}
// Check if it should activate
if ((input.fire && !(previnput.fire)) && (server_tick() > currentcooldown))
{
// ok then, activate ninja
attack_tick = server_tick();
activationdir = direction;
currentmovetime = data->weapons[WEAPON_NINJA].movetime * server_tickspeed() / 1000;
currentcooldown = data->weapons[WEAPON_NINJA].firedelay * server_tickspeed() / 1000 + server_tick();
// reset hit objects
numobjectshit = 0;
create_sound(pos, SOUND_NINJA_FIRE);
}
currentmovetime--;
if (currentmovetime == 0)
{
// reset player velocity
vel *= 0.2f;
//return MODIFIER_RETURNFLAGS_OVERRIDEWEAPON;
}
if (currentmovetime > 0)
{
// Set player velocity
vel = activationdir * data->weapons[WEAPON_NINJA].velocity;
vec2 oldpos = pos;
move_box(&defered_pos, &vel, vec2(phys_size, phys_size), 0.0f);
// reset velocity so the client doesn't predict stuff
vel = vec2(0.0f,0.0f);
if ((currentmovetime % 2) == 0)
{
create_smoke(pos);
}
// check if we hit anything along the way
{
int type = OBJTYPE_PLAYER;
entity *ents[64];
vec2 dir = pos - oldpos;
float radius = length(dir * 0.5f);
vec2 center = oldpos + dir * 0.5f;
int num = world.find_entities(center, radius, ents, 64, &type, 1);
for (int i = 0; i < num; i++)
{
// Check if entity is a player
if (ents[i] == this)
continue;
// make sure we haven't hit this object before
bool balreadyhit = false;
for (int j = 0; j < numobjectshit; j++)
{
if (hitobjects[j] == ents[i])
balreadyhit = true;
}
if (balreadyhit)
continue;
// check so we are sufficiently close
if (distance(ents[i]->pos, pos) > (phys_size * 2.0f))
continue;
// hit a player, give him damage and stuffs...
create_sound(ents[i]->pos, SOUND_NINJA_HIT);
// set his velocity to fast upward (for now)
hitobjects[numobjectshit++] = ents[i];
ents[i]->take_damage(vec2(0,10.0f), data->weapons[WEAPON_NINJA].meleedamage, client_id,-1);
}
}
return MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY | MODIFIER_RETURNFLAGS_OVERRIDEPOSITION | MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY;
}
return 0;
}
int player::handle_weapons()
{ {
// check reload timer // check reload timer
if(reload_timer) if(reload_timer)
{ {
reload_timer--; reload_timer--;
return; return 0;
}
if (active_weapon == WEAPON_NINJA)
{
// don't update other weapons while ninja is active
return handle_ninja();
} }
// switch weapon if wanted // switch weapon if wanted
if(input.activeweapon >= 0 && input.activeweapon < NUM_WEAPONS && weapons[input.activeweapon].got) if(input.activeweapon >= 0 && input.activeweapon < NUM_WEAPONS && weapons[input.activeweapon].got &&
data->weapons[active_weapon].duration <= 0)
active_weapon = input.activeweapon; active_weapon = input.activeweapon;
if(input.fire) if(!previnput.fire && input.fire)
{ {
if(reload_timer == 0) if(reload_timer == 0)
{ {
@ -690,6 +794,8 @@ void player::handle_weapons()
switch(active_weapon) switch(active_weapon)
{ {
case WEAPON_HAMMER: case WEAPON_HAMMER:
// reset objects hit
numobjectshit = 0;
create_sound(pos, SOUND_HAMMER_FIRE); create_sound(pos, SOUND_HAMMER_FIRE);
break; break;
@ -739,17 +845,89 @@ void player::handle_weapons()
} }
weapons[active_weapon].ammo--; weapons[active_weapon].ammo--;
attack_tick = server_tick();
reload_timer = data->weapons[active_weapon].firedelay * server_tickspeed() / 1000;
} }
else else
{ {
// click!!! click // click!!! click
// TODO: make sound here // TODO: make sound here
} }
}
}
// Update weapons
if (active_weapon == WEAPON_HAMMER && reload_timer > 0)
{
// Handle collisions
// only one that needs update (for now)
// do selection for the weapon and bash anything in it
// check if we hit anything along the way
int type = OBJTYPE_PLAYER;
entity *ents[64];
float reach = 20.0f;
vec2 lookdir(direction.x > 0.0f ? 1.0f : -1.0f, 0.0f);
vec2 dir = lookdir * data->weapons[active_weapon].meleereach;
float radius = length(dir * 0.5f);
vec2 center = pos + dir * 0.5f;
int num = world.find_entities(center, radius, ents, 64, &type, 1);
attack_tick = server_tick(); for (int i = 0; i < num; i++)
reload_timer = 10; // TODO: make this variable depending on weapon {
// Check if entity is a player
if (ents[i] == this)
continue;
// make sure we haven't hit this object before
bool balreadyhit = false;
for (int j = 0; j < numobjectshit; j++)
{
if (hitobjects[j] == ents[i])
balreadyhit = true;
}
if (balreadyhit)
continue;
// check so we are sufficiently close
if (distance(ents[i]->pos, pos) > (phys_size * 2.0f))
continue;
// hit a player, give him damage and stuffs...
// create sound for bash
//create_sound(ents[i]->pos, sound_impact);
// set his velocity to fast upward (for now)
create_smoke(ents[i]->pos);
hitobjects[numobjectshit++] = ents[i];
ents[i]->take_damage(vec2(0,10.0f), data->weapons[active_weapon].meleedamage, client_id, active_weapon);
player* target = (player*)ents[i];
vec2 dir;
if (length(target->pos - pos) > 0.0f)
dir = normalize(target->pos - pos);
else
dir = vec2(0,-1);
target->vel += dir * 10.0f + vec2(0,-10.0f);
} }
} }
if (data->weapons[active_weapon].ammoregentime)
{
// If equipped and not active, regen ammo?
if (reload_timer <= 0)
{
if (weapons[active_weapon].ammoregenstart < 0)
weapons[active_weapon].ammoregenstart = server_tick();
if ((server_tick() - weapons[active_weapon].ammoregenstart) >= data->weapons[active_weapon].ammoregentime * server_tickspeed() / 1000)
{
// Add some ammo
weapons[active_weapon].ammo = min(weapons[active_weapon].ammo + 1, data->weapons[active_weapon].maxammo);
weapons[active_weapon].ammoregenstart = -1;
}
}
else
{
weapons[active_weapon].ammoregenstart = -1;
}
}
return 0;
} }
void player::tick() void player::tick()
@ -851,7 +1029,7 @@ void player::tick()
if(hook_state == HOOK_GRABBED) if(hook_state == HOOK_GRABBED)
{ {
if(hooked_player) /*if(hooked_player)
hook_pos = hooked_player->pos; hook_pos = hooked_player->pos;
float d = distance(pos, hook_pos); float d = distance(pos, hook_pos);
@ -861,7 +1039,25 @@ void player::tick()
float accel = hook_drag_accel * (d/hook_length); float accel = hook_drag_accel * (d/hook_length);
vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, vel.x, -accel*dir.x*0.75f); vel.x = saturated_add(-hook_drag_speed, hook_drag_speed, vel.x, -accel*dir.x*0.75f);
vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, vel.y, -accel*dir.y); vel.y = saturated_add(-hook_drag_speed, hook_drag_speed, vel.y, -accel*dir.y);
} }*/
// Old version feels much better (to me atleast)
vec2 hookvel = normalize(hook_pos-pos)*hook_drag_accel;
// the hook as more power to drag you up then down.
// this makes it easier to get on top of an platform
if(hookvel.y > 0)
hookvel.y *= 0.3f;
// the hook will boost it's power if the player wants to move
// in that direction. otherwise it will dampen everything abit
if((hookvel.x < 0 && input.left) || (hookvel.x > 0 && input.right))
hookvel.x *= 0.95f;
else
hookvel.x *= 0.75f;
vec2 new_vel = vel+hookvel;
// check if we are under the legal limit for the hook
if(length(new_vel) < hook_drag_speed || length(new_vel) < length(vel))
vel = new_vel; // no problem. apply
} }
// fix influence of other players, collision + hook // fix influence of other players, collision + hook
@ -897,14 +1093,20 @@ void player::tick()
} }
// handle weapons // handle weapons
handle_weapons(); int retflags = handle_weapons();
if (!(retflags & (MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY | MODIFIER_RETURNFLAGS_OVERRIDEPOSITION)))
{
// add gravity // add gravity
if (!(retflags & MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY))
vel.y += gravity; vel.y += gravity;
// do the move // do the move
defered_pos = pos; defered_pos = pos;
move_box(&defered_pos, &vel, vec2(phys_size, phys_size), 0); move_box(&defered_pos, &vel, vec2(phys_size, phys_size), 0);
}
// Previnput
previnput = input;
return; return;
} }
@ -1085,16 +1287,16 @@ void powerup::tick()
switch (type) switch (type)
{ {
case POWERUP_TYPE_HEALTH: case POWERUP_TYPE_HEALTH:
if(pplayer->health < PLAYER_MAXHEALTH) if(pplayer->health < data->playerinfo[gameobj.gametype].maxhealth)
{ {
pplayer->health = min((int)PLAYER_MAXHEALTH, pplayer->health + 1); pplayer->health = min((int)data->playerinfo[gameobj.gametype].maxhealth, pplayer->health + 1);
respawntime = 20; respawntime = 20;
} }
break; break;
case POWERUP_TYPE_ARMOR: case POWERUP_TYPE_ARMOR:
if(pplayer->armor < PLAYER_MAXARMOR) if(pplayer->armor < data->playerinfo[gameobj.gametype].maxarmor)
{ {
pplayer->armor = min((int)PLAYER_MAXARMOR, pplayer->armor + 1); pplayer->armor = min((int)data->playerinfo[gameobj.gametype].maxarmor, pplayer->armor + 1);
respawntime = 20; respawntime = 20;
} }
break; break;
@ -1110,6 +1312,15 @@ void powerup::tick()
} }
} }
break; break;
case POWERUP_TYPE_NINJA:
{
// activate ninja on target player
pplayer->ninjaactivationtick = server_tick();
pplayer->weapons[WEAPON_NINJA].got = true;
pplayer->active_weapon = WEAPON_NINJA;
respawntime = 20;
break;
}
default: default:
break; break;
}; };
@ -1191,6 +1402,14 @@ void create_smoke(vec2 p)
ev->y = (int)p.y; ev->y = (int)p.y;
} }
void create_spawn(vec2 p)
{
// create the event
ev_spawn *ev = (ev_spawn *)events.create(EVENT_SPAWN, sizeof(ev_spawn));
ev->x = (int)p.x;
ev->y = (int)p.y;
}
void create_sound(vec2 pos, int sound, int loopingflags) void create_sound(vec2 pos, int sound, int loopingflags)
{ {
if (sound < 0) if (sound < 0)
@ -1265,7 +1484,7 @@ void mods_client_input(int client_id, void *input)
{ {
if(!world.paused) if(!world.paused)
{ {
players[client_id].previnput = players[client_id].input; //players[client_id].previnput = players[client_id].input;
players[client_id].input = *(player_input*)input; players[client_id].input = *(player_input*)input;
} }
} }
@ -1323,6 +1542,7 @@ void mods_message(int msg, int client_id)
void mods_init() void mods_init()
{ {
data = load_data_container("data/server.dat");
col_init(32); col_init(32);
int start, num; int start, num;

View file

@ -112,6 +112,7 @@ class gameobject : public entity
int sudden_death; int sudden_death;
public: public:
int gametype;
gameobject(); gameobject();
virtual void post_reset(); virtual void post_reset();
virtual void tick(); virtual void tick();
@ -190,11 +191,21 @@ class player : public entity
public: public:
static const int phys_size = 28; static const int phys_size = 28;
enum // what are these?
{
MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY = 1 << 0,
MODIFIER_RETURNFLAGS_OVERRIDEPOSITION = 1 << 1,
MODIFIER_RETURNFLAGS_OVERRIDEGRAVITY = 1 << 2,
};
// weapon info // weapon info
entity* hitobjects[10];
int numobjectshit;
struct weaponstat struct weaponstat
{ {
bool got; int ammoregenstart;
int ammo; int ammo;
bool got;
} weapons[NUM_WEAPONS]; } weapons[NUM_WEAPONS];
int active_weapon; int active_weapon;
int reload_timer; int reload_timer;
@ -219,6 +230,14 @@ public:
int health; int health;
int armor; int armor;
// ninja
baselib::vec2 activationdir;
int ninjaactivationtick;
int extrapowerflags;
int currentcooldown;
int currentactivation;
int currentmovetime;
int score; int score;
bool dead; bool dead;
@ -251,7 +270,8 @@ public:
void release_hooked(); void release_hooked();
void release_hooks(); void release_hooks();
void handle_weapons(); int handle_weapons();
int handle_ninja();
virtual void tick(); virtual void tick();
virtual void tick_defered(); virtual void tick_defered();