djcev.com

//

Git Repos / fte_dogmode / qc / items / health.qc

Last update to this file was on 2025-03-30 at 19:29.

Show health.qc

//==============================================================================
// HEALTH BOXES
//==============================================================================

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

#ifdef SSQC
//----------------------------------------------------------------------
// base health item spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_ITEM_HEALTH_ROTTEN = 1, // rotten health box
SPAWNFLAG_ITEM_HEALTH_MEGA = 2, // megahealth
SPAWNFLAG_ITEM_HEALTH_VIAL = 4 // vial (AKA bubble)
// SPAWNFLAG_ITEM_SPAWNSILENT = 32, // see base_item.qc -- CEV
// SPAWNFLAG_ITEM_SPAWNED = 64, // see base_item.qc -- CEV
// SPAWNFLAG_ITEM_SUSPENDED = 128, // see base_item.qc -- CEV
// 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 = 2097152, // see base_item.qc -- CEV
// SPAWNFLAG_ITEM_THROWN = 4194304, // see base_item.qc -- CEV
// SPAWNFLAG_ITEM_DONTDROP = 8388608 // see base_item.qc -- CEV
} base_item_health_spawnflags;
#endif

#ifdef SSQC
const float HEALTH_DAMAGE_SMALL = 10; // damage a small box deals when thrown
const float HEALTH_DAMAGE_LARGE = 15; // same, but for large boxes (mega)
const float HEALTH_DAMAGE_VIAL = 5; // same, but for health vials

// constants amounts & respawn times
const float HEALTH_ROTTEN_AMOUNT = 15; // rotten heal amount; id1 15
const float HEALTH_NORMAL_AMOUNT = 25; // standard heal amount; id1 25
const float HEALTH_MEGA_AMOUNT = 100; // megahealth amount; id1 100
const float HEALTH_VIAL_AMOUNT = 5; // vial heal amount; Quake3 5
const float HEALTH_RESPAWN_DM = 20; // deathmatch respawn time; id1 20
const float HEALTH_RESPAWN_SP = 30; // singleplayer respawn time; id1 30
const float HEALTH_RESPAWN_MEGA = 125; // fixed mega respawn time; pd3 125
#endif

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

#ifdef SSQC
// TODO CEV roll T_Heal into addhealth somehow (triggers/heal.qc is a problem)
float (entity e, float healamount, float ignore) T_Heal;
#endif

// base_item_health
#ifdef SSQC
// BASE_ITEM_HEALTH_RESPAWNDM(health_item)
float(entity toucher, float item_index) base_item_health_addhealth;
void(entity grabber, entity box) base_item_health_grab;
void(entity attacker, float item_index) base_item_health_fire;
void() base_item_health_touch;
void(string key, string value) base_item_health_init_field;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) base_item_health_init;
#endif
#ifdef SSQC
strip void() base_item_health;
#endif

// item_health
#ifdef CSQC
void(float isnew) item_health_netreceive;
#endif
#ifdef SSQC
entity(entity src, vector org, vector vel, float fl) spawn_item_health;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) item_health_init;
#endif
#ifdef SSQC
void() item_health;
#endif

// item_health_vial
#ifdef CSQC
void(float isnew) item_health_vial_netreceive;
#endif
#ifdef SSQC
entity(entity src) item_health_vial_drop;
entity(entity src, vector org, vector vel, float fl) spawn_item_health_vial;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) item_health_vial_init;
#endif
#ifdef SSQC
void() item_health_vial;
#endif

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

#ifdef SSQC
//----------------------------------------------------------------------
// T_Heal: add health to an entity, limiting health to max_health
// "ignore" will ignore max_health limit
//----------------------------------------------------------------------
float (entity e, float healamount, float ignore) T_Heal =
{
if (e.health <= 0)
return 0;
if ((!ignore) && (e.health >= e.max_health))
return 0;
healamount = ceil(healamount);

e.health = e.health + healamount;
if ((!ignore) && (e.health >= e.max_health))
e.health = e.max_health;

if (e.health > PLAYER_HEALTH_MEGA)
e.health = PLAYER_HEALTH_MEGA;
return 1;
};
#endif

//----------------------------------------------------------------------
// class base_item_health: base_item
// {
#ifdef SSQC
//--------------------------------------------------------------
#define BASE_ITEM_HEALTH_RESPAWNDM(health_item) \
{ \
/* Special case for megahealth -- CEV */ \
/* Regarding the deathmatch respawn time below:
* id's original code made the megahealth respawn 20 seconds
* after the health of the player who collected it finished
* rotting down. However, this mod has already got rid of the
* weird old megahealth behavior whereby it monitored the
* player who touched it, so the original respawn logic isn't
* applicable. As a solution, the code below uses a respawn
* time of 125 seconds for deathmatch, because that was the
* worst-case scenario of id's original code (5 seconds before
* the player's health started to rot, plus 100 seconds to rot
* down 100 health points, plus the original 20 second delay
* before the item respawned). -- iw */ \
local float respawndm; \
if (health_item.weapon == ITEM_SEQ_HEALTH_MEGA) \
respawndm = HEALTH_RESPAWN_MEGA; \
else \
respawndm = HEALTH_RESPAWN_DM; \
}

//--------------------------------------------------------------
float(entity toucher, float item_index) base_item_health_addhealth =
{
local float amount = 0;

switch (item_index)
{
case ITEM_SEQ_HEALTH_ROTTEN:
amount = HEALTH_ROTTEN_AMOUNT;
break;
case ITEM_SEQ_HEALTH:
amount = HEALTH_NORMAL_AMOUNT;
break;
case ITEM_SEQ_HEALTH_MEGA:
amount = HEALTH_MEGA_AMOUNT;
break;
case ITEM_SEQ_HEALTH_VIAL:
amount = HEALTH_VIAL_AMOUNT;
break;
}

if (item_index == ITEM_SEQ_HEALTH_MEGA ||
item_index == ITEM_SEQ_HEALTH_VIAL)
{
// Megahealth? Ignore max_health...
if (toucher.health >= PLAYER_HEALTH_MEGA)
return FALSE;
if (!T_Heal(toucher, amount, 1))
return FALSE;

// Megahealth = rot down the player's super health
// thanks ydrol!!!
toucher.megahealth_rottime = time + 5;
toucher.items = toucher.items | IT_SUPERHEALTH;
}
else
{
if (!T_Heal(toucher, amount, 0))
return FALSE;
}

sprint (toucher, sprintf("%s receives %g health!\n",
toucher.netname, amount));

local item_info_t item = item_info[item_index];
sound (toucher, CHAN_ITEM_HEALTH, item.pickup_sound,
item.pickup_vol, ATTN_NORM);

stuffcmd (toucher, "bf\n");

return TRUE;
};

//--------------------------------------------------------------
// base_item_health_grab -- player has 'grabbed' the item -- CEV
//--------------------------------------------------------------
void(entity grabber, entity box) base_item_health_grab =
{
BASE_ITEM_INVENTORY_ADD (box, grabber)

sprint (grabber, sprintf("%s grabbed the %s\n",
grabber.netname, box.netname));

// don't re-grab / immediately throw the item -- CEV
if (grabber.button6)
grabber.flags |= FL_THROW_HELD;

if (grabber.classtype == CT_PLAYER && grabber.SendEntity)
grabber.SendFlags |= NETFLAG_PLAYER_WEAPON;

// fire all targets / killtargets
local entity stemp = self;
local entity otemp = other;
other = grabber;
self = box;
activator = other;
sub_usetargets ();
self = stemp;
other = otemp;

// remove or respawn -- CEV
BASE_ITEM_HEALTH_RESPAWNDM (box)
BASE_ITEM_CHECKREMOVE (box, HEALTH_RESPAWN_SP, respawndm)
};

//--------------------------------------------------------------
// base_item_health_fire
// player has pressed +attack while holding the item -- CEV
//--------------------------------------------------------------
void(entity attacker, float item_index) base_item_health_fire =
{
// open the health box -- CEV
if (base_item_health_addhealth(attacker, item_index) == FALSE)
// health didn't add (for whatever reason) -- CEV
return;

// now remove the health box from inventory -- CEV
BASE_ITEM_INVENTORY_REMOVE (attacker)

if (attacker.classtype == CT_PLAYER && attacker.SendEntity)
attacker.SendFlags |= NETFLAG_PLAYER_HEALTH |
NETFLAG_PLAYER_WEAPON;
};

//--------------------------------------------------------------
// health_touch
//--------------------------------------------------------------
void() base_item_health_touch =
{
// thrown item check -- CEV
if (base_item_touch_projectile())
return;

if (sub_checkvalidtouch(other) == FALSE)
return;

// ...except for this: don't touch() if the player isn't
// holding a weapon -- CEV
BASE_ENTITY_WEAPONLOOKUP (other)
if (item_index < ITEM_SEQ_W_START||item_index > ITEM_SEQ_W_END)
{
if (item_index == ITEM_SEQ_HANDS && other.button6 &&
!(other.flags & FL_THROW_HELD))
{
// self.attack_finished = time + 0.5;
base_item_health_grab (other, self);
return;
}
else
{
return;
}
}

if (base_item_health_addhealth(other, self.weapon) == FALSE)
return;

if (other.classtype == CT_PLAYER && other.SendEntity)
other.SendFlags |= NETFLAG_PLAYER_HEALTH;

// fire all targets / killtargets
activator = other;
sub_usetargets ();

// remove or respawn -- CEV
BASE_ITEM_HEALTH_RESPAWNDM (self)
BASE_ITEM_CHECKREMOVE (self, HEALTH_RESPAWN_SP, respawndm)
};

//--------------------------------------------------------------
void(string key, string value) base_item_health_init_field =
{
base_item_init_field (key, value);
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) base_item_health_init =
{
e.classgroup |= CG_ITEM_HEALTH;

local item_info_t item = item_info[e.weapon];

#ifdef SSQC
e.touch = base_item_health_touch;
precache_model (item.world_model);
precache_sound (item.pickup_sound);
setmodel (e, item.world_model);
#endif

#ifdef CSQC
setmodelindex (e, e.modelindex);
#endif

e.noise = item.pickup_sound;
e.netname = item.name;

base_item_init (e);

#ifdef SSQC
// set up rotation -- CEV
BASE_ITEM_THROW_ROTATION (e, item)
#endif
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
strip void() base_item_health =
{
base_item_health_init (self);
};
#endif
// };

/*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) ROTTEN MEGAHEALTH X X X SPAWN_SILENT TRIGGER_SPAWNED SUSPENDED_IN_AIR NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER RESPAWN_WITH_DM_EFFECTS NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ( {{ spawnflags & 1 -> { "path" : "maps/b_bh10.bsp" }, spawnflags & 2 -> { "path" : "maps/b_bh100.bsp" },
"maps/b_bh25.bsp" }} );
}
Health box. Normally gives 25 points.
Rotten box heals 15 points.
Megahealth will add 100 health, then start to
rot the player back down to 100 health after 5 seconds.
*/
//----------------------------------------------------------------------
// class item_health: base_item_health
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) item_health_netreceive =
{
// creates a number of variables, including netflags -- CEV
BASE_ITEM_NETRECEIVE (item_health_init)
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float fl)
spawn_item_health =
{
local entity e = spawn ();
e.owner = src;
e.spawnflags = fl;
e.origin = org;
e.velocity = vel;
item_health_init (e);
return e;
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) item_health_init =
{
e.classname = "item_health";
e.classtype = CT_ITEM_HEALTH;

#ifdef SSQC
if (e.spawnflags & SPAWNFLAG_ITEM_HEALTH_ROTTEN)
{
e.weapon = ITEM_SEQ_HEALTH_ROTTEN;
e.dmg = HEALTH_DAMAGE_SMALL;
if !(e.particles_offset)
e.particles_offset = '16 16 8';
}
else if (e.spawnflags & SPAWNFLAG_ITEM_HEALTH_MEGA)
{
e.weapon = ITEM_SEQ_HEALTH_MEGA;
e.dmg = HEALTH_DAMAGE_LARGE;
if !(e.particles_offset)
e.particles_offset = '16 16 16';
}
else
{
e.weapon = ITEM_SEQ_HEALTH;
e.dmg = HEALTH_DAMAGE_SMALL;
if !(e.particles_offset)
e.particles_offset = '16 16 8';
}
#endif

e.pos1 = '0 0 0';
e.pos2 = '32 32 56';

// StartItem
base_item_health_init (e);
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
void() item_health =
{
// remap spawnflags, inhibit spawn, remap fields -- CEV
BASE_ITEM_PREINIT (base_item_health_init_field)

item_health_init (self);
};
#endif
// };

//----------------------------------------------------------------------
// item_health_vial
//----------------------------------------------------------------------
// class item_health_vial: base_item_health
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) item_health_vial_netreceive =
{
// creates a number of variables, including netflags -- CEV
BASE_ITEM_NETRECEIVE (item_health_vial_init)
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
entity(entity src) item_health_vial_drop =
{
local vector vel;
vel_x = -100 + (random() * 200);
vel_y = -100 + (random() * 200);
vel_z = 300;
return spawn_item_health_vial (src, src.origin - '0 0 24',
vel, SPAWNFLAG_ITEM_THROWN);
};

//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float fl)
spawn_item_health_vial =
{
local entity e = spawn ();
e.owner = src;
e.spawnflags = fl;
e.origin = org;
e.velocity = vel;
item_health_vial_init (e);
return e;
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) item_health_vial_init =
{
e.classname = "item_health_vial";
e.classtype = CT_ITEM_HEALTH_VIAL;

#ifdef SSQC
e.weapon = ITEM_SEQ_HEALTH_VIAL;
e.dmg = HEALTH_DAMAGE_VIAL;

if !(e.particles_offset)
e.particles_offset = '0 0 0';
#endif

e.pos1 = '-16 -16 0';
e.pos2 = '16 16 56';

// StartItem
base_item_health_init (e);
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
void() item_health_vial =
{
// remap spawnflags, inhibit spawn, remap fields -- CEV
BASE_ITEM_PREINIT (base_item_health_init_field)

item_health_vial_init (self);
};
#endif
// };

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

Log health.qc

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