djcev.com

//

Git Repos / fte_dogmode / qc / func / breakable.qc

Last update to this file was on 2024-06-15 at 19:50.

Show breakable.qc

//==============================================================================
// func_breakable -- AD breakable code modified by Qmaster, iw, and dumptruck_ds
//==============================================================================

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

#ifdef SSQC
const float BREAKABLE_NO_MONSTERS = 1;
const float BREAK_EXPLODE = 2;
const float BREAK_CUSTOM = 4;

const float BREAKABLE_NO_MONSTERS = 1;
#endif

//======================================================================
// fields
//======================================================================

#ifdef SSQC
.float brk_obj_count1;
.float brk_obj_count2;
.float brk_obj_count3;
.float brk_obj_count4;
.float brk_obj_count5;

.string break_template1;
.string break_template2;
.string break_template3;
.string break_template4;
.string break_template5;

.string mdl_debris; // dumptruck_ds
#endif

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

// base_breakable
#ifdef SSQC
void() sub_dislodge_resting_entities;
void(vector dir, string templatename) base_breakable_template_single_debris;
void(vector dir) base_breakable_single_debris;
void(vector dir) base_breakable_make_templates_debris;
void(vector dir) base_breakable_make_debris;
void(vector dir) base_breakable_die;
void(vector dir) base_breakable_destroy;
void() base_breakable_use;
void(entity e) base_breakable_template_setup;
void(entity e) base_breakable_init;
void() base_breakable;
#endif

// func_breakable
#ifdef SSQC
void(entity e) func_breakable_init;
void() func_breakable;
#endif

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

//----------------------------------------------------------------------
// base breakable class; used by func_breakable (below), func_fall2
//----------------------------------------------------------------------
// class base_breakable: base_func
// {
#ifdef SSQC
//--------------------------------------------------------------
// SUB_DislodgeRestingEntities
// This clears the FL_ONGROUND flag from any entities that are on
// top of self. The engine does not update the FL_ONGROUND flag
// automatically in some cases, with the result that certain types
// of entities can be left floating in mid-air if the entity they
// are resting on is removed from under them. This function is
// intended to be called in the case where self is going to be
// removed, to ensure that other entities are not left floating. -- iw
//--------------------------------------------------------------
void() sub_dislodge_resting_entities =
{
local entity e;

e = nextent (world);
while (e && e != world)
{
if ((e.flags & FL_ONGROUND) && e.groundentity == self)
e.flags = e.flags - (e.flags & FL_ONGROUND);
e = nextent (e);
}
};

//--------------------------------------------------------------
void(vector dir, string templatename)
base_breakable_template_single_debris =
{
local entity new;

new = spawn ();
new.model = templatename;
new.origin_x = (self.maxs_x - self.mins_x) *
random() + self.mins_x;
new.origin_y = (self.maxs_y - self.mins_y) *
random() + self.mins_y;
new.origin_z = (self.maxs_z - self.mins_z) *
random() + self.mins_z;
// dumptruck_ds
setmodel (new, new.model);
setsize (new, '0 0 0', '0 0 0');
new.movetype = MOVETYPE_BOUNCE;
new.solid = SOLID_NOT;
new.avelocity_x = random() * 600;
new.avelocity_y = random() * 600;
new.avelocity_z = random() * 600;
new.velocity = velocity_for_damage (dir, self.health * 2);
new.think = sub_remove;
new.ltime = time;
new.nextthink = time + 10 + random() * 10;
new.flags = 0;
};

//--------------------------------------------------------------
void(vector dir) base_breakable_single_debris =
{
local entity new;

new = spawn ();
new.origin_x = (self.maxs_x - self.mins_x) *
random() + self.mins_x;
new.origin_y = (self.maxs_y - self.mins_y) *
random() + self.mins_y;
new.origin_z = (self.maxs_z - self.mins_z) *
random() + self.mins_z;

// this was originally just an mdl from Rubicon2, now you set
// custom model via spawnflag or use the builtin from
// Rubicon2 -- dumptruck_ds
// setmodel (new, "progs/debris.mdl");

// dumptruck_ds
setmodel (new, self.mdl_debris);
setsize (new, '0 0 0', '0 0 0');
new.velocity = velocity_for_damage (dir, self.health * 2);
new.movetype = MOVETYPE_BOUNCE;
new.solid = SOLID_NOT;
new.avelocity_x = random() * 600;
new.avelocity_y = random() * 600;
new.avelocity_z = random() * 600;
new.think = sub_remove;
new.ltime = time;
new.nextthink = time + 10 + random() * 10;
new.flags = 0;

// randomly choose size
if (random() > 0.333)
// larger
new.frame = 1;
else
// smaller
new.frame = 2;

// choose skin based on "style" key
//
// this was originally a large block of individual if
// statements in the form of:
// if (self.style == 1)
// new.skin = 1;
// if (self.style == 2)
// new.skin = 2;
// and so on, up until 31. As far as I can tell new.skin
// was always set to the same value as self.style. So I've
// simplified the block into the code below.
// New debris skins start at 3 and continue through 31
// according to comments left by dumptruck_ds -- CEV

if (self.style > 0 && self.style <= 31)
{
new.skin = self.style;
}
};

//--------------------------------------------------------------
// template system from Qmaster -- dumptruck_ds
//--------------------------------------------------------------
void(vector dir) base_breakable_make_templates_debris =
{
local float count = 0;
local string break_template = "";

for (float i = 1; i < 6; i++)
{
switch (i)
{
case 1:
break_template = self.break_template1;
count = self.brk_obj_count1;
break;
case 2:
break_template = self.break_template2;
count = self.brk_obj_count2;
break;
case 3:
break_template = self.break_template3;
count = self.brk_obj_count3;
break;
case 4:
break_template = self.break_template4;
count = self.brk_obj_count4;
break;
case 5:
break_template = self.break_template5;
count = self.brk_obj_count5;
break;
}

if (break_template != __NULL__ && break_template != "")
{
for (float j = 0; j < count; j++)
{
base_breakable_template_single_debris
(dir, break_template);
}
}

break_template = "";
count = 0;
}
};

//==============================================================
// Below this is from Rubicon2 -- dumptruck_ds
//==============================================================

//--------------------------------------------------------------
void(vector dir) base_breakable_make_debris =
{
for (float i = 0; i < self.cnt; i++)
base_breakable_single_debris (dir);
};

//--------------------------------------------------------------
// dumptruck_ds -- set the spawnflag for cosmetic explosion
// effect; use "dmg" value to hurt the player
//--------------------------------------------------------------
void(vector dir) base_breakable_die =
{
// what is this brace doing here? -- TODO CEV
{
// thanks to Qmaster!!! He helped me sort out
// noise1 playing from 0 0 0 with this temp
// entity - dumptruck_ds
local entity ent;

ent = spawn ();
ent.origin = ((self.absmin + self.absmax) * 0.5);
setsize (ent, '0 0 0', '0 0 0');
ent.solid = SOLID_NOT;
ent.think = sub_remove;
// ent.ltime = time;
ent.nextthink = time + 60;

sound (ent, CHAN_AUTO, self.noise1,
VOL_HIGH, ATTN_NORM);
// remove (self);
}

// this is to ensure that any debris from another
// func_breakable which is resting on top of this
// func_breakable is not left floating in mid-air
// after this entity is removed -- iw
sub_dislodge_resting_entities ();

if (self.spawnflags & BREAK_EXPLODE)
{
if (self.spawnflags & BREAK_CUSTOM)
base_breakable_make_templates_debris (dir);
else
base_breakable_make_debris (dir);

// to let us use noise2
// func_explobox_explode_silent ();
self.takedamage = DAMAGE_NO;
self.origin = ((self.absmin + self.absmax) * 0.5);
t_radiusdamage2 (self, self, self.dmg, world);
write_explosion (self.origin);
spawn_base_explosion (self.origin);

// this is broken as of 1.1.0 no custom explosion
// sound for now -- dumptruck_ds
// sound (self, CHAN_VOICE, self.noise2,
// VOL_HIGH, ATTN_NORM);
remove (self);
}
else
{
self.origin = ((self.absmin + self.absmax) * 0.5);
setorigin (self, self.origin);
if (self.drop_item)
base_item_drop_stuff (self);
if (self.spawnflags & BREAK_CUSTOM)
{
if (self.switchshadstyle)
lightstyle (self.switchshadstyle, "m");
base_breakable_make_templates_debris (dir);
if (self)
remove (self);
}
else
{
if (self.switchshadstyle)
lightstyle (self.switchshadstyle, "m");
base_breakable_make_debris (dir);
if (self)
remove (self);
}
}
};

//--------------------------------------------------------------
void(vector dir) base_breakable_destroy =
{
activator = damage_attacker;
sub_usetargets ();
base_breakable_die (dir);
};

//--------------------------------------------------------------
void() base_breakable_use =
{
if (self.targetname == __NULL__ || self.targetname == "")
return;

activator = other;
sub_usetargets ();
base_breakable_die ('0 0 0');
};

//--------------------------------------------------------------
void(entity e) base_breakable_template_setup =
{
if (e.break_template1 != "")
precache_model (e.break_template1);
if (e.break_template2 != "")
precache_model (e.break_template2);
if (e.break_template3 != "")
precache_model (e.break_template3);
if (e.break_template4 != "")
precache_model (e.break_template4);
if (e.break_template5 != "")
precache_model (e.break_template5);
};

//--------------------------------------------------------------
void(entity e) base_breakable_init =
{
base_func_init (e);
base_breakable_template_setup (e);
};

//--------------------------------------------------------------
strip void() base_breakable =
{
base_breakable_init (self);
};
#endif
// };

/*QUAKED func_breakable (0 .5 .8) ? NO_MONSTERS 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

"Breakable - See manual for full details

Defaults to built-in .mdl file with 32 styles, cnt is number of pieces of debris to spawn (built-in only)
Or use spawnflag 4 and break_template1-4 to set path of custom .mdl or .bsp models.
brk_object_count1-4 sets the number of pieces of each break_template when using custom .mdl or bsp models.
If noise1 is not set it will default to various sounds in sounds/break folder
Use spawnflag 2 for an explosion, dmg is amount of damage inflicted"

spawnflags(flags)
1 : "No Monster Damage" : 0 : "Only the player can break"
2 : "Explosion" : 0 : "Produces explosion effect and sound"
4 : "Use custom mdls or bsp models" : 0 : "Uses models specified in break_template1, 2, etc"

style(choices) : "Built-in debris style" : 0
0 : "Green Metal (default)"
1 : "Red Metal"
2 : "Concrete"
3 : "Pine wood"
4 : "Brown wood"
5 : "Red wood"
6 : "Stained Glass Yellow Flames"
7 : "Stained Glass Red Rays"
8 : "Stained Glass Yellow Dragon"
9 : "Stained Glass Blue Dragon"
10 : "Stained Glass Red Dragon"
11 : "Light Copper"
12 : "Dark Copper"
13 : "Tan Bricks Large"
14 : "Brown Bricks Large"
15 : "Green Bricks Large"
16 : "Generic Light Brown"
17 : "Red Brown Computer"
18 : "Grey Black Computer"
19 : "Blue Green Metal"
20 : "Blue Green Runic Wall"
21 : "Brown Metal"
22 : "Dark Brown Metal"
23 : "Medium Brown Metal"
24 : "Blue Metal"
25 : "Green Stonework"
26 : "Blue Stonework"
27 : "Brown Bricks"
28 : "Tan Blue Bricks"
29 : "Red Bricks"
30 : "Blue Bricks"
31 : "Metal Rivets"

noise1(string) : "Break noise (overrides default sounds)"
cnt(integer) : "Number of pieces of debris to spawn" : 5
health(integer) : "Health of breakable" : 20
dmg(integer) : "Amount of Explosive Damage" : 20
break_template1(string) : "Template 1 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
break_template2(string) : "Template 2 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
break_template3(string) : "Template 3 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
break_template4(string) : "Template 4 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
break_template5(string) : "Template 5 model path, e.g. maps/break/brk.bsp or progs/brick.mdl"
brk_obj_count1(integer) : "Template 1 spawn count"
brk_obj_count2(integer) : "Template 2 spawn count"
brk_obj_count3(integer) : "Template 3 spawn count"
brk_obj_count4(integer) : "Template 4 spawn count"
brk_obj_count5(integer) : "Template 5 spawn count"
*/
//----------------------------------------------------------------------
// class func_breakable: base_breakable
// {
#ifdef SSQC
//--------------------------------------------------------------
void(entity e) func_breakable_init =
{
e.classname = "func_breakable";
e.classtype = CT_FUNC_BREAKABLE;

base_breakable_init (e);

e.solid = SOLID_BSP;
e.movetype = MOVETYPE_PUSH;
setmodel (e, e.model);
e.mdl_debris = "progs/debris.mdl";
precache_model (e.mdl_debris);
precache_sound ("blob/hit1.wav");

if (e.noise1 != "")
precache_sound (e.noise1);

// adding new default sounds for "simple" breakables in 1.2.0
// -- dumptruck_ds

// here's genreic metal breaking
if (e.style == 0 || e.style == 11 ||
e.style == 12 || e.style == 17 ||
e.style == 18 || e.style == 19 ||
e.style == 24 || e.style == 31)
{
if !(e.noise1)
{
precache_sound ("break/metal2.wav");
e.noise1 = "break/metal2.wav";
}
}

if (e.style == 3 || e.style == 4 || e.style == 5)
{
if !(e.noise1)
{
precache_sound ("break/wood1.wav");
precache_sound ("break/wood2.wav");
// wood only randomized
if (random() > 0.6)
e.noise1 = "break/wood1.wav";
else
e.noise1 = "break/wood2.wav";
}
}

// glass sounds -- this is more of a shattering sound anyway
if (e.style == 6 || e.style == 7 || e.style == 8 ||
e.style == 9 || e.style == 10)
{
if !(e.noise1)
{
precache_sound ("break/metal1.wav");
e.noise1 = "break/metal1.wav";
}
}

if (e.style == 1 || e.style == 2 ||
e.style == 13 || e.style == 14 ||
e.style == 15 || e.style == 16 ||
e.style == 20 || e.style == 21 ||
e.style == 22 || e.style == 23)
{
if !(e.noise1)
{
precache_sound ("break/stones1.wav");
precache_sound ("break/bricks1.wav");
// wood only randomized
if (random() > 0.6)
e.noise1 = "break/bricks1.wav";
else
e.noise1 = "break/stones1.wav";
}
}

if (e.style == 25 || e.style == 26 ||
e.style == 27 || e.style == 28 ||
e.style == 29 || e.style == 30)
{
if !(e.noise1)
{
precache_sound ("break/stones1.wav");
precache_sound ("break/bricks1.wav");
// wood only randomized
if (random() > 0.6)
e.noise1 = "break/stones1.wav";
else
e.noise1 = "break/bricks1.wav";
}
// else
// {
// (e.noise1 = "blob/hit1.wav");
// }
}

if (!e.health)
e.health = 20;
if (!e.cnt)
// was 6 dumptruck_ds
e.cnt = 5;

if (e.targetname != "" && e.targetname != __NULL__)
{
e.use = base_breakable_use;
}
else
{
e.takedamage = DAMAGE_YES;
e.destroy = base_breakable_destroy;
}

if (e.switchshadstyle)
lightstyle (e.switchshadstyle, "a");
};

//--------------------------------------------------------------
void() func_breakable =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

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

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

Log breakable.qc

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