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
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2024-06-15 | Major update, committing as-is, will have bugs | cev | +16 | -2 |
2024-04-12 | Moveable gibs, heads, some bugfixes | cev | +24 | -23 |
2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +214 | -193 |
2024-02-27 | Bullet projectile, pmove changes, misc | cev | +3 | -3 |
2024-02-18 | Client/player, projectiles, entrypoints refactor | cev | +9 | -7 |
2024-01-31 | Class based monster refactor & start projectiles | cev | +8 | -4 |
2024-01-13 | Refactored items into classes, fix teleporttrain | cev | +1 | -1 |
2024-01-09 | Continue OO / Class-based refactor | cev | +374 | -431 |
2023-12-09 | Start OO / class-based refactor, work on items | cev | -3 | |
2023-11-27 | Code reorg, minor movement changes, misc | cev | +581 |
Return to the top of this page or return to the overview of this repo.