Git Repos / fte_dogmode / qc / base_gore.qc
Last update to this file was on 2024-06-15 at 19:50.
Show base_gore.qc
//==============================================================================
// base_gore.qc -- corpses, gibs, heads. the meaty bits. -- CEV
//==============================================================================
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//
// deadstuff version 1.0 - tony collen - manero@canweb.net -
// EfNet IRC #QuakeEd or #Trinity
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//======================================================================
// constants
//======================================================================
#ifdef SSQC
const float GIB_SOLID = 1; // spawnflags: solid
const float GIB_DYNAMIC = 2; // non-static, moveable gibs
const float CORPSE_HEALTH = 30; // static corpse health
const vector GIB_1_MINS = '-3.57 -8.06 -3.34';
const vector GIB_1_MAXS = '3.69 8.31 30';
const vector GIB_2_MINS = '-12.68 -14.83 -6.19';
const vector GIB_2_MAXS = '13.53 14.57 30';
const vector GIB_3_MINS = '-18.95 -15.92 -3.13';
const vector GIB_3_MAXS = '13.17 15.66 30';
#endif
//======================================================================
// forward declarations
//======================================================================
#ifdef SSQC
void(vector org, vector vel, float damage) spawn_blood;
void(float damage) spawn_touchblood;
void(vector org, vector vel) spawn_chunk;
entity(vector org, vector vel) spawn_meatspray;
vector(vector dir, float dmg) velocity_for_damage;
#endif
#ifdef SSQC
// base_corpse
void(entity e, float corpse_health) become_base_corpse;
void(entity e) base_corpse_init;
strip void() base_corpse;
#endif
#ifdef SSQC
// base_gib
void() base_gib_touch;
entity(entity src, vector org, vector vel, float sflags, .string gibfield,
void(entity) initfn) spawn_base_gib;
void(entity e) base_gib_init;
strip void() base_gib;
#endif
#ifdef SSQC
// gib_misc_1
void(entity src, vector dir, float dmg) throw_gib_1;
entity(entity src, vector org, vector vel, float sflags) spawn_gib_misc_1;
void(entity e) gib_misc_1_init;
void() gib_misc_1;
#endif
#ifdef SSQC
// gib_misc_2
void(entity src, vector dir, float dmg) throw_gib_2;
entity(entity src, vector org, vector vel, float sflags) spawn_gib_misc_2;
void(entity e) gib_misc_2_init;
void() gib_misc_2;
#endif
#ifdef SSQC
// gib_misc_3
void(entity src, vector dir, float dmg) throw_gib_3;
entity(entity src, vector org, vector vel, float sflags) spawn_gib_misc_3;
void(entity e) gib_misc_3_init;
void() gib_misc_3;
#endif
#ifdef SSQC
// base_gib_head
void(entity e, vector dir, float dmg, void(entity e) initfn)
base_gib_head_throw;
void(entity e) base_gib_head_init;
strip void() base_gib_head;
#endif
//------------------------------------------------------------------------------
#ifdef SSQC
//----------------------------------------------------------------------
// SpawnBlood
//----------------------------------------------------------------------
void(vector org, vector vel, float damage) spawn_blood =
{
particle (org, vel * 0.1, 73, damage * 2);
};
//----------------------------------------------------------------------
// spawn_touchblood
//----------------------------------------------------------------------
void(float damage) spawn_touchblood =
{
// wall_velocity
local vector vel;
vel = normalize (self.velocity);
vel = normalize (vel + v_up * (random() - 0.5) +
v_right * (random() - 0.5));
// TODO CEV when was the last time a trace was called?
vel = vel + 2 * trace_plane_normal;
vel = (vel * 200) * 0.2;
spawn_blood (self.origin + vel * 0.01, vel, damage);
};
//----------------------------------------------------------------------
// SpawnChunk
//----------------------------------------------------------------------
void(vector org, vector vel) spawn_chunk =
{
particle (org, vel * 0.02, 0, 10);
};
//----------------------------------------------------------------------
// SpawnMeatSpray
//----------------------------------------------------------------------
entity(vector org, vector vel) spawn_meatspray =
{
// reusing the "zombiechunk" projectile -- CEV
local entity e = spawn_projectile_zombiechunk (self, org, vel);
// override some defaults, notably solid and force damage to 0 -- CEV
e.solid = SOLID_NOT;
e.direct_damage = 0;
e.velocity_z += 250 + 50 * random ();
e.nextthink = time + 1;
return e;
};
//----------------------------------------------------------------------
vector(vector dir, float dmg) velocity_for_damage =
{
// local vector startdir = dir;
local vector v;
// next three lines original id1 behavior -- CEV
v_x = 100 * crandom ();
v_y = 100 * crandom ();
v_z = 200 + 100 * random ();
// damage response scaling from Alkaline, presumably by bmFbr -- CEV
v *= max (1, min(10, dmg * dmg / 5000));
if (dir != '0 0 0')
{
// directional gib behavior from Alkaline (which appears to
// be by bmFbr according to the commit log, see Alkaline
// commit 083f87c18a2d2be645ba197c1f23fc6533afca81).
// dir is set by killed () and is already normalized -- CEV
dir *= bound (10, dmg * dmg / 22, 800);
dir_x *= 2.5;
dir_y *= 2.5;
dir_z *= 0.7;
v += dir;
}
// velocity limiting code again from Alkaline and written by bmFbr.
// I'm leaning on Alkaline here and above because the implementation
// I came up with was way worse. -- CEV
local float vspeed = vlen (v);
if (vspeed > 500)
v *= 500 / vspeed;
v_z = min (500, v_z);
// dprint (sprintf("velocity_for_damage: damage is %g, startdir is %v, "
// "v is %v\n", dmg, startdir, v));
return v;
};
#endif
#ifdef SSQC
//----------------------------------------------------------------------
// Corpse base class, used for both converting dead monsters into corpses
// and for DeadStuff mod mapper-placeable corpses -- CEV
//----------------------------------------------------------------------
// class base_corpse: base_mapentity
// {
//--------------------------------------------------------------
// Convert an entity into a shootable corpse. Call at the end of
// a monster's death think. Uses FTE's SOLID_CORPSE. Inspired by
// / based on Kryten's gibbable corpse tutorial found at
// https://www.insideqc.com/qctut/qctut-33.shtml -- CEV
//--------------------------------------------------------------
void(entity e, float corpse_health) become_base_corpse =
{
e.classgroup |= CG_CORPSE;
// set up trigger interaction
e.flags &= ~FL_MONSTER;
if (corpse_health)
e.health = corpse_health;
else
e.health = CORPSE_HEALTH;
// e.movetype = MOVETYPE_STEP;
e.solid = SOLID_CORPSE;
e.takedamage = DAMAGE_YES;
// clear targets
e.killtarget = e.killtarget2 = __NULL__;
e.pain_target = __NULL__;
e.target = e.target2 = e.target3 = e.target4 = __NULL__;
// clear everything but destroy
// leave e.destroy alone, the existing destroy will handle it
e.th_pain = sub_nullpain;
// leave e.think alone so e's animation can finish
e.touch = sub_null;
e.use = sub_null;
// clear monster think functions
e.th_melee = sub_null;
e.th_missile = sub_null;
e.th_run = sub_null;
e.th_stand = sub_null;
e.th_turret = sub_null;
e.th_walk = sub_null;
};
//--------------------------------------------------------------
void(entity e) base_corpse_init =
{
base_mapentity_init (e);
e.classgroup |= CG_CORPSE;
if (e.spawnflags & GIB_SOLID)
e.solid = SOLID_BBOX;
else
e.solid = SOLID_NOT;
};
//--------------------------------------------------------------
strip void() base_corpse =
{
base_corpse_init (self);
};
// };
#endif
#ifdef SSQC
//----------------------------------------------------------------------
// class base_gib: base_mapentity
// {
//--------------------------------------------------------------
// Inspired by Ivana Gibson's kickable gibs [1] and similar
// functions found in other mods (Scarlet, etc) -- CEV
// [1]: https://www.insideqc.com/qctut/lesson-52.shtml
//--------------------------------------------------------------
void() base_gib_touch =
{
// only run if the object has come to rest -- CEV
if (self.velocity)
return;
// only run if touched by a player or monster -- CEV
if (other.classtype != CT_PLAYER && !(other.flags & FL_MONSTER))
return;
// only run if other is moving fast enough to disturb
// stationary objects -- CEV
if (other.classtype == CT_PLAYER && other.speed < 200)
return;
// push self horizontally according to other's direction and
// speed, maximum of 160ups -- CEV
base_entity_push (self, other, PM_MAXSPEED * 0.5);
if (self.avelocity_y == 0)
// a little spin, as a treat. Rotating in the other
// axes seem to cause gibs to move into the floor -- CEV
self.avelocity_y = 100 * crandom ();
};
//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float sflags,
.string gibfield, void(entity) initfn) spawn_base_gib =
{
local entity e = spawn ();
e.owner = src;
e.spawnflags = sflags;
e.origin = org;
e.velocity = vel;
if (src.gibfield && src.gibfield != "")
e.gibfield = src.gibfield;
initfn (e);
return e;
};
//--------------------------------------------------------------
void(entity e) base_gib_init =
{
if (!(e.flags & FL_CLIENT))
base_mapentity_init (e);
e.classgroup |= CG_CORPSE;
// if we're converting an existing entity and it has a destroy
// function make sure that destroy func is sub_null -- CEV
if (e.destroy)
e.destroy = sub_nulldestroy;
if (e.spawnflags & GIB_SOLID)
{
e.solid = SOLID_BBOX;
}
else if (e.spawnflags & GIB_DYNAMIC)
{
e.movetype = MOVETYPE_BOUNCE;
e.takedamage = DAMAGE_NO;
e.solid = SOLID_TRIGGER;
e.touch = base_gib_touch;
if (e.flags & FL_CLIENT)
e.flags = e.flags - (e.flags & FL_ONGROUND);
else
e.flags = 0;
}
else
{
e.solid = SOLID_NOT;
}
};
strip void() base_gib =
{
base_gib_init (self);
};
// };
#endif
#ifdef SSQC
/*QUAKED gib_misc_1 (0 0.5 0.8) (-8 -8 -8) (8 8 8) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/gib1.mdl");
}*/
//----------------------------------------------------------------------
// class gib_misc_1: base_gib
// {
//--------------------------------------------------------------
// 'self' in this context is the thing being gibbed -- CEV
//--------------------------------------------------------------
void(entity src, vector dir, float dmg) throw_gib_1 =
{
local entity e = spawn_gib_misc_1 (src, src.origin + '0 0 24',
velocity_for_damage(dir, dmg), GIB_DYNAMIC);
e.avelocity_x = random() * 600;
e.avelocity_y = random() * 600;
e.avelocity_z = random() * 600;
e.alpha = 1.0;
e.think = sub_remove_fade;
e.ltime = time;
e.nextthink = time + 10 + random() * 10;
};
//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float sflags)
spawn_gib_misc_1 =
{
return spawn_base_gib (src, org, vel, sflags, mdl_gib2,
gib_misc_1_init);
};
//--------------------------------------------------------------
void(entity e) gib_misc_1_init =
{
e.classname = "gib_misc_1";
e.classtype = CT_GORE_GIB1;
// this will set e.solid
base_gib_init (e);
if (e.mdl_gib1 != "")
{
precache_model (e.mdl_gib1);
setmodel (e, e.mdl_gib1);
}
else
{
precache_model ("progs/gib1.mdl");
setmodel (e, "progs/gib1.mdl");
if (e.solid == SOLID_BBOX || e.solid == SOLID_TRIGGER)
setsize (e, GIB_1_MINS, GIB_1_MAXS);
}
e.frame = 0;
};
//--------------------------------------------------------------
void() gib_misc_1 =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
gib_misc_1_init (self);
};
// };
#endif
#ifdef SSQC
/*QUAKED gib_misc_2 (0 0.5 0.8) (-8 -8 -8) (8 8 8) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/gib2.mdl");
}*/
//----------------------------------------------------------------------
// class gib_misc_2: base_gib
// {
//--------------------------------------------------------------
// 'self' in this context is the thing being gibbed -- CEV
//--------------------------------------------------------------
void(entity src, vector dir, float dmg) throw_gib_2 =
{
local entity e = spawn_gib_misc_2 (src, src.origin + '0 0 24',
velocity_for_damage(dir, dmg), GIB_DYNAMIC);
e.avelocity_x = random() * 600;
e.avelocity_y = random() * 600;
e.avelocity_z = random() * 600;
e.alpha = 1.0;
e.think = sub_remove_fade;
e.ltime = time;
e.nextthink = time + 10 + random() * 10;
};
//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float sflags)
spawn_gib_misc_2 =
{
return spawn_base_gib (src, org, vel, sflags, mdl_gib2,
gib_misc_2_init);
};
//--------------------------------------------------------------
void(entity e) gib_misc_2_init =
{
e.classname = "gib_misc_2";
e.classtype = CT_GORE_GIB2;
// this will set e.solid
base_gib_init (e);
if (e.mdl_gib2 != "")
{
precache_model (e.mdl_gib2);
setmodel (e, e.mdl_gib2);
}
else
{
precache_model ("progs/gib2.mdl");
setmodel (e, "progs/gib2.mdl");
if (e.solid == SOLID_BBOX || e.solid == SOLID_TRIGGER)
setsize (e, GIB_2_MINS, GIB_2_MAXS);
}
e.frame = 0;
};
//--------------------------------------------------------------
void() gib_misc_2 =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
gib_misc_2_init (self);
};
// };
#endif
#ifdef SSQC
/*QUAKED gib_misc_3 (0 0.5 0.8) (-8 -8 -8) (8 8 8) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/gib3.mdl");
}*/
//----------------------------------------------------------------------
// class gib_misc_3: base_gib
// {
//--------------------------------------------------------------
// 'self' in this context is the thing being gibbed -- CEV
//--------------------------------------------------------------
void(entity src, vector dir, float dmg) throw_gib_3 =
{
local entity e = spawn_gib_misc_3 (src, src.origin + '0 0 24',
velocity_for_damage(dir, dmg), GIB_DYNAMIC);
e.avelocity_x = random() * 600;
e.avelocity_y = random() * 600;
e.avelocity_z = random() * 600;
e.alpha = 1.0;
e.think = sub_remove_fade;
e.ltime = time;
e.nextthink = time + 10 + random() * 10;
};
//--------------------------------------------------------------
entity(entity src, vector org, vector vel, float sflags)
spawn_gib_misc_3 =
{
return spawn_base_gib (src, org, vel, sflags, mdl_gib3,
gib_misc_3_init);
};
//--------------------------------------------------------------
void(entity e) gib_misc_3_init =
{
e.classname = "gib_misc_3";
e.classtype = CT_GORE_GIB3;
// this will set e.solid
base_gib_init (e);
if (e.mdl_gib3 != "")
{
precache_model (e.mdl_gib3);
setmodel (e, e.mdl_gib3);
}
else
{
precache_model ("progs/gib3.mdl");
setmodel (e, "progs/gib3.mdl");
if (e.solid == SOLID_BBOX || e.solid == SOLID_TRIGGER)
setsize (e, GIB_3_MINS, GIB_3_MAXS);
}
e.frame = 0;
};
//--------------------------------------------------------------
void() gib_misc_3 =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
gib_misc_3_init (self);
};
// };
#endif
#ifdef SSQC
//----------------------------------------------------------------------
// class base_gib_head: base_gib
// {
//--------------------------------------------------------------
// ThrowHead
//--------------------------------------------------------------
void(entity e, vector dir, float dmg, void(entity e) initfn)
base_gib_head_throw =
{
e.skin = e.skin_head;
e.nextthink = -1;
e.spawnflags = GIB_DYNAMIC;
e.view_ofs = '0 0 8';
e.origin_z = e.origin_z - 24;
e.avelocity = crandom() * '0 600 0';
e.velocity = velocity_for_damage (dir, dmg);
if (initfn)
initfn (e);
};
//--------------------------------------------------------------
void(entity e) base_gib_head_init =
{
base_gib_init (e);
};
//--------------------------------------------------------------
strip void() base_gib_head =
{
base_gib_head_init (self);
};
// };
#endif
Return to the top of this page or return to the overview of this repo.
Log base_gore.qc
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2024-06-15 | Major update, committing as-is, will have bugs | cev | +141 | -62 |
2024-04-12 | Moveable gibs, heads, some bugfixes | cev | +505 |
Return to the top of this page or return to the overview of this repo.