djcev.com

//

Git Repos / fte_dogmode / qc / base_item.qc

Last update to this file was on 2025-08-13 at 05:20.

Show base_item.qc

//==============================================================================
// base_item.qc -- top-level item pickups
//==============================================================================

//======================================================================
// constants
//======================================================================

#ifdef SSQC
//----------------------------------------------------------------------
// base item spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_ITEM_SPAWNSILENT = 32,// item won't make sound when spawning
SPAWNFLAG_ITEM_SPAWNED = 64,
SPAWNFLAG_ITEM_SUSPENDED = 128,
// SPAWNFLAG_NOT_ON_EASY = 256, // see base_entities.qc -- CEV
// SPAWNFLAG_NOT_ON_NORMAL = 512,
// SPAWNFLAG_NOT_ON_HARD_OR_NIGHTMARE = 1024,
// SPAWNFLAG_NOT_IN_DEATHMATCH = 2048,
// SPAWNFLAG_NOT_IN_COOP = 4096,
// SPAWNFLAG_NOT_IN_SP = 8192,
// SPAWNFLAG_NOT_ON_SKILL2 = 32768, // see base_entities.qc -- CEV
// SPAWNFLAG_NOT_ON_SKILL3 = 65536, // see base_entities.qc -- CEV
// SPAWNFLAG_CENTERPRINTALL = 131072 // see base_entities.qc -- CEV
SPAWNFLAG_ITEM_RESPAWN = 1048576, // respawn
SPAWNFLAG_ITEM_THROWN = 2097152, // item was thrown
SPAWNFLAG_ITEM_DONTDROP = 4194304 // last flag! don't drop to the ground
} base_item_spawnflags;
#endif

#ifdef SSQC
const float ITEM_ALPHA_WAITSPAWN = 0.00001; // alpha values (respawn feedback)
const float ITEM_ALPHA_NEARSPAWN = 0.2;
const float ITEM_ALPHA_OPAQUE = 1.0;
#endif

//======================================================================
// forward declarations
//======================================================================

// base_item
#ifdef CSQC
// BASE_ITEM_NETRECEIVE(initfn)
float() base_item_predraw;
#endif
#ifdef SSQC
void() base_item_neteval;
#endif
#ifdef SSQC
// BASE_ITEM_INVENTORY_ADD(from, to)
// BASE_ITEM_INVENTORY_REMOVE(holder)
// BASE_ITEM_PICKUPMESSAGE(p, i)
// BASE_ITEM_CHECKREMOVE(bic_item, sp_wait, dm_wait)
// BASE_ITEM_THROW_ROTATION(ent, item)
void(float old, float new) base_item_contentstransition;
float() base_item_touch_projectile;
float(entity item, float delay_sp, float delay_dm) base_item_check_respawn;
void() base_item_think_respawn;
void() base_item_think_nearspawn;
void() base_item_think_rhull;
void() base_item_think_throwgroundcheck;
void() base_item_think_place;
void() base_item_use_delayspawn;
entity(float idx, vector org, vector vel, float fl) spawn_base_item;
// BASE_ITEM_PREINIT(func)
void(string key, string value) base_item_init_field;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) base_item_init;
#endif
#ifdef SSQC
strip void() base_item;
#endif

//------------------------------------------------------------------------------

//----------------------------------------------------------------------
// class base_item: base_mapentity
// {
//==============================================================
// Generic item networking -- CEV
//==============================================================

#ifdef CSQC
//--------------------------------------------------------------
#define BASE_ITEM_NETRECEIVE(initfn) \
/* { */ \
local float netflags = base_entity_netreceive (isnew); \
if (NETFLAG_BASE_ENTITY_FRAME) \
{ \
self.frame = self.frame_net; \
} \
if (isnew && !(self.predraw)) \
{ \
initfn (self); \
} \
else \
{ \
if (netflags & NETFLAG_BASE_ENTITY_MODEL) \
{ \
setmodelindex (self, self.modelindex); \
} \
if (netflags & NETFLAG_BASE_ENTITY_SOLID) \
{ \
if (self.solid) \
{ \
local item_info_t iit = \
item_info[self.weapon]; \
setsize (self, iit.world_mins, \
iit.world_maxs); \
} \
else \
{ \
setsize (self, '0 0 0', '0 0 0'); \
} \
} \
} \
/* } */

//--------------------------------------------------------------
float() base_item_predraw =
{
// skip invisible entities -- CEV
if (!self.modelindex)
return PREDRAW_NEXT;

// interpolate origin -- see base_entities.qc -- CEV
BASE_ENTITY_LERP_ORIGIN (self,
self.origin_net, self.origin_prev, pmovelatesttime,
self.origin_net_time, self.origin_prev_time)

if (self.modelflags & MF_ROTATE)
{
// this item is flagged to automatically rotate -- CEV
// rotation formula from Nuclide -- CEV
self.angles.y += frametime * 120.0f;
// wrap angles -- CEV
if (self.angles.y > 180)
self.angles.y -= 360;
else if (self.angles.y < -180)
self.angles.y += 360;
}
else
{
// interpolate angles -- see base_entities.qc -- CEV
BASE_ENTITY_LERP_ANGLES (self,
self.angles_net, self.angles_prev,
pmovelatesttime,
self.angles_net_time, self.angles_prev_time)
}

if (self.effects & EF_REDTINT)
{
self.colormod = '1.0 0 0';
self.effects &= ~EF_REDTINT;
}
else if (self.colormod)
{
self.colormod = '0 0 0';
}

// draw this entity -- CEV
addentity (self);

// rewind to last known server origin -- CEV
setorigin (self, self.origin_net);

// go to next without auto-drawing this entity -- CEV
return PREDRAW_NEXT;
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
void() base_item_neteval =
{
if (!(self.SendFlags & NETFLAG_BASE_ENTITY_ORIGIN))
{
if (self.origin != self.origin_net)
{
// client needs updated origin -- CEV
self.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN;
}
}

if (!(self.SendFlags & NETFLAG_BASE_ENTITY_ANGLES))
{
if (self.angles != self.angles_net)
{
// client needs updated angles -- CEV
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
}
}
};
#endif

//==============================================================
// Macros
//==============================================================

#ifdef SSQC
//--------------------------------------------------------------
#define BASE_ITEM_INVENTORY_ADD(from, to) \
/* { */ \
switch (to.weapon) \
{ \
case 1: to.item[0] = from.weapon; break; \
case 2: to.item[1] = from.weapon; break; \
case 3: to.item[2] = from.weapon; break; \
case 4: to.item[3] = from.weapon; break; \
case 5: to.item[4] = from.weapon; break; \
case 6: to.item[5] = from.weapon; break; \
case 7: to.item[6] = from.weapon; break; \
case 8: to.item[7] = from.weapon; break; \
} \
/* } */

//--------------------------------------------------------------
#define BASE_ITEM_INVENTORY_REMOVE(holder) \
/* { */ \
switch (holder.weapon) \
{ \
case 1: holder.item[0] = ITEM_SEQ_HANDS; break; \
case 2: holder.item[1] = ITEM_SEQ_HANDS; break; \
case 3: holder.item[2] = ITEM_SEQ_HANDS; break; \
case 4: holder.item[3] = ITEM_SEQ_HANDS; break; \
case 5: holder.item[4] = ITEM_SEQ_HANDS; break; \
case 6: holder.item[5] = ITEM_SEQ_HANDS; break; \
case 7: holder.item[6] = ITEM_SEQ_HANDS; break; \
case 8: holder.item[7] = ITEM_SEQ_HANDS; break; \
} \
/* } */

//--------------------------------------------------------------
#define BASE_ITEM_PICKUPMESSAGE(p, i) \
/* { */ \
/* item touch message */ \
sprint (p, sprintf("%s got the %s!\n", p.netname, i.name)); \
/* item touch sound */ \
sound (p, i.pickup_sound.channel, i.pickup_sound.wav, \
i.pickup_sound.volume, i.pickup_sound.attenuation); \
/* item touch screenflash */ \
stuffcmd (p, "bf\n"); \
/* } */

//--------------------------------------------------------------
// check if we need to respawn the item; remove if not -- CEV
//--------------------------------------------------------------
#define BASE_ITEM_CHECKREMOVE(bic_item, sp_wait, dm_wait) \
/* { */ \
/* make sure the item exists before proceeding -- CEV */ \
if (bic_item) \
{ \
bic_item.model = __NULL__; \
bic_item.solid = SOLID_NOT; \
setmodel (bic_item, bic_item.model); \
bic_item.SendFlags |= NETFLAG_BASE_ENTITY_MODEL | \
NETFLAG_BASE_ENTITY_SOLID; \
/* Supa, SP respawning items support */ \
if (bic_item.spawnflags & SPAWNFLAG_ITEM_THROWN) \
{ \
/* remove thrown items after pickup -- CEV */ \
bic_item.touch = sub_null; \
bic_item.think = sub_remove; \
bic_item.nextthink = time + 0.2; \
} \
else if (base_item_check_respawn(bic_item, \
sp_wait, dm_wait)) \
{ \
/* clear to remove this item -- CEV */ \
bic_item.touch = sub_null; \
bic_item.think = sub_remove; \
bic_item.nextthink = time + 0.2; \
} \
} \
/* } */

//--------------------------------------------------------------
// set up rotation for thrown items -- CEV
//--------------------------------------------------------------
#define BASE_ITEM_THROW_ROTATION(ent, item) \
/* { */ \
if (ent.spawnflags & SPAWNFLAG_ITEM_THROWN && ent.owner) \
{ \
local float ay; \
/* TODO CEV simplify this */ \
ay = ent.owner.angles.y + item.view_angles_offset.y; \
ay = ay - 360.0f * rint(ay / 360.0f); \
ay = ay - 180.0f * rint(ay / 180.0f); \
ay = ay - 90.0f * rint(ay / 90.0f); \
ent.angles.y = ay; \
if (ent.angles.y > 0) \
ent.avelocity_y = -60; \
else \
ent.avelocity_y = 60; \
} \
/* } */

//--------------------------------------------------------------
void(float old, float new) base_item_contentstransition =
{
dprint (sprintf("base_item_contentstransition: class %s, "
"old %g, new %g\n", self.classname, old, new));

if (self.swim_time >= time)
return;

if (new <= CONTENT_WATER && old == CONTENT_EMPTY)
{
// just crossed into water
self.swim_time = time + 2;
SOUND_RDELAY (self, snd_misc_h2ohit)
}
else if (old != CONTENT_EMPTY)
{
// just crossed into open
self.swim_time = time + 2;
SOUND_RDELAY (self, snd_misc_h2ohit)
}
};

//--------------------------------------------------------------
float() base_item_touch_projectile =
{
if (self.spawnflags & SPAWNFLAG_ITEM_THROWN) {
if (!(self.flags & FL_ONGROUND)) {
if (self.solid == SOLID_SLIDEBOX)
{
// this is a thrown item that's currently SOLID_SLIDEBOX
// (and so probably airborne). do some typical
// projectile checks -- CEV
local float pc = pointcontents (self.origin);
if (pc == CONTENT_SKY)
{
dprint (sprintf("base_item_touch_projectile: "
"%s in the sky!\n",
self.classname));
base_entity_remove (self);
return TRUE;
}
else if (pc == CONTENT_SOLID)
{
dprint (sprintf("base_item_touch_projectile: "
"%s within a solid!\n",
self.classname));
base_entity_remove (self);
return TRUE;
}

if (other.solid == SOLID_BSP)
{
dprint (sprintf("base_item_touch_projectile: "
"hit %s, vel %v!\n",
other.classname, self.velocity));

if (other.classtype == CT_WORLD) {
if (self.velocity.z < 0)
{
base_entity_aligntoground (self);
} }

if (self.flags & FL_ONGROUND)
self.velocity = '0 0 0';
else
self.velocity = [
self.velocity_x * 0.5,
self.velocity_y * 0.5,
self.velocity_z];
}

if (other != self.owner) {
if (!(self.flags & FL_ONGROUND)) {
if (other.takedamage) {
if (time >= self.attack_finished) {
if (self.dmg)
{
// we're airbone for sure and hit something
// that takes damage. do the thing. -- CEV
self.attack_finished = time + 0.5;
spawn_touchblood (self.dmg);
t_damage2 (other, self, self.owner, self.dmg);
} } } } }

// skip all other checks if we're still solid
// at this point -- CEV
return TRUE;
} } }
return FALSE;
};

//==============================================================
// Subs
//==============================================================

//--------------------------------------------------------------
// CheckItemRespawn -- was in items.qc
//--------------------------------------------------------------
float(entity item, float delay_sp, float delay_dm)
base_item_check_respawn =
{
local item_info_t iit = item_info[item.weapon];

// DM rules first
if (deathmatch == 1)
{
if (delay_dm > 5.0)
{
item.alpha = ITEM_ALPHA_WAITSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.think = base_item_think_nearspawn;
item.nextthink = time + delay_dm - 5.0;
}
else
{
item.alpha = ITEM_ALPHA_NEARSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.nextthink = time + delay_dm;
}

item.nextthink = time + delay_dm;
setmodel (item, iit.world_model);
setsize (item, iit.world_mins, iit.world_maxs);
return FALSE;
}

if (deathmatch)
{
dprint (sprintf("base_item_check_respawn: unhandled "
"deathmatch state %f\n", deathmatch));
return TRUE;
}

// Supa, SP respawning items support
// respawn item if flagged, otherwise abort
if (!(item.spawnflags & SPAWNFLAG_ITEM_RESPAWN) ||
item.wait == -1)
{
return TRUE;
}

// inc before check to account for zero indexing
item.cnt = item.cnt + 1;

// limited respawns
if (item.count && item.count < item.cnt)
return TRUE;

// okay, we're clear to set up a respawn
if (item.wait)
{
// custom respawn delay
if (item.wait > 5.0)
{
item.alpha = ITEM_ALPHA_WAITSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.think = base_item_think_nearspawn;
item.nextthink = time + item.wait - 5.0;
}
else
{
item.alpha = ITEM_ALPHA_NEARSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.nextthink = time + item.wait;
}
}
else
{
if (delay_sp > 5.0)
{
item.alpha = ITEM_ALPHA_WAITSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.think = base_item_think_nearspawn;
item.nextthink = time + delay_sp - 5.0;
}
else
{
item.alpha = ITEM_ALPHA_NEARSPAWN;
item.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
item.nextthink = time + delay_sp;
}
}

setmodel (item, iit.world_model);
setsize (item, iit.world_mins, iit.world_maxs);
return FALSE;
};

//==============================================================
// Interfacing
//==============================================================

//--------------------------------------------------------------
// SUB_Regen -- was in items.qc
//--------------------------------------------------------------
void() base_item_think_respawn =
{
local item_info_t iit = item_info[self.weapon];

// restore original model
self.model = iit.world_model;
self.alpha = ITEM_ALPHA_OPAQUE;
setmodel (self, self.model);
setsize (self, iit.world_mins, iit.world_maxs);

// allow it to be touched again
self.solid = SOLID_TRIGGER;
self.flags |= FL_FINDABLE_NONSOLID;

// guarantee size -- CEV
setsize (self, iit.world_mins, iit.world_maxs);

// relink -- CEV
setorigin (self, self.origin);

// new respawning effects -- CEV
SOUND (self, snd_item_respawn)

// make sure the client knows -- CEV
self.SendFlags |= NETFLAG_BASE_ENTITY_MODEL |
NETFLAG_BASE_ENTITY_SOLID | NETFLAG_BASE_ENTITY_ALPHA;
};

//--------------------------------------------------------------
void() base_item_think_nearspawn =
{
// bump alpha when 5s remain -- CEV
self.alpha = ITEM_ALPHA_NEARSPAWN;
self.SendFlags |= NETFLAG_BASE_ENTITY_ALPHA;
self.think = base_item_think_respawn;
self.nextthink = time + 5.0;
};

//--------------------------------------------------------------
// RefreshHull -- Supa, restore old hull and lock movement
//--------------------------------------------------------------
void() base_item_think_rhull =
{
dprint ("base_item_think_rhull: fix for bboxes\n");

// dumptruck_ds -- fix for bounding boxes
local item_info_t iit = item_info[self.weapon];
setsize (self, iit.world_mins, iit.world_maxs);

self.movetype = MOVETYPE_NONE;
self.velocity = '0 0 0';
self.SendFlags |= NETFLAG_BASE_ENTITY_SOLID;
};

//--------------------------------------------------------------
void() base_item_think_throwgroundcheck =
{
if (self.flags & FL_ONGROUND)
{
dprint (sprintf("base_item_think_throwgroundcheck: "
"onground at %g, owner %s\n",
time, self.owner.classname));

// yaw to 0 (so the bbox will fit the item) -- CEV
if (!(self.classgroup & CG_CORPSE))
if (self.angles_y)
self.angles_y = 0;

// return to original size -- CEV
local item_info_t iit = item_info[self.weapon];
setsize (self, iit.world_mins, iit.world_maxs);

// remove from frametick que if needed -- CEV
if (self.classgroup & CG_FRAMETICK)
self.classgroup &= ~CG_FRAMETICK;

// clear owner (if we have one) -- CEV
if (self.owner)
self.owner = world;

// stop moving, thinking, & return to non-solid -- CEV
self.velocity = '0 0 0';
self.avelocity = '0 0 0';
self.solid = SOLID_TRIGGER;
self.think = sub_null;
self.SendFlags |= NETFLAG_BASE_ENTITY_SOLID |
NETFLAG_BASE_ENTITY_ANGLES;
}
else
{
/*
dprint (sprintf("base_item_think_throwgroundcheck: "
"angles %v\n", self.angles));
*/

// manage rotation towards center -- CEV
if (!(self.classgroup & CG_CORPSE))
{
if (self.angles_y)
{
if (self.avelocity_y > 0)
{
if (self.angles_y > 0)
{
self.angles_y = 0;
self.avelocity_y = 0;
}
}
else
{
if (self.angles_y < 0)
{
self.angles_y = 0;
self.avelocity_y = 0;
}
}
}
}

self.nextthink = time + 0.1;
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
}
};

//--------------------------------------------------------------
// PlaceItem -- plants the object on the floor
//--------------------------------------------------------------
void() base_item_think_place =
{
// we want to be visible -- CEV
if (!(self.alpha))
self.alpha = ITEM_ALPHA_OPAQUE;

// so findradius can find it -- CEV
self.flags |= FL_FINDABLE_NONSOLID;

// don't make extra wide, it interferes w/tracelines -- CEV
// self.flags |= FL_ITEM;

if (!(self.spawnflags & SPAWNFLAG_ITEM_THROWN))
{
self.velocity = '0 0 0';
self.think = base_item_think_respawn;
}

// guarantee size -- CEV
local item_info_t iit = item_info[self.weapon];

if (self.spawnflags & SPAWNFLAG_ITEM_THROWN)
{
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_TOSS;
setsize (self, iit.world_mins, iit.world_maxs);
setorigin (self, self.origin);

// add to frametick queue -- CEV
self.tick = base_item_neteval;
self.classgroup |= CG_FRAMETICK;

// check for ground once per 0.1 -- CEV
self.think = base_item_think_throwgroundcheck;
self.nextthink = time + 0.1;
}
else if (self.spawnflags & SPAWNFLAG_ITEM_SUSPENDED)
{
// ijed Don't drop spawnflag
dprint (sprintf("base_item_think_place: spawned "
"suspended item %s at %v\n",
self.classname, self.origin));
setsize (self, iit.world_mins, iit.world_maxs);
self.solid = SOLID_TRIGGER;
self.movetype = MOVETYPE_FLY;
}
else
{
setsize (self, iit.world_mins, iit.world_maxs);

// The following hack for item_health was inherited
// from the RMQ code, and was here when the
// func_mapjamx maps were created. It would have been
// nice to remove this code entirely, because progs_dump
// doesn't need it, and it breaks item_health's
// collision with entities that have MOVETYPE_PUSH.
// However, removing this code would cause some of the
// item_health entities in some of the func_mapjamx
// maps to "fall out of the level", because they're
// accidentally touching solid surfaces. So, to
// maintain backwards-compatibility, this code has
// been left in, but will only be run if one of the
// func_mapjamx maps is being played. -- iw
if (known_release == KNOWN_RELEASE_FUNC_MAPJAMX)
{
if (self.classtype == CT_ITEM_HEALTH)
{
// Supa, CTF
// hacking around hull issues..
// void hull for now
setsize (self, '0 0 0', '0 0 0');
self.think = base_item_think_rhull;
self.nextthink = time + 0.2;
}
}

self.solid = SOLID_TRIGGER;
self.movetype = MOVETYPE_TOSS;

if (!(self.spawnflags & SPAWNFLAG_ITEM_DONTDROP))
{
setorigin (self, self.origin + '0 0 6');

if (!droptofloor())
{
dprint (sprintf("base_item_think_place"
": bonus item %s fell out of "
"level at %v\n",
self.classname, self.origin));
// TODO CEV
// base_entity_remove (self);
return;
}

// TODO CEV
// base_entity_aligntoground (self);
}

self.tick = base_item_neteval;
// self.classgroup |= CG_FRAMETICK;
}

if (self.spawnflags & SPAWNFLAG_ITEM_SPAWNED)
{
// SPAWNED, gb
setsize (self, '0 0 0', '0 0 0');

self.model = "";
self.solid = SOLID_NOT;
self.flags &= ~FL_FINDABLE_NONSOLID;

if (self.spawnflags & SPAWNFLAG_ITEM_DONTDROP)
self.movetype = MOVETYPE_NONE;

self.use = base_item_use_delayspawn;
}

// manage watertype and waterlevel -- CEV
self.watertype = self.owner.watertype;
self.contentstransition = base_item_contentstransition;

self.SendEntity = base_entity_netsend;
self.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
};

//--------------------------------------------------------------
// DelaySpawnItem -- this is from rmq-items.qc
// Makes a SPAWNED item ready for pickup on a trigger event
// - modified a bit -- dumptruck_ds
//--------------------------------------------------------------
void() base_item_use_delayspawn =
{
local item_info_t iit = item_info[self.weapon];

self.solid = SOLID_TRIGGER;
self.flags |= FL_FINDABLE_NONSOLID;
setmodel (self, iit.world_model);
setsize (self, iit.world_mins, iit.world_maxs);

if (!(self.spawnflags & SPAWNFLAG_ITEM_SPAWNSILENT))
// SILENT, gb
spawn_tfog (self.origin + self.view_ofs);

if (self.spawnflags & SPAWNFLAG_ITEM_SUSPENDED)
self.movetype = MOVETYPE_FLY;
else
self.movetype = MOVETYPE_TOSS;

self.use = sub_null;
};

//==============================================================
// Constructor & Spawn Functions
//==============================================================

//--------------------------------------------------------------
// generic item spawn function - args are item_index, origin,
// velocity, and spawnflags -- CEV
//
// 'self' is assumed to be the source/owner entity -- CEV
//--------------------------------------------------------------
entity(float idx, vector org, vector vel, float fl) spawn_base_item =
{
// some item types need special handling -- CEV
if (idx >= ITEM_SEQ_PACKS_START && idx <= ITEM_SEQ_PACKS_END)
{
// backpacks
return spawn_item_backpack (self, org, vel);
}
else if (idx >= ITEM_SEQ_THROWABLE_START &&
idx <= ITEM_SEQ_THROWABLE_END)
{
// throwables
return spawn_base_item_throwable (idx, org, vel, fl);
}

// spawn an entity and set it up -- CEV
local entity e = spawn ();
e.owner = self;
e.spawnflags = fl;
e.origin = org;
e.velocity = vel;
e.weapon = idx;

// map item_index to a spawn function -- CEV
switch (idx)
{
case ITEM_SEQ_SHOTGUN:
case ITEM_SEQ_SUPERSHOTGUN:
case ITEM_SEQ_NAILGUN:
case ITEM_SEQ_SUPERNAILGUN:
case ITEM_SEQ_GRENADELAUNCHER:
case ITEM_SEQ_ROCKETLAUNCHER:
case ITEM_SEQ_LIGHTNINGGUN:
base_item_weapon_init (e); break;
case ITEM_SEQ_AMMO_SHELLS_LARGE:
e.spawnflags |= SPAWNFLAG_ITEM_AMMO_LARGE_BOX;
case ITEM_SEQ_AMMO_SHELLS_SMALL:
base_item_ammo_init (e); break;
case ITEM_SEQ_AMMO_NAILS_LARGE:
e.spawnflags |= SPAWNFLAG_ITEM_AMMO_LARGE_BOX;
case ITEM_SEQ_AMMO_NAILS_SMALL:
base_item_ammo_init (e); break;
case ITEM_SEQ_AMMO_ROCKETS_LARGE:
e.spawnflags |= SPAWNFLAG_ITEM_AMMO_LARGE_BOX;
case ITEM_SEQ_AMMO_ROCKETS_SMALL:
base_item_ammo_init (e); break;
case ITEM_SEQ_AMMO_CELLS_LARGE:
e.spawnflags |= SPAWNFLAG_ITEM_AMMO_LARGE_BOX;
case ITEM_SEQ_AMMO_CELLS_SMALL:
base_item_ammo_init (e); break;
case ITEM_SEQ_ARMOR_GREEN:
case ITEM_SEQ_ARMOR_YELLOW:
case ITEM_SEQ_ARMOR_RED:
case ITEM_SEQ_ARMOR_SHARD:
base_item_armor_init (e); break;
case ITEM_SEQ_HEALTH_MEGA:
e.spawnflags |= SPAWNFLAG_ITEM_HEALTH_MEGA;
base_item_health_init (e); break;
case ITEM_SEQ_HEALTH_ROTTEN:
e.spawnflags |= SPAWNFLAG_ITEM_HEALTH_ROTTEN;
base_item_health_init (e); break;
case ITEM_SEQ_HEALTH:
case ITEM_SEQ_HEALTH_VIAL:
base_item_health_init (e); break;
case ITEM_SEQ_ARTIFACT_ENVIROSUIT:
case ITEM_SEQ_ARTIFACT_INVISIBILITY:
case ITEM_SEQ_ARTIFACT_INVULNERABILITY:
case ITEM_SEQ_ARTIFACT_QUAD:
base_item_powerup_init (e); break;
case ITEM_SEQ_TORCH:
item_torch_init (e); break;
default:
objerror (sprintf("spawn_base_item: "
"unknown item type %g!\n", idx));
remove (e);
return __NULL__;
}

// now return our (hopefully initialized) new entity -- CEV
return e;
}

//--------------------------------------------------------------
// pre-initialization macro. remap spawnflags for known releases,
// check spawnflags to inhibit spawn, then loop over spawndata
// if necessary -- CEV
//--------------------------------------------------------------
#define BASE_ITEM_PREINIT(func) \
/* { */ \
if (known_release == KNOWN_RELEASE_QUAKE3 || \
known_release == KNOWN_RELEASE_CPMA || \
known_release == KNOWN_RELEASE_QUAKELIVE) \
{ \
/* remap flags for Q3 -- CEV */ \
compat_quake3_item_spawnflags (); \
} \
else if (known_release == KNOWN_RELEASE_COPPER) \
{ \
/* remap flags for Copper -- CEV */ \
compat_copper_item_spawnflags (); \
} \
/* call func (if it's valid) to remap fields -- CEV */ \
/* run before inhibit in case it alters spawnflags -- CEV */ \
base_mapentity_init_spawndata (func); \
/* new spawnflags for all entities -- iw */ \
if (SUB_Inhibit()) \
return; \
/* } */

//--------------------------------------------------------------
void(string key, string value) base_item_init_field =
{
if (known_release == KNOWN_RELEASE_QUAKE3 ||
known_release == KNOWN_RELEASE_CPMA ||
known_release == KNOWN_RELEASE_QUAKELIVE)
{
compat_quake3_entity_init_field (key, value);
}

switch (key)
{
// remap Quoth (and pd3) item respawning fields to
// count, wait, and a spawnflag -- CEV
case "respawncount":
// count limits number of respawns -- CEV
if (!self.count)
self.count = stof (value);
break;
case "respawndelay":
// wait is respawn delay -- CEV
if (!self.wait)
self.wait = stof (value);
break;
case "ritem":
// set SPAWNFLAG_ITEM_RESPAWN -- CEV
local float ritem = stof (value);
if (ritem)
self.spawnflags |=
SPAWNFLAG_ITEM_RESPAWN;
break;
case "particles_offset":
// remap to view_ofs -- CEV
if (!self.view_ofs)
self.view_ofs = stov (value);
}
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) base_item_init =
{
base_mapentity_init (e);
e.classgroup |= CG_ITEM;

e.stateflags |= STATE_PUSHABLE | STATE_TELEPORTABLE;

#ifdef CSQC
local item_info_t iit = item_info[e.weapon];

setsize (e, iit.world_mins, iit.world_maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_item_predraw;
// make sure MOVE_EVERYTHING traces will hit items -- CEV
e.flags |= FL_FINDABLE_NONSOLID;
#endif

#ifdef SSQC
//------------------------------------------------------
// StartItem -- Sets the clipping size and plants the
// object on the floor
//------------------------------------------------------
if (e.spawnflags & SPAWNFLAG_ITEM_THROWN)
{
// call immediately for thrown items -- CEV
sub_runvoidas (e, base_item_think_place);
}
else
{
e.think = base_item_think_place;
// items start after other solids
// was 0.2 -- dumptruck_ds
e.nextthink = time + 0.3;
}
#endif
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
strip void() base_item =
{
base_item_init (self);
};
#endif
// };

Return to the top of this page or return to the overview of this repo.

Log base_item.qc

Return to the top of this page or return to the overview of this repo.