Quake DeveLS - Exploding Health Boxes

Author: Mark "Grey" Davies
Difficulty: Easy

Overview:

This tutorial just explains how to add exploding health boxes to your mods. When a player touches a health box the following code checks to see if that player has reached or exeeded max health. If so, the health box explodes into stimpacks, otherwise the box acts as normal.

The cvar "exploding_health" can be set to indicate how many groups of 8 stimpacks are released. A setting of 0 turns off exploding stimpacks. I do not suggest setting this value to more than 4.

Instructions:

Locate the Pickup_Health() function, it should be located in the g_items.c file. Replace the following text

qboolean Pickup_Health (edict_t *ent, edict_t *other)
{
	if (!(ent->style & HEALTH_IGNORE_MAX))
		if (other->health >= other->max_health)
			return false;

with

qboolean Pickup_Health (edict_t *ent, edict_t *other)
{
	if (!(ent->style & HEALTH_IGNORE_MAX))
		if (other->health >= other->max_health)
        {
            cvar_t *health = gi.cvar( "exploding_health", "1", CVAR_SERVERINFO );

            if( health->value )
            {
                gitem_t *item = NULL;
                edict_t	*dropped;
                vec3_t	offset;
                int     i,j;
                int     speed = 10;            
                vec3_t  spray[] = {
                    {  25,  00,  40 },
                    {  17, -17,  40 },
                    {  00, -25,  40 },
                    { -17, -17,  40 },
                    { -25,  00,  40 },
                    { -17,  17,  40 },
                    {  00,  25,  40 },
                    {  17,  17,  40 },
                };

                for( j=0; j < min((int)health->value,4); j++ )
                    for( i=0; i< (sizeof(spray)/sizeof(spray[0])); i++ )
                    {
                        vec3_t	forward = { 5.0, 5.0, 5.0 };
                        vec3_t  right   = { 5.0, 5.0, 5.0 };
                        vec3_t  up      = { 5.0, 5.0, 5.0 };

                        VectorSet(offset, spray[i][0], spray[i][1], spray[i][2]);

                        offset[0] += ((crandom() * 16.0) - 8.0);
                        offset[1] += ((crandom() * 16.0) - 8.0);
                        offset[2] += ((crandom() * 16.0) - 8.0);

                        speed += (crandom() * 10.0);

                        dropped = G_Spawn();

                        dropped->model = "models/items/healing/stimpack/tris.md2";
                        dropped->count = 2;
                        dropped->style = HEALTH_IGNORE_MAX;
                        item = FindItem ("Health");


                        dropped->classname = item->classname;
                        dropped->item = item;
                        dropped->spawnflags = DROPPED_ITEM;
                        dropped->s.effects = item->world_model_flags;
                        dropped->s.renderfx = RF_GLOW;
                        VectorSet (dropped->mins, -15, -15, -15);
                        VectorSet (dropped->maxs, 15, 15, 15);

                        gi.setmodel (dropped, dropped->model);

                        dropped->solid = SOLID_TRIGGER;
                        //dropped->movetype = MOVETYPE_TOSS;  
                        dropped->movetype = MOVETYPE_BOUNCE;
                        dropped->touch = drop_temp_touch;
                        dropped->owner = other;

                        dropped->s.effects |= EF_COLOR_SHELL; // EF_GRENADE;

                        /* throw bouncing stimpacks */
                        {
                            trace_t	trace;
                            vec3_t	dir;

                            vectoangles (offset, dir);
                            AngleVectors (dir, forward, right, up);

                            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 (offset, speed, dropped->velocity);
                        dropped->velocity[2] = 300;

                        dropped->think = drop_make_touchable;
                        dropped->nextthink = level.time + 1.0;

                        gi.linkentity (dropped);
                    }

                if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
                    SetRespawn (ent, 20);   /* respawn quicker than normal */

                return true;
            }
            else
            {
                return false;
            }
        }

Mark "Grey" Davies