Git Repos / fte_dogmode / qc / items / powerups.qc
Last update to this file was on 2025-08-13 at 05:20.
Show powerups.qc
//==============================================================================
// items/powerups.qc -- POWERUPS
//==============================================================================
//======================================================================
// forward declarations
//======================================================================
// base_item_powerup
#ifdef CSQC
void(float isnew) base_item_powerup_netreceive;
#endif
#ifdef SSQC
// BASE_ITEM_POWERUP_RESPAWNDELAY(idx)
// BASE_ITEM_POWERUP_ADD(pl, idx)
void(entity grabber, entity power) base_item_powerup_grab;
void(entity attacker, float item_index) base_item_powerup_fire;
void() base_item_powerup_touch;
void(string key, string value) base_item_powerup_init_field;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) base_item_powerup_init;
#endif
#ifdef SSQC
strip void() base_item_powerup;
#endif
#ifdef SSQC
//----------------------------------------------------------------------
// original id1 & pd3 spawn functions -- CEV
//----------------------------------------------------------------------
void() item_artifact_envirosuit;
void() item_artifact_invisibility;
void() item_artifact_invulnerability;
void() item_artifact_super_damage;
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------
// class base_item_powerup: base_item
// {
#ifdef CSQC
        //--------------------------------------------------------------
        void(float isnew) base_item_powerup_netreceive =
        {
                // creates a number of variables, including netflags -- CEV
                BASE_ITEM_NETRECEIVE (base_item_powerup_init)
        };
#endif
#ifdef SSQC
        //--------------------------------------------------------------
        #define BASE_ITEM_POWERUP_RESPAWNDELAY(idx) \
        { \
                local float delay_sp = 0; \
                local float delay_dm = 0; \
                if (deathmatch) \
                { \
                        if (idx == ITEM_SEQ_ARTIFACT_INVISIBILITY || \
                                idx == ITEM_SEQ_ARTIFACT_INVULNERABILITY) \
                        { \
                                delay_dm = time + 60 * 5; \
                        } \
                        else \
                        { \
                                delay_dm = time + 60; \
                        } \
                } \
                else \
                { \
                        if (idx == ITEM_SEQ_ARTIFACT_INVISIBILITY || \
                                idx == ITEM_SEQ_ARTIFACT_INVULNERABILITY) \
                        { \
                                delay_sp = 300; \
                        } \
                        else \
                        { \
                                delay_sp = 60; \
                        } \
                } \
        }
        //--------------------------------------------------------------
        #define BASE_ITEM_POWERUP_ADD(pl, idx) \
        { \
                /* do the apropriate action */ \
                if (idx == ITEM_SEQ_ARTIFACT_ENVIROSUIT) \
                { \
                        pl.items |= IT_SUIT; \
                        pl.rad_time = 1; \
                        pl.radsuit_finished = time + 30; \
                } \
                else if (idx == ITEM_SEQ_ARTIFACT_INVISIBILITY) \
                { \
                        pl.items |= IT_INVISIBILITY; \
                        pl.invisible_time = 1; \
                        pl.invisible_finished = time + 30; \
                } \
                else if (idx == ITEM_SEQ_ARTIFACT_INVULNERABILITY) \
                { \
                        pl.items |= IT_INVULNERABILITY; \
                        pl.invincible_time = 1; \
                        pl.invincible_finished = time + 30; \
                } \
                else if (idx == ITEM_SEQ_ARTIFACT_QUAD) \
                { \
                        pl.items |= IT_QUAD; \
                        pl.super_time = 1; \
                        pl.super_damage_finished = time + 30; \
                } \
        }
        //--------------------------------------------------------------
        void(entity grabber, entity power) base_item_powerup_grab =
        {
                BASE_ITEM_INVENTORY_ADD (power, grabber)
                // don't re-grab / immediately throw the item -- CEV
                if (grabber.button4)
                        grabber.flags |= FL_THROW_HELD;
                // let the player know -- CEV
                sprint (grabber, sprintf("%s grabbed the %s\n",
                        grabber.netname, power.netname));
                // let the client (CSQC) know -- CEV
                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 = power;
                activator = other;
                sub_usetargets ();
                self = stemp;
                other = otemp;
                // either remove the item or set up for respawning -- CEV
                BASE_ITEM_POWERUP_RESPAWNDELAY (power.weapon)
                BASE_ITEM_CHECKREMOVE (power, delay_sp, delay_dm)
        };
        //--------------------------------------------------------------
        void(entity attacker, float item_index) base_item_powerup_fire =
        {
                // add the item -- CEV
                BASE_ITEM_POWERUP_ADD (attacker, item_index)
                // now remove the powerup from the inventory -- CEV
                BASE_ITEM_INVENTORY_REMOVE (attacker)
                // make sure the client knows -- CEV
                if (attacker.classtype == CT_PLAYER && attacker.SendEntity)
                        attacker.SendFlags |= NETFLAG_PLAYER_ITEMS |
                                NETFLAG_PLAYER_WEAPON;
                // and make sure the player knows -- CEV
                local item_info_t iit = item_info[item_index];
                BASE_ITEM_PICKUPMESSAGE (attacker, iit)
        };
        //--------------------------------------------------------------
        void() base_item_powerup_touch =
        {
                // thrown item check -- CEV
                if (base_item_touch_projectile())
                        return;
                if (sub_checkvalidtouch(other) == FALSE)
                        return;
                // 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.button4)
                        {
                                // self.attack_finished = time + 0.5;
                                base_item_powerup_grab (other, self);
                                return;
                        }
                        else if (!other.button0)
                        {
                                return;
                        }
                }
                // add the item -- CEV
                BASE_ITEM_POWERUP_RESPAWNDELAY (self.weapon)
                BASE_ITEM_POWERUP_ADD (other, self.weapon)
                local item_info_t iit = item_info[self.weapon];
                BASE_ITEM_PICKUPMESSAGE (other, iit)
                // fire all targets / killtargets
                activator = other;
                sub_usetargets ();
                // either remove the item or set up for respawning -- CEV
                BASE_ITEM_CHECKREMOVE (self, delay_sp, delay_dm)
        };
        //--------------------------------------------------------------
        void(string key, string value) base_item_powerup_init_field =
        {
                base_item_init_field (key, value);
        };
#endif
#if defined(CSQC) || defined(SSQC)
        //--------------------------------------------------------------
        void(entity e) base_item_powerup_init =
        {
                local item_info_t iit = item_info[e.weapon];
                e.classgroup |= CG_ITEM_POWERUP;
                e.netname = iit.name;
                #ifdef CSQC
                setmodelindex (e, e.modelindex);
                e.modelflags |= MF_ROTATE;
                #endif
                #ifdef SSQC
                e.classname = iit.classname;
                e.classtype = iit.classtype;
                e.items = iit.option;
                e.touch = base_item_powerup_touch;
                if (!e.dmg && iit.dmg)
                        e.dmg = iit.dmg;
                if (!e.skin && iit.world_skin)
                        e.skin = iit.world_skin;
                // precaches & other info not included in item_info_t -- CEV
                // t_fog fix for custom models -- dumptruck_ds
                switch (e.weapon)
                {
                        case ITEM_SEQ_ARTIFACT_ENVIROSUIT:
                                precache_sound (snd_item_suit_off.wav);
                                e.view_ofs = '0 0 32';
                                break;
                        case ITEM_SEQ_ARTIFACT_INVISIBILITY:
                                precache_sound (snd_item_invis_off.wav);
                                precache_sound (snd_item_invis_amb.wav);
                                e.view_ofs = '0 0 0';
                                break;
                        case ITEM_SEQ_ARTIFACT_INVULNERABILITY:
                                // called in client.qc -- dumptruck_ds
                                precache_sound (snd_item_pent_off.wav);
                                // called in combat.qc -- dumptruck_ds
                                precache_sound (snd_item_pent_prot.wav);
                                e.view_ofs = '0 0 16';
                                break;
                        case ITEM_SEQ_ARTIFACT_QUAD:
                                precache_sound (snd_item_quad_dam.wav);
                                e.view_ofs = '0 0 16';
                                break;
                }
                precache_model (iit.world_model);
                precache_sound (iit.pickup_sound.wav);
                setmodel (e, iit.world_model);
                #endif
                base_item_init (e);
        };
#endif
#ifdef SSQC
        //--------------------------------------------------------------
        strip void() base_item_powerup =
        {
                base_item_powerup_init (self);
        };
#endif
// };
//----------------------------------------------------------------------
// id1 & pd3 spawn functions -- CEV
//----------------------------------------------------------------------
#ifdef SSQC
//----------------------------------------------------------------------
#define ITEM_PUP(idx) \
/* { */ \
        BASE_ITEM_PREINIT (base_item_powerup_init_field) \
        self.weapon = idx; \
        base_item_powerup_init (self);
/* } */
/*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32) X X 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("progs/suit.mdl");        }
Biosuit
Player takes no damage from water or slime for 30 seconds
*/
//----------------------------------------------------------------------
// class item_artifact_envirosuit: base_item_powerup
// {
        //--------------------------------------------------------------
        void() item_artifact_envirosuit =
                { ITEM_PUP (ITEM_SEQ_ARTIFACT_ENVIROSUIT) };
// };
/*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32) X X 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("progs/invisibl.mdl");    }
Ring of Shadows
Player is invisible for 30 seconds
*/
//----------------------------------------------------------------------
// class item_artifact_invisibility: base_item_powerup
// {
        //--------------------------------------------------------------
        void() item_artifact_invisibility =
                { ITEM_PUP (ITEM_SEQ_ARTIFACT_INVISIBILITY) };
// };
/*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32) X X 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("progs/invulner.mdl");    }
Pentagram of Protection
Player is invulnerable for 30 seconds
*/
//----------------------------------------------------------------------
// class item_artifact_invulnerability: base_item_powerup
// {
        //--------------------------------------------------------------
        void() item_artifact_invulnerability =
                { ITEM_PUP (ITEM_SEQ_ARTIFACT_INVULNERABILITY) };
// };
/*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32) X X 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("progs/quaddama.mdl");    }
Quad Damage
Player does 4x damage for 30 seconds
*/
//----------------------------------------------------------------------
// class item_artifact_super_damage: base_item_powerup
// {
        //--------------------------------------------------------------
        void() item_artifact_super_damage =
                { ITEM_PUP (ITEM_SEQ_ARTIFACT_QUAD) };
// };
#undef ITEM_PUP
#endif
Return to the top of this page or return to the overview of this repo.
Log powerups.qc
| Date | Commit Message | Author | + | - | 
|---|---|---|---|---|
| 2025-08-13 | Another big commit. Item changes, field rework, etc. | cev | +82 | -305 | 
| 2025-03-30 | Big commit. Entity networking, etc. | cev | +367 | -172 | 
| 2024-06-15 | Major update, committing as-is, will have bugs | cev | +21 | -1 | 
| 2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +212 | -93 | 
| 2024-02-18 | Client/player, projectiles, entrypoints refactor | cev | +13 | -13 | 
| 2024-01-13 | Refactored items into classes, fix teleporttrain | cev | +183 | -170 | 
| 2023-12-09 | Start OO / class-based refactor, work on items | cev | +14 | -13 | 
| 2023-12-02 | More refactoring & moving, begin adding mdls & snd | cev | +224 | 
Return to the top of this page or return to the overview of this repo.