mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-14 16:40:57 +00:00
95295401a4
Added weapon balancing and tech control cvars to 3ZB2 DLL. Added Vampire and Ammogen techs to 3ZB2 game DLL. Fixed func_door_secret movement bug (when built with origin brush) in Zaero DLL. Fixed armor stacking bug in default Lazarus, missionpack, and Zaero DLLs. Removed unused tech cvars in default Lazarus DLL. Changed parsing of TE_BLASTER_COLORED tempent.
3388 lines
73 KiB
C
3388 lines
73 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
Copyright (C) 2000-2002 Mr. Hyde and Mad Dog
|
|
|
|
This file is part of Lazarus Quake 2 Mod source code.
|
|
|
|
Lazarus Quake 2 Mod source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Lazarus Quake 2 Mod source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Lazarus Quake 2 Mod source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "g_local.h"
|
|
|
|
qboolean Pickup_Weapon (edict_t *ent, edict_t *other);
|
|
void Use_Weapon (edict_t *ent, gitem_t *inv);
|
|
void Drop_Weapon (edict_t *ent, gitem_t *inv);
|
|
|
|
void Weapon_Blaster (edict_t *ent);
|
|
void Weapon_Shotgun (edict_t *ent);
|
|
void Weapon_SuperShotgun (edict_t *ent);
|
|
void Weapon_Machinegun (edict_t *ent);
|
|
void Weapon_Chaingun (edict_t *ent);
|
|
void Weapon_HyperBlaster (edict_t *ent);
|
|
void Weapon_RocketLauncher (edict_t *ent);
|
|
void Weapon_Grenade (edict_t *ent);
|
|
void Weapon_GrenadeLauncher (edict_t *ent);
|
|
void Weapon_Railgun (edict_t *ent);
|
|
void Weapon_BFG (edict_t *ent);
|
|
void Weapon_HomingMissileLauncher (edict_t *ent);
|
|
void Weapon_Null(edict_t *ent);
|
|
|
|
gitem_armor_t jacketarmor_info = { 25, 50, .30, .00, ARMOR_JACKET};
|
|
gitem_armor_t combatarmor_info = { 50, 100, .60, .30, ARMOR_COMBAT};
|
|
gitem_armor_t bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY};
|
|
|
|
int noweapon_index;
|
|
int jacket_armor_index;
|
|
int combat_armor_index;
|
|
int body_armor_index;
|
|
int power_screen_index;
|
|
int power_shield_index;
|
|
int shells_index;
|
|
int bullets_index;
|
|
int grenades_index;
|
|
int rockets_index;
|
|
int cells_index;
|
|
int slugs_index;
|
|
int fuel_index;
|
|
int homing_index;
|
|
int blaster_index;
|
|
int rl_index;
|
|
int hml_index;
|
|
int rg_index;
|
|
|
|
#define HEALTH_IGNORE_MAX 1
|
|
#define HEALTH_TIMED 2
|
|
#define HEALTH_SMALL 4
|
|
#define HEALTH_LARGE 8
|
|
|
|
#define NO_STUPID_SPINNING 4
|
|
#define NO_DROPTOFLOOR 8
|
|
#define SHOOTABLE 16
|
|
|
|
void Use_Quad (edict_t *ent, gitem_t *item);
|
|
void Use_Stasis (edict_t *ent, gitem_t *item);
|
|
static int quad_drop_timeout_hack;
|
|
|
|
|
|
//======================================================================
|
|
|
|
// Lazarus: damageable pickups
|
|
void item_die (edict_t *self,edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
|
{
|
|
//ZOID
|
|
// flags are important
|
|
if (strcmp(self->classname, "item_flag_team1") == 0) {
|
|
CTFResetFlag(CTF_TEAM1); // this will free self!
|
|
safe_bprintf(PRINT_HIGH, "The %s flag has returned!\n",
|
|
CTFTeamName(CTF_TEAM1));
|
|
return;
|
|
}
|
|
if (strcmp(self->classname, "item_flag_team2") == 0) {
|
|
CTFResetFlag(CTF_TEAM2); // this will free self!
|
|
safe_bprintf(PRINT_HIGH, "The %s flag has returned!\n",
|
|
CTFTeamName(CTF_TEAM1));
|
|
return;
|
|
}
|
|
// techs are important too
|
|
if (self->item && (self->item->flags & IT_TECH)) {
|
|
CTFRespawnTech(self); // this frees self!
|
|
return;
|
|
}
|
|
//ZOID
|
|
|
|
gi.WriteByte (svc_temp_entity);
|
|
gi.WriteByte (TE_EXPLOSION1);
|
|
gi.WritePosition (self->s.origin);
|
|
gi.multicast (self->s.origin, MULTICAST_PVS);
|
|
|
|
if (level.num_reflectors)
|
|
ReflectExplosion (TE_EXPLOSION1, self->s.origin);
|
|
|
|
if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (self, 30);
|
|
else
|
|
G_FreeEdict (self);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GetItemByIndex
|
|
===============
|
|
*/
|
|
gitem_t *GetItemByIndex (int index)
|
|
{
|
|
if (index == 0 || index >= game.num_items)
|
|
return NULL;
|
|
|
|
return &itemlist[index];
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GetMaxAmmoByIndex
|
|
===============
|
|
*/
|
|
int GetMaxAmmoByIndex (gclient_t *client, int item_index)
|
|
{
|
|
int value;
|
|
|
|
if (!client)
|
|
return 0;
|
|
|
|
if (item_index == shells_index)
|
|
value = client->pers.max_shells;
|
|
else if (item_index == bullets_index)
|
|
value = client->pers.max_bullets;
|
|
else if (item_index == grenades_index)
|
|
value = client->pers.max_grenades;
|
|
else if (item_index == rockets_index)
|
|
value = client->pers.max_rockets;
|
|
else if (item_index == cells_index)
|
|
value = client->pers.max_cells;
|
|
else if (item_index == slugs_index)
|
|
value = client->pers.max_slugs;
|
|
else if (item_index == fuel_index)
|
|
value = client->pers.max_fuel;
|
|
else if (item_index == homing_index)
|
|
value = client->pers.max_homing_rockets;
|
|
else
|
|
value = 0;
|
|
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GetMaxArmorByIndex
|
|
===============
|
|
*/
|
|
int GetMaxArmorByIndex (int item_index)
|
|
{
|
|
int value;
|
|
|
|
if (item_index == jacket_armor_index)
|
|
value = sk_max_armor_jacket->value;
|
|
else if (item_index == combat_armor_index)
|
|
value = sk_max_armor_combat->value;
|
|
else if (item_index == body_armor_index)
|
|
value = sk_max_armor_body->value;
|
|
else
|
|
value = 0;
|
|
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
FindItemByClassname
|
|
===============
|
|
*/
|
|
gitem_t *FindItemByClassname (char *classname)
|
|
{
|
|
int i;
|
|
gitem_t *it;
|
|
|
|
it = itemlist;
|
|
for (i=0 ; i<game.num_items ; i++, it++)
|
|
{
|
|
if (!it->classname)
|
|
continue;
|
|
if (!Q_stricmp(it->classname, classname))
|
|
return it;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
FindItem
|
|
===============
|
|
*/
|
|
gitem_t *FindItem (char *pickup_name)
|
|
{
|
|
int i;
|
|
gitem_t *it;
|
|
|
|
it = itemlist;
|
|
for (i=0 ; i<game.num_items ; i++, it++)
|
|
{
|
|
if (!it->pickup_name)
|
|
continue;
|
|
if (!Q_stricmp(it->pickup_name, pickup_name))
|
|
return it;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void DoRespawn (edict_t *ent)
|
|
{
|
|
if (ent->team)
|
|
{
|
|
edict_t *master;
|
|
int count;
|
|
int choice;
|
|
|
|
master = ent->teammaster;
|
|
|
|
//ZOID
|
|
//in ctf, when we are weapons stay, only the master of a team of weapons
|
|
//is spawned
|
|
if (ctf->value &&
|
|
((int)dmflags->value & DF_WEAPONS_STAY) &&
|
|
master->item && (master->item->flags & IT_WEAPON))
|
|
ent = master;
|
|
else {
|
|
//ZOID
|
|
for (count = 0, ent = master; ent; ent = ent->chain, count++)
|
|
;
|
|
|
|
// choice = rand() % count;
|
|
choice = count ? rand() % count : 0;
|
|
|
|
for (count = 0, ent = master; count < choice; ent = ent->chain, count++)
|
|
;
|
|
}
|
|
}
|
|
|
|
ent->svflags &= ~SVF_NOCLIENT;
|
|
if (ent->spawnflags & SHOOTABLE)
|
|
{
|
|
ent->solid = SOLID_BBOX;
|
|
ent->clipmask |= MASK_MONSTERSOLID;
|
|
if (!ent->health)
|
|
ent->health = 20;
|
|
ent->takedamage = DAMAGE_YES;
|
|
ent->die = item_die;
|
|
}
|
|
else
|
|
ent->solid = SOLID_TRIGGER;
|
|
gi.linkentity (ent);
|
|
|
|
// send an effect
|
|
ent->s.event = EV_ITEM_RESPAWN;
|
|
}
|
|
|
|
void SetRespawn (edict_t *ent, float delay)
|
|
{
|
|
ent->flags |= FL_RESPAWN;
|
|
ent->svflags |= SVF_NOCLIENT;
|
|
ent->solid = SOLID_NOT;
|
|
ent->nextthink = level.time + delay;
|
|
ent->think = DoRespawn;
|
|
gi.linkentity (ent);
|
|
}
|
|
|
|
|
|
//======================================================================
|
|
|
|
qboolean Pickup_Powerup (edict_t *ent, edict_t *other)
|
|
{
|
|
int quantity;
|
|
|
|
quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)];
|
|
if ((skill->value == 1 && quantity >= sk_powerup_max->value) || (skill->value >= 2 && quantity >= (sk_powerup_max->value - 1)))
|
|
return false;
|
|
|
|
if ((coop->value) && (ent->item->flags & IT_STAY_COOP) && (quantity > 0))
|
|
return false;
|
|
|
|
// Lazarus: Don't allow more than one of some items
|
|
#ifdef FLASHLIGHT_MOD
|
|
if ( !Q_stricmp(ent->classname,"item_flashlight") && quantity >= 1 ) return false;
|
|
#endif
|
|
#ifdef JETPACK_MOD
|
|
if ( !Q_stricmp(ent->classname,"item_jetpack") )
|
|
{
|
|
gitem_t *fuel;
|
|
|
|
if ( quantity >= 1 )
|
|
return false;
|
|
|
|
fuel = FindItem("fuel");
|
|
if (ent->count < 0)
|
|
{
|
|
other->client->jetpack_infinite = true;
|
|
Add_Ammo(other,fuel,10000);
|
|
}
|
|
else
|
|
{
|
|
other->client->jetpack_infinite = false;
|
|
Add_Ammo(other,fuel,ent->count);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
|
|
|
|
#ifdef FLASHLIGHT_MOD
|
|
// DON'T Instant-use flashlight
|
|
if (ent->item->use == Use_Flashlight) return true;
|
|
#endif
|
|
|
|
if (deathmatch->value)
|
|
{
|
|
if (!(ent->spawnflags & DROPPED_ITEM) )
|
|
SetRespawn (ent, ent->item->quantity);
|
|
|
|
#ifdef JETPACK_MOD
|
|
// DON'T Instant-use Jetpack
|
|
if (ent->item->use == Use_Jet) return true;
|
|
#endif
|
|
|
|
if (((int)dmflags->value & DF_INSTANT_ITEMS) || ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM))
|
|
|| other->is_bot) // Knightmare- bots always instant-use items
|
|
{
|
|
if ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM))
|
|
quad_drop_timeout_hack = (ent->nextthink - level.time) / FRAMETIME;
|
|
ent->item->use (other, ent->item);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Drop_General (edict_t *ent, gitem_t *item)
|
|
{
|
|
Drop_Item (ent, item);
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
}
|
|
|
|
#ifdef JETPACK_MOD
|
|
void Drop_Jetpack (edict_t *ent, gitem_t *item)
|
|
{
|
|
if (ent->client->jetpack)
|
|
safe_cprintf(ent,PRINT_HIGH,"Cannot drop jetpack in use\n");
|
|
else
|
|
{
|
|
edict_t *dropped;
|
|
|
|
dropped = Drop_Item (ent, item);
|
|
if (ent->client->jetpack_infinite)
|
|
{
|
|
dropped->count = -1;
|
|
ent->client->pers.inventory[fuel_index] = 0;
|
|
ent->client->jetpack_infinite = false;
|
|
}
|
|
else
|
|
{
|
|
dropped->count = ent->client->pers.inventory[fuel_index];
|
|
if (dropped->count > 500)
|
|
dropped->count = 500;
|
|
ent->client->pers.inventory[fuel_index] -= dropped->count;
|
|
}
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//======================================================================
|
|
|
|
qboolean Pickup_Adrenaline (edict_t *ent, edict_t *other)
|
|
{
|
|
if (!deathmatch->value) {
|
|
other->max_health += 1;
|
|
// Knightmare- copy max health to client_persistant_t
|
|
// Fixes health reverting to prev max_health value on
|
|
// map change when game is not saved first
|
|
if (other->client)
|
|
other->client->pers.max_health = other->max_health;
|
|
}
|
|
|
|
if (other->health < other->max_health)
|
|
other->health = other->max_health;
|
|
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, ent->item->quantity);
|
|
|
|
return true;
|
|
}
|
|
|
|
qboolean Pickup_AncientHead (edict_t *ent, edict_t *other)
|
|
{
|
|
other->max_health += 2;
|
|
// Knightmare- copy max health to client_persistant_t
|
|
// Fixes health reverting to prev max_health value on
|
|
// map change when game is not saved first
|
|
if (other->client)
|
|
other->client->pers.max_health = other->max_health;
|
|
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, ent->item->quantity);
|
|
|
|
return true;
|
|
}
|
|
|
|
qboolean Pickup_Bandolier (edict_t *ent, edict_t *other)
|
|
{
|
|
gitem_t *item;
|
|
|
|
//Knightmare- override ammo pickup values with cvars
|
|
SetAmmoPickupValues ();
|
|
|
|
if (other->client->pers.max_bullets < sk_bando_bullets->value)
|
|
other->client->pers.max_bullets = sk_bando_bullets->value;
|
|
if (other->client->pers.max_shells < sk_bando_shells->value)
|
|
other->client->pers.max_shells = sk_bando_shells->value;
|
|
if (other->client->pers.max_cells < sk_bando_cells->value)
|
|
other->client->pers.max_cells = sk_bando_cells->value;
|
|
if (other->client->pers.max_slugs < sk_bando_slugs->value)
|
|
other->client->pers.max_slugs = sk_bando_slugs->value;
|
|
if (other->client->pers.max_fuel < sk_bando_fuel->value)
|
|
other->client->pers.max_fuel = sk_bando_fuel->value;
|
|
|
|
item = FindItem("Bullets");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Shells");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, ent->item->quantity);
|
|
|
|
return true;
|
|
}
|
|
|
|
qboolean Pickup_Pack (edict_t *ent, edict_t *other)
|
|
{
|
|
gitem_t *item;
|
|
|
|
//Knightmare- override ammo pickup values with cvars
|
|
SetAmmoPickupValues ();
|
|
|
|
if (other->client->pers.max_bullets < sk_pack_bullets->value)
|
|
other->client->pers.max_bullets = sk_pack_bullets->value;
|
|
if (other->client->pers.max_shells < sk_pack_shells->value)
|
|
other->client->pers.max_shells = sk_pack_shells->value;
|
|
if (other->client->pers.max_rockets < sk_pack_rockets->value)
|
|
other->client->pers.max_rockets = sk_pack_rockets->value;
|
|
if (other->client->pers.max_grenades < sk_pack_grenades->value)
|
|
other->client->pers.max_grenades = sk_pack_grenades->value;
|
|
if (other->client->pers.max_cells < sk_pack_cells->value)
|
|
other->client->pers.max_cells = sk_pack_cells->value;
|
|
if (other->client->pers.max_slugs < sk_pack_slugs->value)
|
|
other->client->pers.max_slugs = sk_pack_slugs->value;
|
|
if (other->client->pers.max_homing_rockets < sk_pack_rockets->value)
|
|
other->client->pers.max_homing_rockets = sk_pack_rockets->value;
|
|
if (other->client->pers.max_fuel < sk_pack_fuel->value)
|
|
other->client->pers.max_fuel = sk_pack_fuel->value;
|
|
|
|
item = FindItem("Bullets");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Shells");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Cells");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Grenades");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Rockets");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Slugs");
|
|
if (item)
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, ent->item->quantity);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Knightmare added- Ammogen tech-spawned backpack
|
|
qboolean Pickup_AmmogenPack (edict_t *ent, edict_t *other)
|
|
{
|
|
gitem_t *item;
|
|
|
|
if (!ent || !other)
|
|
return false;
|
|
|
|
// Knightmare- override ammo pickup values with cvars
|
|
SetAmmoPickupValues ();
|
|
|
|
item = FindItem("Bullets");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Shells");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Cells");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Grenades");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Rockets");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Slugs");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("Homing Rockets");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
item = FindItem("fuel");
|
|
if (item && other->client->pers.inventory[ITEM_INDEX(item)])
|
|
Add_Ammo (other, item, item->quantity);
|
|
|
|
return true;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void Use_Quad (edict_t *ent, gitem_t *item)
|
|
{
|
|
int timeout;
|
|
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
|
|
if (quad_drop_timeout_hack)
|
|
{
|
|
timeout = quad_drop_timeout_hack;
|
|
quad_drop_timeout_hack = 0;
|
|
}
|
|
else
|
|
{
|
|
timeout = (sk_quad_time->value * 10);
|
|
}
|
|
|
|
if (ent->client->quad_framenum > level.framenum)
|
|
ent->client->quad_framenum += timeout;
|
|
else
|
|
ent->client->quad_framenum = level.framenum + timeout;
|
|
|
|
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void Use_Breather (edict_t *ent, gitem_t *item)
|
|
{
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
|
|
if (ent->client->breather_framenum > level.framenum)
|
|
ent->client->breather_framenum += (sk_breather_time->value * 10);
|
|
else
|
|
ent->client->breather_framenum = level.framenum + (sk_breather_time->value * 10);
|
|
|
|
// gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void Use_Envirosuit (edict_t *ent, gitem_t *item)
|
|
{
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
|
|
if (ent->client->enviro_framenum > level.framenum)
|
|
ent->client->enviro_framenum += (sk_enviro_time->value * 10);
|
|
else
|
|
ent->client->enviro_framenum = level.framenum + (sk_enviro_time->value * 10);
|
|
|
|
// gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void Use_Invulnerability (edict_t *ent, gitem_t *item)
|
|
{
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
|
|
if (ent->client->invincible_framenum > level.framenum)
|
|
ent->client->invincible_framenum += (sk_inv_time->value * 10);
|
|
else
|
|
ent->client->invincible_framenum = level.framenum + (sk_inv_time->value * 10);
|
|
|
|
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
void Use_Silencer (edict_t *ent, gitem_t *item)
|
|
{
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
ent->client->silencer_shots += sk_silencer_shots->value;
|
|
|
|
// gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
qboolean Pickup_Key (edict_t *ent, edict_t *other)
|
|
{
|
|
if (coop->value)
|
|
{
|
|
if (strcmp(ent->classname, "key_power_cube") == 0)
|
|
{
|
|
if (other->client->pers.power_cubes & ((ent->spawnflags & 0x0000ff00)>> 8))
|
|
return false;
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
|
|
other->client->pers.power_cubes |= ((ent->spawnflags & 0x0000ff00) >> 8);
|
|
}
|
|
else
|
|
{
|
|
if (other->client->pers.inventory[ITEM_INDEX(ent->item)])
|
|
return false;
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)] = 1;
|
|
}
|
|
return true;
|
|
}
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
|
|
return true;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
qboolean Add_Ammo (edict_t *ent, gitem_t *item, int count)
|
|
{
|
|
int index;
|
|
int max;
|
|
|
|
if (!ent->client)
|
|
return false;
|
|
|
|
if (item->tag == AMMO_BULLETS)
|
|
max = ent->client->pers.max_bullets;
|
|
else if (item->tag == AMMO_SHELLS)
|
|
max = ent->client->pers.max_shells;
|
|
else if (item->tag == AMMO_ROCKETS)
|
|
max = ent->client->pers.max_rockets;
|
|
else if (item->tag == AMMO_GRENADES)
|
|
max = ent->client->pers.max_grenades;
|
|
else if (item->tag == AMMO_CELLS)
|
|
max = ent->client->pers.max_cells;
|
|
else if (item->tag == AMMO_SLUGS)
|
|
max = ent->client->pers.max_slugs;
|
|
else if (item->tag == AMMO_HOMING_ROCKETS)
|
|
max = ent->client->pers.max_homing_rockets;
|
|
else if (item->tag == AMMO_FUEL)
|
|
max = ent->client->pers.max_fuel;
|
|
else
|
|
return false;
|
|
|
|
index = ITEM_INDEX(item);
|
|
|
|
if (ent->client->pers.inventory[index] >= max)
|
|
return false;
|
|
|
|
ent->client->pers.inventory[index] += count;
|
|
|
|
if (ent->client->pers.inventory[index] > max)
|
|
ent->client->pers.inventory[index] = max;
|
|
|
|
return true;
|
|
}
|
|
|
|
//Knightmare- this function overrides ammo pickup values with cvars
|
|
void SetAmmoPickupValues (void)
|
|
{
|
|
gitem_t *item;
|
|
|
|
item = FindItem("Shells");
|
|
if (item)
|
|
item->quantity = sk_box_shells->value;
|
|
|
|
item = FindItem("Bullets");
|
|
if (item)
|
|
item->quantity = sk_box_bullets->value;
|
|
|
|
item = FindItem("Grenades");
|
|
if (item)
|
|
item->quantity = sk_box_grenades->value;
|
|
|
|
item = FindItem("Rockets");
|
|
if (item)
|
|
item->quantity = sk_box_rockets->value;
|
|
|
|
item = FindItem("Homing Rockets");
|
|
if (item)
|
|
item->quantity = sk_box_rockets->value;
|
|
|
|
item = FindItem("Cells");
|
|
if (item)
|
|
item->quantity = sk_box_cells->value;
|
|
|
|
item = FindItem("Slugs");
|
|
if (item)
|
|
item->quantity = sk_box_slugs->value;
|
|
|
|
item = FindItem("Fuel");
|
|
if (item)
|
|
item->quantity = sk_box_fuel->value;
|
|
|
|
item = FindItemByClassname("item_health_small");
|
|
if (item)
|
|
item->quantity = sk_health_bonus_value->value;
|
|
}
|
|
|
|
qboolean Pickup_Ammo (edict_t *ent, edict_t *other)
|
|
{
|
|
int oldcount;
|
|
int count;
|
|
qboolean weapon;
|
|
|
|
//Knightmare- override ammo pickup values with cvars
|
|
SetAmmoPickupValues ();
|
|
|
|
weapon = (ent->item->flags & IT_WEAPON);
|
|
if ( (weapon) && ( (int)dmflags->value & DF_INFINITE_AMMO ) )
|
|
count = 1000;
|
|
else if (ent->count)
|
|
count = ent->count;
|
|
else
|
|
count = ent->item->quantity;
|
|
|
|
oldcount = other->client->pers.inventory[ITEM_INDEX(ent->item)];
|
|
|
|
if (!Add_Ammo (other, ent->item, count))
|
|
return false;
|
|
|
|
if (weapon && !oldcount)
|
|
{
|
|
if (other->client->pers.weapon != ent->item && ( !deathmatch->value || other->client->pers.weapon == FindItem("Blaster") || other->client->pers.weapon == FindItem("No weapon") ) )
|
|
other->client->newweapon = ent->item;
|
|
}
|
|
|
|
if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)) && (deathmatch->value))
|
|
SetRespawn (ent, 30);
|
|
return true;
|
|
}
|
|
|
|
void Drop_Ammo (edict_t *ent, gitem_t *item)
|
|
{
|
|
edict_t *dropped;
|
|
int index;
|
|
|
|
index = ITEM_INDEX(item);
|
|
dropped = Drop_Item (ent, item);
|
|
if (ent->client->pers.inventory[index] >= item->quantity)
|
|
dropped->count = item->quantity;
|
|
else
|
|
dropped->count = ent->client->pers.inventory[index];
|
|
|
|
if (ent->client->pers.weapon &&
|
|
ent->client->pers.weapon->tag == AMMO_GRENADES &&
|
|
item->tag == AMMO_GRENADES &&
|
|
ent->client->pers.inventory[index] - dropped->count <= 0) {
|
|
safe_cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
|
|
G_FreeEdict(dropped);
|
|
return;
|
|
}
|
|
|
|
ent->client->pers.inventory[index] -= dropped->count;
|
|
ValidateSelectedItem (ent);
|
|
}
|
|
|
|
|
|
//======================================================================
|
|
|
|
void MegaHealth_think (edict_t *self)
|
|
{
|
|
if (self->owner->health > self->owner->max_health
|
|
//ZOID
|
|
&& !CTFHasRegeneration(self->owner))
|
|
//ZOID
|
|
{
|
|
self->nextthink = level.time + 1;
|
|
self->owner->health -= 1;
|
|
return;
|
|
}
|
|
|
|
if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (self, 20);
|
|
else
|
|
G_FreeEdict (self);
|
|
}
|
|
|
|
qboolean Pickup_Health (edict_t *ent, edict_t *other)
|
|
{
|
|
if (!(ent->style & HEALTH_IGNORE_MAX))
|
|
if (other->health >= other->max_health)
|
|
return false;
|
|
|
|
//ZOID
|
|
if (ctf->value && other->health >= 250 && ent->count > 25)
|
|
return false;
|
|
//ZOID
|
|
|
|
other->health += ent->count;
|
|
|
|
//ZOID
|
|
if (ctf->value && other->health > 250 && ent->count > 25)
|
|
other->health = 250;
|
|
//ZOID
|
|
|
|
if (!(ent->style & HEALTH_IGNORE_MAX))
|
|
{
|
|
if (other->health > other->max_health)
|
|
other->health = other->max_health;
|
|
}
|
|
|
|
//ZOID
|
|
if (ent->style & HEALTH_TIMED
|
|
&& !CTFHasRegeneration(other))
|
|
//ZOID
|
|
{
|
|
ent->think = MegaHealth_think;
|
|
ent->nextthink = level.time + 5;
|
|
ent->owner = other;
|
|
ent->flags |= FL_RESPAWN;
|
|
ent->svflags |= SVF_NOCLIENT;
|
|
ent->solid = SOLID_NOT;
|
|
}
|
|
else
|
|
{
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, 30);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
int ArmorIndex (edict_t *ent)
|
|
{
|
|
if (!ent->client)
|
|
return 0;
|
|
|
|
if (ent->client->pers.inventory[jacket_armor_index] > 0)
|
|
return jacket_armor_index;
|
|
|
|
if (ent->client->pers.inventory[combat_armor_index] > 0)
|
|
return combat_armor_index;
|
|
|
|
if (ent->client->pers.inventory[body_armor_index] > 0)
|
|
return body_armor_index;
|
|
|
|
return 0;
|
|
}
|
|
|
|
qboolean Pickup_Armor (edict_t *ent, edict_t *other)
|
|
{
|
|
int old_armor_index;
|
|
gitem_armor_t *oldinfo;
|
|
gitem_armor_t *newinfo;
|
|
int newcount;
|
|
float salvage;
|
|
int salvagecount;
|
|
int armor_maximum, old_armor_maximum;
|
|
|
|
// set armor cap
|
|
if (ent->item->tag == ARMOR_JACKET)
|
|
armor_maximum = sk_max_armor_jacket->value;
|
|
else if (ent->item->tag == ARMOR_COMBAT)
|
|
armor_maximum = sk_max_armor_combat->value;
|
|
else // ARMOR_BODY
|
|
armor_maximum = sk_max_armor_body->value;
|
|
|
|
// get info on new armor
|
|
newinfo = (gitem_armor_t *)ent->item->info;
|
|
|
|
old_armor_index = ArmorIndex (other);
|
|
|
|
// handle armor shards specially
|
|
if (ent->item->tag == ARMOR_SHARD)
|
|
{
|
|
if (!old_armor_index)
|
|
other->client->pers.inventory[jacket_armor_index] = sk_armor_bonus_value->value;
|
|
else
|
|
other->client->pers.inventory[old_armor_index] += sk_armor_bonus_value->value;
|
|
}
|
|
|
|
// if player has no armor, just use it
|
|
else if (!old_armor_index)
|
|
{
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)] = newinfo->base_count;
|
|
}
|
|
|
|
// use the better armor
|
|
else
|
|
{
|
|
// get info on old armor
|
|
if (old_armor_index == jacket_armor_index) {
|
|
oldinfo = &jacketarmor_info;
|
|
old_armor_maximum = sk_max_armor_jacket->value;
|
|
}
|
|
else if (old_armor_index == combat_armor_index) {
|
|
oldinfo = &combatarmor_info;
|
|
old_armor_maximum = sk_max_armor_combat->value;
|
|
}
|
|
else { // (old_armor_index == body_armor_index)
|
|
oldinfo = &bodyarmor_info;
|
|
old_armor_maximum = sk_max_armor_body->value;
|
|
}
|
|
|
|
// if stronger than current armor (always pick up)
|
|
if (newinfo->normal_protection > oldinfo->normal_protection)
|
|
{
|
|
// calc new armor values
|
|
salvage = oldinfo->normal_protection / newinfo->normal_protection;
|
|
salvagecount = salvage * other->client->pers.inventory[old_armor_index];
|
|
newcount = newinfo->base_count + salvagecount;
|
|
// if (newcount > newinfo->max_count)
|
|
// newcount = newinfo->max_count;
|
|
if (newcount > armor_maximum)
|
|
newcount = armor_maximum;
|
|
|
|
// zero count of old armor so it goes away
|
|
other->client->pers.inventory[old_armor_index] = 0;
|
|
|
|
// change armor to new item with computed value
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)] = newcount;
|
|
}
|
|
else
|
|
{
|
|
// calc new armor values
|
|
salvage = newinfo->normal_protection / oldinfo->normal_protection;
|
|
salvagecount = salvage * newinfo->base_count;
|
|
newcount = other->client->pers.inventory[old_armor_index] + salvagecount;
|
|
// if (newcount > oldinfo->max_count)
|
|
// newcount = oldinfo->max_count;
|
|
if (newcount > old_armor_maximum)
|
|
newcount = old_armor_maximum;
|
|
|
|
// if we're already maxed out then we don't need the new armor
|
|
if (other->client->pers.inventory[old_armor_index] >= newcount)
|
|
return false;
|
|
|
|
// update current armor value
|
|
other->client->pers.inventory[old_armor_index] = newcount;
|
|
}
|
|
}
|
|
|
|
if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
|
|
SetRespawn (ent, 20);
|
|
|
|
return true;
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
// Knightmare- rewrote this so it's handled properly
|
|
int PowerArmorType (edict_t *ent)
|
|
{
|
|
if (!ent->client)
|
|
return POWER_ARMOR_NONE;
|
|
|
|
// if (!(ent->flags & FL_POWER_ARMOR))
|
|
// return POWER_ARMOR_NONE;
|
|
|
|
// if (ent->client->pers.inventory[power_shield_index] > 0)
|
|
if (ent->flags & FL_POWER_SHIELD)
|
|
return POWER_ARMOR_SHIELD;
|
|
|
|
// if (ent->client->pers.inventory[power_screen_index] > 0)
|
|
if (ent->flags & FL_POWER_SCREEN)
|
|
return POWER_ARMOR_SCREEN;
|
|
|
|
return POWER_ARMOR_NONE;
|
|
}
|
|
|
|
//Knightmare- rewrote this to differentiate between power shield and power screen
|
|
void Use_PowerArmor (edict_t *ent, gitem_t *item)
|
|
{
|
|
int index;
|
|
|
|
if (item == FindItemByClassname("item_power_screen"))
|
|
{ //if player has an active power shield, deacivate that and activate power screen
|
|
if (ent->flags & FL_POWER_SHIELD)
|
|
{
|
|
index = ITEM_INDEX(FindItem("cells"));
|
|
if (!ent->client->pers.inventory[index])
|
|
{
|
|
safe_cprintf (ent, PRINT_HIGH, "No cells for power screen.\n");
|
|
return;
|
|
}
|
|
ent->flags &= ~FL_POWER_SHIELD;
|
|
ent->flags |= FL_POWER_SCREEN;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
//if they have an active power screen, deactivate that
|
|
else if (ent->flags & FL_POWER_SCREEN)
|
|
{
|
|
ent->flags &= ~FL_POWER_SCREEN;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else //activate power screen
|
|
{
|
|
index = ITEM_INDEX(FindItem("cells"));
|
|
if (!ent->client->pers.inventory[index])
|
|
{
|
|
safe_cprintf (ent, PRINT_HIGH, "No cells for power screen.\n");
|
|
return;
|
|
}
|
|
ent->flags |= FL_POWER_SCREEN;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
|
|
|
|
}
|
|
}
|
|
else if (item == FindItemByClassname("item_power_shield"))
|
|
{ //if player has an active power screen, deacivate that and activate power shield
|
|
if (ent->flags & FL_POWER_SCREEN)
|
|
{
|
|
index = ITEM_INDEX(FindItem("cells"));
|
|
if (!ent->client->pers.inventory[index])
|
|
{
|
|
safe_cprintf (ent, PRINT_HIGH, "No cells for power shield.\n");
|
|
return;
|
|
}
|
|
ent->flags &= ~FL_POWER_SCREEN;
|
|
ent->flags |= FL_POWER_SHIELD;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
//if they have an active power shield, deactivate it
|
|
else if (ent->flags & FL_POWER_SHIELD)
|
|
{
|
|
ent->flags &= ~FL_POWER_SHIELD;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else //activate power shield
|
|
{
|
|
index = ITEM_INDEX(FindItem("cells"));
|
|
if (!ent->client->pers.inventory[index])
|
|
{
|
|
safe_cprintf (ent, PRINT_HIGH, "No cells for power shield.\n");
|
|
return;
|
|
}
|
|
ent->flags |= FL_POWER_SHIELD;
|
|
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
qboolean Pickup_PowerArmor (edict_t *ent, edict_t *other)
|
|
{
|
|
int quantity;
|
|
|
|
quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)];
|
|
|
|
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
|
|
|
|
if (deathmatch->value)
|
|
{
|
|
if (!(ent->spawnflags & DROPPED_ITEM) )
|
|
SetRespawn (ent, ent->item->quantity);
|
|
// auto-use for DM only if we didn't already have one
|
|
if (!quantity
|
|
//Knightmare- don't switch to power screen if we already have a power shield active
|
|
&& !(ent->item == FindItemByClassname("item_power_screen") && (other->flags & FL_POWER_SHIELD)))
|
|
ent->item->use (other, ent->item);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Knightmare- rewrote this so it's handled properly
|
|
void Drop_PowerArmor (edict_t *ent, gitem_t *item)
|
|
{
|
|
if (item == FindItemByClassname("item_power_shield"))
|
|
{
|
|
if ((ent->flags & FL_POWER_SHIELD) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1))
|
|
Use_PowerArmor (ent, item);
|
|
}
|
|
else
|
|
if ((ent->flags & FL_POWER_SCREEN) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1))
|
|
Use_PowerArmor (ent, item);
|
|
Drop_General (ent, item);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
/*
|
|
===============
|
|
Touch_Item
|
|
===============
|
|
*/
|
|
void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
|
|
{
|
|
qboolean taken;
|
|
|
|
if (!other->client)
|
|
return;
|
|
if (other->health < 1)
|
|
return; // dead people can't pickup
|
|
if (!ent->item->pickup)
|
|
return; // not a grabbable item?
|
|
|
|
taken = ent->item->pickup(ent, other);
|
|
|
|
if (taken)
|
|
{
|
|
// flash the screen
|
|
other->client->bonus_alpha = 0.25;
|
|
|
|
// show icon and name on status bar
|
|
other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(ent->item->icon);
|
|
other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+ITEM_INDEX(ent->item);
|
|
other->client->pickup_msg_time = level.time + 3.0;
|
|
|
|
// change selected item
|
|
if (ent->item->use)
|
|
other->client->pers.selected_item = other->client->ps.stats[STAT_SELECTED_ITEM] = ITEM_INDEX(ent->item);
|
|
|
|
if (ent->item->pickup == Pickup_Health)
|
|
{
|
|
if (ent->style == (HEALTH_IGNORE_MAX|HEALTH_TIMED)) // if (ent->count == 100)
|
|
gi.sound(other, CHAN_ITEM, gi.soundindex("items/m_health.wav"), 1, ATTN_NORM, 0);
|
|
else if (ent->style & HEALTH_SMALL) // if (ent->count == sk_health_bonus_value->value)
|
|
gi.sound(other, CHAN_ITEM, gi.soundindex("items/s_health.wav"), 1, ATTN_NORM, 0);
|
|
else if (ent->style & HEALTH_LARGE) // if (ent->count == 25)
|
|
gi.sound(other, CHAN_ITEM, gi.soundindex("items/l_health.wav"), 1, ATTN_NORM, 0);
|
|
else // if (ent->count == 10)
|
|
gi.sound(other, CHAN_ITEM, gi.soundindex("items/n_health.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else if (ent->item->pickup_sound)
|
|
{
|
|
gi.sound(other, CHAN_ITEM, gi.soundindex(ent->item->pickup_sound), 1, ATTN_NORM, 0);
|
|
}
|
|
}
|
|
|
|
if (!(ent->spawnflags & ITEM_TARGETS_USED))
|
|
{
|
|
G_UseTargets (ent, other);
|
|
ent->spawnflags |= ITEM_TARGETS_USED;
|
|
}
|
|
|
|
if (!taken)
|
|
return;
|
|
|
|
DeleteReflection (ent, -1);
|
|
|
|
if (!((coop->value) && (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))
|
|
{
|
|
if (ent->flags & FL_RESPAWN)
|
|
ent->flags &= ~FL_RESPAWN;
|
|
else
|
|
G_FreeEdict (ent);
|
|
}
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
/*static*/ void drop_temp_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
|
|
{
|
|
if (other == ent->owner)
|
|
return;
|
|
|
|
Touch_Item (ent, other, plane, surf);
|
|
}
|
|
|
|
/*static*/ void drop_make_touchable (edict_t *ent)
|
|
{
|
|
ent->touch = Touch_Item;
|
|
if (deathmatch->value)
|
|
{
|
|
ent->nextthink = level.time + 29;
|
|
ent->think = G_FreeEdict;
|
|
}
|
|
}
|
|
|
|
edict_t *Drop_Item (edict_t *ent, gitem_t *item)
|
|
{
|
|
edict_t *dropped;
|
|
vec3_t forward, right;
|
|
vec3_t offset;
|
|
|
|
dropped = G_Spawn();
|
|
|
|
dropped->classname = item->classname;
|
|
dropped->item = item;
|
|
dropped->spawnflags = DROPPED_ITEM;
|
|
dropped->s.skinnum = item->world_model_skinnum; // Knightmare- skinnum specified in item table
|
|
dropped->s.effects = item->world_model_flags;
|
|
dropped->s.renderfx = RF_GLOW | RF_IR_VISIBLE;
|
|
dropped->s.angles[1] = ent->s.angles[1]; // Knightmare- preserve yaw from dropping entity
|
|
// mxd- Actually randomize it a bit (and not in 0 .. 32767 range like rand() does)
|
|
/*if (rand() > 0.5) // randomize it a bit
|
|
dropped->s.angles[1] += rand()*45;
|
|
else
|
|
dropped->s.angles[1] -= rand()*45;*/
|
|
dropped->s.angles[1] += crandom() * 45;
|
|
|
|
// VectorSet (dropped->mins, -15, -15, -15);
|
|
// VectorSet (dropped->maxs, 15, 15, 15);
|
|
VectorSet (dropped->mins, -16, -16, -16);
|
|
VectorSet (dropped->maxs, 16, 16, 16);
|
|
gi.setmodel (dropped, dropped->item->world_model);
|
|
dropped->solid = SOLID_TRIGGER;
|
|
dropped->movetype = MOVETYPE_TOSS;
|
|
dropped->touch = drop_temp_touch;
|
|
dropped->owner = ent;
|
|
|
|
// Lazarus: for monster-dropped health
|
|
if (item->pickup == Pickup_Health)
|
|
{
|
|
dropped->count = item->quantity;
|
|
if (item->quantity == sk_health_bonus_value->value)
|
|
dropped->style |= HEALTH_IGNORE_MAX;
|
|
if (item->quantity == 100)
|
|
dropped->style |= HEALTH_IGNORE_MAX | HEALTH_TIMED;
|
|
}
|
|
|
|
if (ent->client)
|
|
{
|
|
trace_t trace;
|
|
|
|
AngleVectors (ent->client->v_angle, forward, right, NULL);
|
|
VectorSet(offset, 24, 0, -16);
|
|
G_ProjectSource (ent->s.origin, offset, forward, right, dropped->s.origin);
|
|
trace = gi.trace (ent->s.origin, dropped->mins, dropped->maxs,
|
|
dropped->s.origin, ent, CONTENTS_SOLID);
|
|
VectorCopy (trace.endpos, dropped->s.origin);
|
|
}
|
|
else
|
|
{
|
|
// Lazarus: throw the dropped item a bit farther than the default
|
|
trace_t trace;
|
|
|
|
AngleVectors (ent->s.angles, forward, right, NULL);
|
|
// VectorCopy (ent->s.origin, dropped->s.origin);
|
|
VectorSet(offset, 24, 0, -16);
|
|
G_ProjectSource (ent->s.origin, offset, forward, right, dropped->s.origin);
|
|
trace = gi.trace (ent->s.origin, dropped->mins, dropped->maxs,
|
|
dropped->s.origin, ent, CONTENTS_SOLID);
|
|
VectorCopy (trace.endpos, dropped->s.origin);
|
|
}
|
|
|
|
VectorScale (forward, 100, dropped->velocity);
|
|
dropped->velocity[2] = 300;
|
|
|
|
dropped->think = drop_make_touchable;
|
|
dropped->nextthink = level.time + 1;
|
|
|
|
gi.linkentity (dropped);
|
|
|
|
return dropped;
|
|
}
|
|
|
|
void Use_Item (edict_t *ent, edict_t *other, edict_t *activator)
|
|
{
|
|
ent->svflags &= ~SVF_NOCLIENT;
|
|
ent->use = NULL;
|
|
|
|
if (ent->spawnflags & ITEM_NO_TOUCH)
|
|
{
|
|
ent->solid = SOLID_BBOX;
|
|
ent->touch = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Lazarus:
|
|
if (ent->spawnflags & SHOOTABLE)
|
|
{
|
|
ent->solid = SOLID_BBOX;
|
|
ent->clipmask |= MASK_MONSTERSOLID;
|
|
if (!ent->health)
|
|
ent->health = 20;
|
|
ent->takedamage = DAMAGE_YES;
|
|
ent->die = item_die;
|
|
}
|
|
else
|
|
ent->solid = SOLID_TRIGGER;
|
|
ent->touch = Touch_Item;
|
|
}
|
|
|
|
gi.linkentity (ent);
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
/*
|
|
================
|
|
droptofloor
|
|
================
|
|
*/
|
|
void droptofloor (edict_t *ent)
|
|
{
|
|
trace_t tr;
|
|
vec3_t dest;
|
|
float *v;
|
|
|
|
v = tv(-15,-15,-15);
|
|
VectorCopy (v, ent->mins);
|
|
v = tv(15,15,15);
|
|
VectorCopy (v, ent->maxs);
|
|
|
|
if (ent->model)
|
|
gi.setmodel (ent, ent->model);
|
|
else
|
|
gi.setmodel (ent, ent->item->world_model);
|
|
|
|
// Lazarus:
|
|
// origin_offset is wrong - absmin and absmax weren't set soon enough.
|
|
// Fortunately we KNOW what the "offset" is - nada.
|
|
VectorClear(ent->origin_offset);
|
|
|
|
if (ent->spawnflags & SHOOTABLE)
|
|
{
|
|
ent->solid = SOLID_BBOX;
|
|
ent->clipmask |= MASK_MONSTERSOLID;
|
|
if (!ent->health)
|
|
ent->health = 20;
|
|
ent->takedamage = DAMAGE_YES;
|
|
ent->die = item_die;
|
|
}
|
|
else
|
|
ent->solid = SOLID_TRIGGER;
|
|
|
|
// Lazarus:
|
|
if (ent->movewith)
|
|
ent->movetype = MOVETYPE_PUSH;
|
|
else if (ent->spawnflags & NO_DROPTOFLOOR)
|
|
ent->movetype = MOVETYPE_NONE;
|
|
else
|
|
ent->movetype = MOVETYPE_TOSS;
|
|
ent->touch = Touch_Item;
|
|
|
|
// Lazarus:
|
|
if (!(ent->spawnflags & NO_DROPTOFLOOR))
|
|
{
|
|
v = tv(0,0,-128);
|
|
VectorAdd (ent->s.origin, v, dest);
|
|
|
|
tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
|
|
if (tr.startsolid)
|
|
{
|
|
gi.dprintf ("droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
|
|
G_FreeEdict (ent);
|
|
return;
|
|
}
|
|
tr.endpos[2] += 1;
|
|
ent->mins[2] -= 1;
|
|
VectorCopy (tr.endpos, ent->s.origin);
|
|
}
|
|
|
|
if (ent->team)
|
|
{
|
|
ent->flags &= ~FL_TEAMSLAVE;
|
|
ent->chain = ent->teamchain;
|
|
ent->teamchain = NULL;
|
|
|
|
ent->svflags |= SVF_NOCLIENT;
|
|
ent->solid = SOLID_NOT;
|
|
if (ent == ent->teammaster)
|
|
{
|
|
ent->nextthink = level.time + FRAMETIME;
|
|
ent->think = DoRespawn;
|
|
}
|
|
}
|
|
|
|
if (ent->spawnflags & ITEM_NO_TOUCH)
|
|
{
|
|
ent->solid = SOLID_BBOX;
|
|
ent->touch = NULL;
|
|
ent->s.effects &= ~EF_ROTATE;
|
|
ent->s.renderfx &= ~RF_GLOW;
|
|
}
|
|
|
|
if (ent->spawnflags & ITEM_TRIGGER_SPAWN)
|
|
{
|
|
ent->svflags |= SVF_NOCLIENT;
|
|
ent->solid = SOLID_NOT;
|
|
ent->use = Use_Item;
|
|
}
|
|
|
|
gi.linkentity (ent);
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
PrecacheItem
|
|
|
|
Precaches all data needed for a given item.
|
|
This will be called for each item spawned in a level,
|
|
and for each item in each client's inventory.
|
|
===============
|
|
*/
|
|
void PrecacheItem (gitem_t *it)
|
|
{
|
|
char *s, *start;
|
|
char data[MAX_QPATH];
|
|
int len;
|
|
gitem_t *ammo;
|
|
|
|
if (!it)
|
|
return;
|
|
|
|
if (it->pickup_sound)
|
|
gi.soundindex (it->pickup_sound);
|
|
if (it->world_model)
|
|
gi.modelindex (it->world_model);
|
|
if (it->view_model)
|
|
gi.modelindex (it->view_model);
|
|
if (it->icon)
|
|
gi.imageindex (it->icon);
|
|
|
|
// parse everything for its ammo
|
|
if (it->ammo && it->ammo[0])
|
|
{
|
|
ammo = FindItem (it->ammo);
|
|
if (ammo != it)
|
|
PrecacheItem (ammo);
|
|
}
|
|
|
|
// parse the space seperated precache string for other items
|
|
s = it->precaches;
|
|
if (!s || !s[0])
|
|
return;
|
|
|
|
while (*s)
|
|
{
|
|
start = s;
|
|
while (*s && *s != ' ')
|
|
s++;
|
|
|
|
len = s-start;
|
|
if (len >= MAX_QPATH || len < 5)
|
|
gi.error ("PrecacheItem: %s has bad precache string", it->classname);
|
|
memcpy (data, start, len);
|
|
data[len] = 0;
|
|
if (*s)
|
|
s++;
|
|
|
|
// determine type based on extension
|
|
if (!strcmp(data+len-3, "md2"))
|
|
gi.modelindex (data);
|
|
else if (!strcmp(data+len-3, "sp2"))
|
|
gi.modelindex (data);
|
|
else if (!strcmp(data+len-3, "wav"))
|
|
gi.soundindex (data);
|
|
if (!strcmp(data+len-3, "pcx"))
|
|
gi.imageindex (data);
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
SpawnItem
|
|
|
|
Sets the clipping size and plants the object on the floor.
|
|
|
|
Items can't be immediately dropped to floor, because they might
|
|
be on an entity that hasn't spawned yet.
|
|
============
|
|
*/
|
|
void SpawnItem (edict_t *ent, gitem_t *item)
|
|
{
|
|
PrecacheItem (item);
|
|
|
|
// Lazarus: added several spawnflags, plus gave ALL keys trigger_spawn and no_touch
|
|
// capabilities
|
|
if ( ( (item->flags & IT_KEY) && (ent->spawnflags & ~31) ) ||
|
|
(!(item->flags & IT_KEY) && (ent->spawnflags & ~28) ) )
|
|
// if (ent->spawnflags)
|
|
{
|
|
// if (strcmp(ent->classname, "key_power_cube") != 0)
|
|
{
|
|
gi.dprintf("%s at %s has invalid spawnflags set (%d)\n", ent->classname, vtos(ent->s.origin), ent->spawnflags);
|
|
if (item->flags & IT_KEY)
|
|
ent->spawnflags &= 31;
|
|
else
|
|
ent->spawnflags &= 28;
|
|
}
|
|
}
|
|
|
|
// some items will be prevented in deathmatch
|
|
if (deathmatch->value)
|
|
{
|
|
if ( (int)dmflags->value & DF_NO_ARMOR )
|
|
{
|
|
if (item->pickup == Pickup_Armor || item->pickup == Pickup_PowerArmor)
|
|
{
|
|
G_FreeEdict (ent);
|
|
return;
|
|
}
|
|
}
|
|
if ( (int)dmflags->value & DF_NO_ITEMS )
|
|
{
|
|
if (item->pickup == Pickup_Powerup)
|
|
{
|
|
G_FreeEdict (ent);
|
|
return;
|
|
}
|
|
}
|
|
if ( (int)dmflags->value & DF_NO_HEALTH )
|
|
{
|
|
if (item->pickup == Pickup_Health || item->pickup == Pickup_Adrenaline || item->pickup == Pickup_AncientHead)
|
|
{
|
|
G_FreeEdict (ent);
|
|
return;
|
|
}
|
|
}
|
|
if ( (int)dmflags->value & DF_INFINITE_AMMO )
|
|
{
|
|
if ( (item->flags == IT_AMMO) || (strcmp(ent->classname, "weapon_bfg") == 0) )
|
|
{
|
|
G_FreeEdict (ent);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (coop->value && (strcmp(ent->classname, "key_power_cube") == 0))
|
|
{
|
|
ent->spawnflags |= (1 << (8 + level.power_cubes));
|
|
level.power_cubes++;
|
|
}
|
|
|
|
// don't let them drop items that stay in a coop game
|
|
if ((coop->value) && (item->flags & IT_STAY_COOP))
|
|
{
|
|
item->drop = NULL;
|
|
}
|
|
|
|
// Lazarus: flashlight - get level-wide cost for use
|
|
if (strcmp(ent->classname, "item_flashlight") == 0)
|
|
level.flashlight_cost = ent->count;
|
|
|
|
//ZOID
|
|
//Don't spawn the flags unless enabled
|
|
if (!ctf->value &&
|
|
(strcmp(ent->classname, "item_flag_team1") == 0 ||
|
|
strcmp(ent->classname, "item_flag_team2") == 0)) {
|
|
G_FreeEdict(ent);
|
|
return;
|
|
}
|
|
|
|
ent->item = item;
|
|
ent->nextthink = level.time + 2 * FRAMETIME; // items start after other solids
|
|
ent->think = droptofloor;
|
|
if (ent->skinnum) // Knightmare- use mapper-specified skinnum
|
|
ent->s.skinnum = ent->skinnum;
|
|
else
|
|
// if (!ent->s.skinnum) // Knightmare- allow mapper-specified skinnum
|
|
ent->s.skinnum = item->world_model_skinnum; // Knightmare- skinnum specified in item table
|
|
ent->s.effects = item->world_model_flags;
|
|
ent->s.renderfx = RF_GLOW;
|
|
|
|
// Lazarus:
|
|
if (item->pickup == Pickup_Health)
|
|
{
|
|
if (strcmp(ent->classname, "item_health_small") == 0)
|
|
ent->count = sk_health_bonus_value->value;
|
|
else
|
|
ent->count = item->quantity;
|
|
ent->style = item->tag;
|
|
}
|
|
if (ent->spawnflags & NO_STUPID_SPINNING) {
|
|
ent->s.effects &= ~EF_ROTATE;
|
|
ent->s.renderfx &= ~RF_GLOW;
|
|
}
|
|
|
|
if (ent->model)
|
|
gi.modelindex (ent->model);
|
|
|
|
|
|
//ZOID
|
|
//flags are server animated and have special handling
|
|
if (strcmp(ent->classname, "item_flag_team1") == 0 ||
|
|
strcmp(ent->classname, "item_flag_team2") == 0 ||
|
|
strcmp(ent->classname, "item_flag_team3") == 0) // Knightmare added
|
|
ent->think = CTFFlagSetup;
|
|
//ZOID
|
|
|
|
}
|
|
|
|
//======================================================================
|
|
|
|
gitem_t itemlist[] =
|
|
{
|
|
{
|
|
NULL
|
|
}, // leave index 0 alone
|
|
|
|
//
|
|
// ARMOR
|
|
//
|
|
|
|
/*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_armor_body",
|
|
Pickup_Armor,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"misc/ar1_pkup.wav",
|
|
"models/items/armor/body/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_bodyarmor",
|
|
/* pickup */ "Body Armor",
|
|
/* width */ 3,
|
|
0,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
&bodyarmor_info,
|
|
ARMOR_BODY,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_armor_combat",
|
|
Pickup_Armor,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"misc/ar1_pkup.wav",
|
|
"models/items/armor/combat/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_combatarmor",
|
|
/* pickup */ "Combat Armor",
|
|
/* width */ 3,
|
|
0,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
&combatarmor_info,
|
|
ARMOR_COMBAT,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_armor_jacket (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_armor_jacket",
|
|
Pickup_Armor,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"misc/ar1_pkup.wav",
|
|
"models/items/armor/jacket/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_jacketarmor",
|
|
/* pickup */ "Jacket Armor",
|
|
/* width */ 3,
|
|
0,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
&jacketarmor_info,
|
|
ARMOR_JACKET,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_armor_shard",
|
|
Pickup_Armor,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"misc/ar2_pkup.wav",
|
|
"models/items/armor/shard/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
#ifdef KMQUAKE2_ENGINE_MOD
|
|
"i_shard", //icon
|
|
#else
|
|
"i_jacketarmor", //icon
|
|
#endif
|
|
/* pickup */ "Armor Shard",
|
|
/* width */ 3,
|
|
0,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
NULL,
|
|
ARMOR_SHARD,
|
|
/* precache */ ""
|
|
},
|
|
|
|
//Knightmare- armor shard that lies flat on the ground
|
|
//5
|
|
/*QUAKED item_armor_shard_flat (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN
|
|
*/
|
|
{
|
|
"item_armor_shard_flat",
|
|
Pickup_Armor,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"misc/ar2_pkup.wav",
|
|
"models/items/armor/shard/flat/tris.md2", 0, 0,
|
|
NULL,
|
|
#ifdef KMQUAKE2_ENGINE_MOD
|
|
"i_shard", //icon
|
|
#else
|
|
"i_jacketarmor", //icon
|
|
#endif
|
|
"Armor Shard", //pickup
|
|
3, //width
|
|
0,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
NULL,
|
|
ARMOR_SHARD,
|
|
"" //precache
|
|
},
|
|
|
|
/*QUAKED item_power_screen (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_power_screen",
|
|
Pickup_PowerArmor,
|
|
Use_PowerArmor,
|
|
Drop_PowerArmor,
|
|
NULL,
|
|
"misc/ar3_pkup.wav",
|
|
"models/items/armor/screen/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_powerscreen",
|
|
/* pickup */ "Power Screen",
|
|
/* width */ 0,
|
|
60,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_power_shield (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_power_shield",
|
|
Pickup_PowerArmor,
|
|
Use_PowerArmor,
|
|
Drop_PowerArmor,
|
|
NULL,
|
|
"misc/ar3_pkup.wav",
|
|
"models/items/armor/shield/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_powershield",
|
|
/* pickup */ "Power Shield",
|
|
/* width */ 0,
|
|
60,
|
|
NULL,
|
|
IT_ARMOR,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "misc/power2.wav misc/power1.wav"
|
|
},
|
|
|
|
//
|
|
// WEAPONS
|
|
//
|
|
|
|
/* weapon_grapple (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
always owned, never in the world
|
|
*/
|
|
{
|
|
"weapon_grapple",
|
|
NULL,
|
|
Use_Weapon,
|
|
NULL,
|
|
CTFWeapon_Grapple,
|
|
"misc/w_pkup.wav",
|
|
NULL, 0, 0,
|
|
"models/weapons/grapple/tris.md2",
|
|
/* icon */ "w_grapple",
|
|
/* pickup */ "Grapple",
|
|
0,
|
|
0,
|
|
NULL,
|
|
IT_WEAPON,
|
|
WEAP_GRAPPLE,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/grapple/grfire.wav weapons/grapple/grpull.wav weapons/grapple/grhang.wav weapons/grapple/grreset.wav weapons/grapple/grhit.wav"
|
|
},
|
|
|
|
/* weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
always owned, never in the world
|
|
*/
|
|
/* {
|
|
"weapon_blaster",
|
|
NULL,
|
|
Use_Weapon,
|
|
NULL,
|
|
Weapon_Blaster,
|
|
"misc/w_pkup.wav",
|
|
NULL, 0, 0,
|
|
"models/weapons/v_blast/tris.md2",
|
|
"w_blaster",
|
|
"Blaster",
|
|
0,
|
|
0,
|
|
NULL,
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_BLASTER,
|
|
NULL,
|
|
0,
|
|
"weapons/blastf1a.wav misc/lasfly.wav"
|
|
}, */
|
|
|
|
// DWH
|
|
/*QUAKED weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_blaster",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_Blaster,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_blast/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_blast/tris.md2",
|
|
"w_blaster",
|
|
"Blaster",
|
|
0,
|
|
0,
|
|
NULL,
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_BLASTER,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/blastf1a.wav misc/lasfly.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_shotgun",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_Shotgun,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_shotg/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_shotg/tris.md2",
|
|
/* icon */ "w_shotgun",
|
|
/* pickup */ "Shotgun",
|
|
0,
|
|
1,
|
|
"Shells",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_SHOTGUN,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/shotgf1b.wav weapons/shotgr1b.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_supershotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_supershotgun",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_SuperShotgun,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_shotg2/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_shotg2/tris.md2",
|
|
/* icon */ "w_sshotgun",
|
|
/* pickup */ "Super Shotgun",
|
|
0,
|
|
2,
|
|
"Shells",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_SUPERSHOTGUN,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/sshotf1b.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_machinegun",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_Machinegun,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_machn/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_machn/tris.md2",
|
|
/* icon */ "w_machinegun",
|
|
/* pickup */ "Machinegun",
|
|
0,
|
|
1,
|
|
"Bullets",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_MACHINEGUN,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_chaingun",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_Chaingun,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_chain/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_chain/tris.md2",
|
|
/* icon */ "w_chaingun",
|
|
/* pickup */ "Chaingun",
|
|
0,
|
|
1,
|
|
"Bullets",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_CHAINGUN,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav weapons/chngnd1a.wav"
|
|
},
|
|
|
|
/*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_grenades",
|
|
Pickup_Ammo,
|
|
Use_Weapon,
|
|
Drop_Ammo,
|
|
Weapon_Grenade,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/grenades/medium/tris.md2", 0, 0,
|
|
"models/weapons/v_handgr/tris.md2",
|
|
/* icon */ "a_grenades",
|
|
/* pickup */ "Grenades",
|
|
/* width */ 3,
|
|
5,
|
|
"grenades",
|
|
IT_AMMO|IT_WEAPON,
|
|
WEAP_GRENADES,
|
|
NULL,
|
|
AMMO_GRENADES,
|
|
/* precache */ "models/objects/grenade2/tris.md2 weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav "
|
|
},
|
|
|
|
/*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_grenadelauncher",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_GrenadeLauncher,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_launch/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_launch/tris.md2",
|
|
/* icon */ "w_glauncher",
|
|
/* pickup */ "Grenade Launcher",
|
|
0,
|
|
1,
|
|
"Grenades",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_GRENADELAUNCHER,
|
|
NULL,
|
|
0,
|
|
/* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_rocketlauncher",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_RocketLauncher,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_rocket/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_rocket/tris.md2",
|
|
/* icon */ "w_rlauncher",
|
|
/* pickup */ "Rocket Launcher",
|
|
0,
|
|
1,
|
|
"Rockets",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_ROCKETLAUNCHER,
|
|
NULL,
|
|
0,
|
|
/* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2"
|
|
},
|
|
|
|
/*QUAKED weapon_hyperblaster (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_hyperblaster",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_HyperBlaster,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_hyperb/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_hyperb/tris.md2",
|
|
/* icon */ "w_hyperblaster",
|
|
/* pickup */ "HyperBlaster",
|
|
0,
|
|
1,
|
|
"Cells",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_HYPERBLASTER,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav" // removed weapons/hyprbu1a.wav
|
|
},
|
|
|
|
/*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_railgun",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_Railgun,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_rail/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_rail/tris.md2",
|
|
/* icon */ "w_railgun",
|
|
/* pickup */ "Railgun",
|
|
0,
|
|
1,
|
|
"Slugs",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_RAILGUN,
|
|
NULL,
|
|
0,
|
|
/* precache */ "weapons/rg_hum.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_bfg",
|
|
Pickup_Weapon,
|
|
Use_Weapon,
|
|
Drop_Weapon,
|
|
Weapon_BFG,
|
|
"misc/w_pkup.wav",
|
|
"models/weapons/g_bfg/tris.md2", 0, EF_ROTATE,
|
|
"models/weapons/v_bfg/tris.md2",
|
|
/* icon */ "w_bfg",
|
|
/* pickup */ "BFG10K",
|
|
0,
|
|
50,
|
|
"Cells",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_BFG,
|
|
NULL,
|
|
0,
|
|
/* precache */ "sprites/s_bfg1.sp2 sprites/s_bfg2.sp2 sprites/s_bfg3.sp2 weapons/bfg__f1y.wav weapons/bfg__l1a.wav weapons/bfg__x1b.wav weapons/bfg_hum.wav"
|
|
},
|
|
|
|
/*QUAKED weapon_hml (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"weapon_hml",
|
|
NULL,
|
|
Use_Weapon,
|
|
NULL,
|
|
Weapon_HomingMissileLauncher,
|
|
NULL,
|
|
NULL, 0, EF_ROTATE,
|
|
"models/weapons/v_homing/tris.md2",
|
|
/* icon */ NULL,
|
|
/* pickup */ "Homing Rocket Launcher",
|
|
0,
|
|
1,
|
|
"homing rockets",
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_ROCKETLAUNCHER,
|
|
NULL,
|
|
0,
|
|
/* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2"
|
|
},
|
|
|
|
// Lazarus: No weapon - we HAVE to have a weapon
|
|
{
|
|
"weapon_null",
|
|
NULL,
|
|
Use_Weapon,
|
|
NULL,
|
|
Weapon_Null,
|
|
"misc/w_pkup.wav",
|
|
NULL, 0, 0,
|
|
NULL,
|
|
NULL,
|
|
"No Weapon",
|
|
0,
|
|
0,
|
|
NULL,
|
|
IT_WEAPON|IT_STAY_COOP,
|
|
WEAP_NONE,
|
|
NULL,
|
|
0,
|
|
""
|
|
},
|
|
|
|
//
|
|
// AMMO ITEMS
|
|
//
|
|
|
|
/*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_shells",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/shells/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_shells",
|
|
/* pickup */ "Shells",
|
|
/* width */ 3,
|
|
10,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_SHELLS,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_bullets",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/bullets/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_bullets",
|
|
/* pickup */ "Bullets",
|
|
/* width */ 3,
|
|
50,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_BULLETS,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_cells",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/cells/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_cells",
|
|
/* pickup */ "Cells",
|
|
/* width */ 3,
|
|
50,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_CELLS,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_rockets",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/rockets/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_rockets",
|
|
/* pickup */ "Rockets",
|
|
/* width */ 3,
|
|
5,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_ROCKETS,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_homing_missiles (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_homing_missiles",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/homing/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_homing",
|
|
/* pickup */ "Homing Rockets",
|
|
/* width */ 3,
|
|
5,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_HOMING_ROCKETS,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_slugs",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/slugs/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_slugs",
|
|
/* pickup */ "Slugs",
|
|
/* width */ 3,
|
|
10,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_SLUGS,
|
|
/* precache */ ""
|
|
},
|
|
/*QUAKED ammo_fuel (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"ammo_fuel",
|
|
Pickup_Ammo,
|
|
NULL,
|
|
Drop_Ammo,
|
|
NULL,
|
|
"misc/am_pkup.wav",
|
|
"models/items/ammo/fuel/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
/* icon */ "a_fuel",
|
|
/* pickup */ "fuel",
|
|
/* width */ 4,
|
|
500,
|
|
NULL,
|
|
IT_AMMO,
|
|
0,
|
|
NULL,
|
|
AMMO_FUEL,
|
|
/* precache */ ""
|
|
},
|
|
|
|
//
|
|
// POWERUP ITEMS
|
|
//
|
|
/*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_quad",
|
|
Pickup_Powerup,
|
|
Use_Quad,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/quaddama/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_quad",
|
|
/* pickup */ "Quad Damage",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "items/damage.wav items/damage2.wav items/damage3.wav"
|
|
},
|
|
|
|
/*QUAKED item_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_invulnerability",
|
|
Pickup_Powerup,
|
|
Use_Invulnerability,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/invulner/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_invulnerability",
|
|
/* pickup */ "Invulnerability",
|
|
/* width */ 2,
|
|
300,
|
|
NULL,
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "items/protect.wav items/protect2.wav items/protect4.wav"
|
|
},
|
|
|
|
/*QUAKED item_silencer (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_silencer",
|
|
Pickup_Powerup,
|
|
Use_Silencer,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/silencer/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_silencer",
|
|
/* pickup */ "Silencer",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_breather (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_breather",
|
|
Pickup_Powerup,
|
|
Use_Breather,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/breather/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_rebreather",
|
|
/* pickup */ "Rebreather",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
IT_STAY_COOP|IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "items/airout.wav"
|
|
},
|
|
|
|
/*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_enviro",
|
|
Pickup_Powerup,
|
|
Use_Envirosuit,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/enviro/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_envirosuit",
|
|
/* pickup */ "Environment Suit",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
IT_STAY_COOP|IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "items/airout.wav"
|
|
},
|
|
|
|
/*QUAKED item_ancient_head (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
Special item that gives +2 to maximum health
|
|
*/
|
|
{
|
|
"item_ancient_head",
|
|
Pickup_AncientHead,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/c_head/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_fixme",
|
|
/* pickup */ "Ancient Head",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
gives +1 to maximum health
|
|
*/
|
|
{
|
|
"item_adrenaline",
|
|
Pickup_Adrenaline,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/adrenal/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_adrenaline",
|
|
/* pickup */ "Adrenaline",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_bandolier (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_bandolier",
|
|
Pickup_Bandolier,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/band/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "p_bandolier",
|
|
/* pickup */ "Bandolier",
|
|
/* width */ 2,
|
|
60,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
*/
|
|
{
|
|
"item_pack",
|
|
Pickup_Pack,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/pack/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_pack",
|
|
/* pickup */ "Ammo Pack",
|
|
/* width */ 2,
|
|
180,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
#ifdef FLASHLIGHT_MOD
|
|
#if FLASHLIGHT_USE != POWERUP_USE_ITEM
|
|
{
|
|
"item_flashlight",
|
|
Pickup_Powerup,
|
|
Use_Flashlight,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/f_light/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"p_flash",
|
|
"Flashlight",
|
|
2,
|
|
60,
|
|
NULL,
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
""
|
|
},
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef JETPACK_MOD
|
|
{
|
|
"item_jetpack",
|
|
Pickup_Powerup,
|
|
Use_Jet,
|
|
Drop_Jetpack,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/jet/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"p_jet",
|
|
"Jetpack",
|
|
2,
|
|
600,
|
|
"fuel",
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
"jetpack/activate.wav jetpack/rev1.wav jetpack/revrun.wav jetpack/running.wav jetpack/shutdown.wav jetpack/stutter.wav"
|
|
},
|
|
#endif
|
|
|
|
{
|
|
"item_freeze",
|
|
Pickup_Powerup,
|
|
Use_Stasis,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/stasis/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"p_freeze",
|
|
"Stasis Generator",
|
|
2,
|
|
30,
|
|
NULL,
|
|
IT_POWERUP,
|
|
0,
|
|
NULL,
|
|
0,
|
|
"items/stasis_start.wav items/stasis.wav items/stasis_stop.wav"
|
|
},
|
|
//
|
|
// KEYS
|
|
//
|
|
/*QUAKED key_data_cd (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
key for computer centers
|
|
*/
|
|
{
|
|
"key_data_cd",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/data_cd/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_datacd",
|
|
"Data CD",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_power_cube (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN NO_TOUCH
|
|
warehouse circuits
|
|
*/
|
|
{
|
|
"key_power_cube",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/power/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_powercube",
|
|
"Power Cube",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
key for the entrance of jail3
|
|
*/
|
|
{
|
|
"key_pyramid",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/pyramid/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_pyramid",
|
|
"Pyramid Key",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_data_spinner (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
key for the city computer
|
|
*/
|
|
{
|
|
"key_data_spinner",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/spinner/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_dataspin",
|
|
"Data Spinner",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_pass (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
security pass for the security level
|
|
*/
|
|
{
|
|
"key_pass",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/pass/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_security",
|
|
"Security Pass",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_blue_key (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
normal door key - blue
|
|
*/
|
|
{
|
|
"key_blue_key",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/key/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_bluekey",
|
|
"Blue Key",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_red_key (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
normal door key - red
|
|
*/
|
|
{
|
|
"key_red_key",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/red_key/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
"k_redkey",
|
|
"Red Key",
|
|
2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_commander_head (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
tank commander's head
|
|
*/
|
|
{
|
|
"key_commander_head",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/monsters/commandr/head/tris.md2", 0, EF_GIB,
|
|
NULL,
|
|
/* icon */ "k_comhead",
|
|
/* pickup */ "Commander's Head",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
|
|
/*QUAKED key_airstrike_target (0 .5 .8) (-16 -16 -16) (16 16 16)
|
|
tank commander's head
|
|
*/
|
|
{
|
|
"key_airstrike_target",
|
|
Pickup_Key,
|
|
NULL,
|
|
Drop_General,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/keys/target/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_airstrike",
|
|
/* pickup */ "Airstrike Marker",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_STAY_COOP|IT_KEY,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
/*
|
|
{
|
|
NULL,
|
|
Pickup_Health,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
NULL, 0, 0,
|
|
NULL,
|
|
"i_health",
|
|
"Health",
|
|
3,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
"items/s_health.wav items/n_health.wav items/l_health.wav items/m_health.wav"
|
|
},
|
|
*/
|
|
// Lazarus: Dunno what adding actual health models might end up fouling up, but
|
|
// we'll give it a try for now. This will allow monsters to give up health.
|
|
|
|
{
|
|
"item_health_small",
|
|
Pickup_Health,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/s_health.wav",
|
|
"models/items/healing/stimpack/tris.md2", 0, 0,
|
|
NULL,
|
|
"i_health",
|
|
"Health",
|
|
3,
|
|
2,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
HEALTH_IGNORE_MAX|HEALTH_SMALL,
|
|
"items/s_health.wav"
|
|
},
|
|
|
|
{
|
|
"item_health",
|
|
Pickup_Health,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/n_health.wav",
|
|
"models/items/healing/medium/tris.md2", 0, 0,
|
|
NULL,
|
|
"i_health",
|
|
"Health",
|
|
3,
|
|
10,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
"items/n_health.wav"
|
|
},
|
|
|
|
{
|
|
"item_health_large",
|
|
Pickup_Health,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/l_health.wav",
|
|
"models/items/healing/large/tris.md2", 0, 0,
|
|
NULL,
|
|
"i_health",
|
|
"Health",
|
|
3,
|
|
25,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
HEALTH_LARGE,
|
|
"items/l_health.wav"
|
|
},
|
|
|
|
{
|
|
"item_health_mega",
|
|
Pickup_Health,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/m_health.wav",
|
|
"models/items/mega_h/tris.md2", 0, 0,
|
|
NULL,
|
|
"i_health",
|
|
"Health",
|
|
3,
|
|
100,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
HEALTH_IGNORE_MAX | HEALTH_TIMED,
|
|
"items/m_health.wav"
|
|
},
|
|
|
|
//ZOID
|
|
/*QUAKED item_flag_team1 (1 0.2 0) (-16 -16 -24) (16 16 32)
|
|
*/
|
|
{
|
|
"item_flag_team1",
|
|
CTFPickup_Flag,
|
|
NULL,
|
|
CTFDrop_Flag, //Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"ctf/flagtk.wav",
|
|
"players/male/flag1.md2", 0, EF_FLAG1,
|
|
NULL,
|
|
/* icon */ "i_ctf1",
|
|
/* pickup */ "Red Flag",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/flagcap.wav ctf/flagret.wav"
|
|
},
|
|
|
|
/*QUAKED item_flag_team2 (1 0.2 0) (-16 -16 -24) (16 16 32)
|
|
*/
|
|
{
|
|
"item_flag_team2",
|
|
CTFPickup_Flag,
|
|
NULL,
|
|
CTFDrop_Flag, //Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"ctf/flagtk.wav",
|
|
"players/male/flag2.md2", 0, EF_FLAG2,
|
|
NULL,
|
|
/* icon */ "i_ctf2",
|
|
/* pickup */ "Blue Flag",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/flagcap.wav ctf/flagret.wav"
|
|
},
|
|
|
|
|
|
/*QUAKED item_flag_team3 (1 0.2 0) (-16 -16 -24) (16 16 32)
|
|
*/
|
|
{
|
|
"item_flag_team3",
|
|
CTFPickup_Flag,
|
|
NULL,
|
|
CTFDrop_Flag, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"ctf/flagtk.wav",
|
|
#ifdef KMQUAKE2_ENGINE_MOD
|
|
"models/ctf/flags/flag3.md2", 0, EF_FLAG1|EF_FLAG2,
|
|
#else
|
|
"models/ctf/flags/flag3.md2", 0, EF_FLAG2,
|
|
#endif
|
|
NULL,
|
|
/* icon */ "3tctfg",
|
|
/* pickup */ "Green Flag",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/flagcap.wav ctf/flagret.wav"
|
|
},
|
|
|
|
/* Resistance Tech */
|
|
{
|
|
"item_tech1",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/resistance/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech1",
|
|
/* pickup */ "Disruptor Shield",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech1.wav"
|
|
},
|
|
|
|
/* Strength Tech */
|
|
{
|
|
"item_tech2",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/strength/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech2",
|
|
/* pickup */ "Power Amplifier",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech2.wav ctf/tech2x.wav"
|
|
},
|
|
|
|
/* Haste Tech */
|
|
{
|
|
"item_tech3",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/haste/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech3",
|
|
/* pickup */ "Time Accel",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech3.wav"
|
|
},
|
|
|
|
/* Regeneration Tech */
|
|
{
|
|
"item_tech4",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/regeneration/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech4",
|
|
/* pickup */ "AutoDoc",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech4.wav"
|
|
},
|
|
|
|
/* Vampire Tech */
|
|
{
|
|
"item_tech5",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/vampire/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech5",
|
|
/* pickup */ "Vampire",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech5.wav"
|
|
},
|
|
|
|
/* Ammogen Tech */
|
|
{
|
|
"item_tech6",
|
|
CTFPickup_Tech,
|
|
NULL,
|
|
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/ctf/ammogen/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "tech6",
|
|
/* pickup */ "Ammogen",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
IT_TECH,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ "ctf/tech6.wav"
|
|
},
|
|
|
|
/* Ammogen-spawned Backpack */
|
|
{
|
|
"item_ammogen_pack",
|
|
Pickup_AmmogenPack,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"items/pkup.wav",
|
|
"models/items/pack/tris.md2", 0, EF_ROTATE,
|
|
NULL,
|
|
/* icon */ "i_pack",
|
|
/* pickup */ "Backpack",
|
|
/* width */ 2,
|
|
0,
|
|
NULL,
|
|
0,
|
|
0,
|
|
NULL,
|
|
0,
|
|
/* precache */ ""
|
|
},
|
|
//ZOID
|
|
|
|
// end of list marker
|
|
{NULL}
|
|
};
|
|
|
|
|
|
// QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
|
|
void SP_item_health (edict_t *self)
|
|
{
|
|
if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
self->class_id = ENTITY_ITEM_HEALTH;
|
|
|
|
if (!self->model) // Knightmare- allow mapper-spcified model
|
|
self->model = "models/items/healing/medium/tris.md2";
|
|
if (!self->count) // Knightmare- allow mapper-spcified count
|
|
self->count = 10;
|
|
// SpawnItem (self, FindItem ("Health"));
|
|
SpawnItem (self, FindItemByClassname ("item_health"));
|
|
gi.soundindex ("items/n_health.wav");
|
|
}
|
|
|
|
// QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
|
|
void SP_item_health_small (edict_t *self)
|
|
{
|
|
if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
self->class_id = ENTITY_ITEM_HEALTH_SMALL;
|
|
|
|
if (!self->model) // Knightmare- allow mapper-spcified model
|
|
self->model = "models/items/healing/stimpack/tris.md2";
|
|
if (!self->count) // Knightmare- allow mapper-spcified count
|
|
self->count = sk_health_bonus_value->value;
|
|
// SpawnItem (self, FindItem ("Health"));
|
|
SpawnItem (self, FindItemByClassname ("item_health_small"));
|
|
self->style = HEALTH_IGNORE_MAX|HEALTH_SMALL;
|
|
gi.soundindex ("items/s_health.wav");
|
|
}
|
|
|
|
// QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
|
|
void SP_item_health_large (edict_t *self)
|
|
{
|
|
if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
self->class_id = ENTITY_ITEM_HEALTH_LARGE;
|
|
|
|
if (!self->model) // Knightmare- allow mapper-spcified model
|
|
self->model = "models/items/healing/large/tris.md2";
|
|
if (!self->count) // Knightmare- allow mapper-spcified count
|
|
self->count = 25;
|
|
// SpawnItem (self, FindItem ("Health"));
|
|
SpawnItem (self, FindItemByClassname ("item_health_large"));
|
|
self->style = HEALTH_LARGE;
|
|
gi.soundindex ("items/l_health.wav");
|
|
}
|
|
|
|
// QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16)
|
|
|
|
void SP_item_health_mega (edict_t *self)
|
|
{
|
|
if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
self->class_id = ENTITY_ITEM_HEALTH_MEGA;
|
|
|
|
if (!self->model) // Knightmare- allow mapper-spcified model
|
|
self->model = "models/items/mega_h/tris.md2";
|
|
if (!self->count) // Knightmare- allow mapper-spcified count
|
|
self->count = 100;
|
|
// SpawnItem (self, FindItem ("Health"));
|
|
SpawnItem (self, FindItemByClassname ("item_health_mega"));
|
|
gi.soundindex ("items/m_health.wav");
|
|
self->style = HEALTH_IGNORE_MAX|HEALTH_TIMED;
|
|
}
|
|
|
|
|
|
void InitItems (void)
|
|
{
|
|
game.num_items = sizeof(itemlist)/sizeof(itemlist[0]) - 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
SetItemNames
|
|
|
|
Called by worldspawn
|
|
===============
|
|
*/
|
|
void SetItemNames (void)
|
|
{
|
|
int i;
|
|
gitem_t *it;
|
|
|
|
for (i=0 ; i<game.num_items ; i++)
|
|
{
|
|
it = &itemlist[i];
|
|
gi.configstring (CS_ITEMS+i, it->pickup_name);
|
|
}
|
|
|
|
noweapon_index = ITEM_INDEX(FindItem("No Weapon"));
|
|
jacket_armor_index = ITEM_INDEX(FindItem("Jacket Armor"));
|
|
combat_armor_index = ITEM_INDEX(FindItem("Combat Armor"));
|
|
body_armor_index = ITEM_INDEX(FindItem("Body Armor"));
|
|
power_screen_index = ITEM_INDEX(FindItem("Power Screen"));
|
|
power_shield_index = ITEM_INDEX(FindItem("Power Shield"));
|
|
shells_index = ITEM_INDEX(FindItem("shells"));
|
|
bullets_index = ITEM_INDEX(FindItem("bullets"));
|
|
grenades_index = ITEM_INDEX(FindItem("Grenades"));
|
|
rockets_index = ITEM_INDEX(FindItem("rockets"));
|
|
cells_index = ITEM_INDEX(FindItem("cells"));
|
|
slugs_index = ITEM_INDEX(FindItem("slugs"));
|
|
fuel_index = ITEM_INDEX(FindItem("fuel"));
|
|
homing_index = ITEM_INDEX(FindItem("homing rockets"));
|
|
blaster_index = ITEM_INDEX(FindItem("Blaster"));
|
|
rl_index = ITEM_INDEX(FindItem("Rocket Launcher"));
|
|
hml_index = ITEM_INDEX(FindItem("Homing Rocket Launcher"));
|
|
rg_index = ITEM_INDEX(FindItem("Railgun"));
|
|
}
|
|
|
|
|
|
/*
|
|
==================
|
|
Use_Flashlight
|
|
==================
|
|
*/
|
|
void Use_Flashlight ( edict_t *ent, gitem_t *item )
|
|
{
|
|
if (!ent->client->flashlight)
|
|
{
|
|
if (ent->client->pers.inventory[ITEM_INDEX(FindItem(FLASHLIGHT_ITEM))] < level.flashlight_cost)
|
|
{
|
|
safe_cprintf(ent,PRINT_HIGH,"Flashlight requires %s\n",FLASHLIGHT_ITEM);
|
|
return;
|
|
}
|
|
#if FLASHLIGHT_USE != POWERUP_USE_ITEM
|
|
/* Lazarus: We never "use up" the flashlight
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--; */
|
|
ValidateSelectedItem (ent);
|
|
#endif
|
|
}
|
|
if (ent->client->flashlight ^= 1)
|
|
ent->client->flashlight_time = level.time + FLASHLIGHT_DRAIN;
|
|
}
|
|
|
|
#ifdef JETPACK_MOD
|
|
//==============================================================================
|
|
void Use_Jet ( edict_t *ent, gitem_t *item )
|
|
{
|
|
if (ent->client->jetpack)
|
|
{
|
|
// Currently on... turn it off and store remaining time
|
|
ent->client->jetpack = false;
|
|
ent->client->jetpack_framenum = 0;
|
|
// Force frame. While using the jetpack ClientThink forces the frame to
|
|
// stand20 when it really SHOULD be jump2. This is fine, but if we leave
|
|
// it at that then the player cycles through the wrong frames to complete
|
|
// his "jump" when the jetpack is turned off. The same thing is done in
|
|
// ClientThink when jetpack timer expires.
|
|
ent->s.frame = 67;
|
|
gi.sound(ent, CHAN_GIZMO, gi.soundindex("jetpack/shutdown.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
else
|
|
{
|
|
// Knightmare- don't allow activating during stasis- or player can't descend
|
|
if (level.freeze)
|
|
{
|
|
gi.dprintf("Cannot use jetpack while using stasis generator\n");
|
|
return;
|
|
}
|
|
|
|
// Currently off. Turn it on, and add time, if any, remaining
|
|
// from last jetpack.
|
|
if ( ent->client->pers.inventory[ITEM_INDEX(item)] )
|
|
{
|
|
ent->client->jetpack = true;
|
|
// Lazarus: Never remove jetpack from inventory (unless dropped)
|
|
// ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
ent->client->jetpack_framenum = level.framenum;
|
|
ent->client->jetpack_activation = level.framenum;
|
|
}
|
|
else if (ent->client->pers.inventory[fuel_index] > 0)
|
|
{
|
|
ent->client->jetpack = true;
|
|
ent->client->jetpack_framenum = level.framenum;
|
|
ent->client->jetpack_activation = level.framenum;
|
|
}
|
|
else
|
|
return; // Shouldn't have been able to get here, but I'm a pessimist
|
|
gi.sound(ent, CHAN_GIZMO, gi.soundindex("jetpack/activate.wav"), 1, ATTN_NORM, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Lazarus: Stasis field generator
|
|
void Use_Stasis ( edict_t *ent, gitem_t *item )
|
|
{
|
|
if (ent->client->jetpack)
|
|
{
|
|
gi.dprintf("Cannot use stasis generator while using jetpack\n");
|
|
return;
|
|
}
|
|
ent->client->pers.inventory[ITEM_INDEX(item)]--;
|
|
ValidateSelectedItem (ent);
|
|
level.freeze = true;
|
|
level.freezeframes = 0;
|
|
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/stasis_start.wav"), 1, ATTN_NORM, 0);
|
|
}
|