cod4-sdk/raw/maps/_pipes.gsc
2008-01-19 00:00:00 +00:00

600 lines
No EOL
17 KiB
Text

#include common_scripts\utility;
#include maps\_utility;
main()
{
waittillframeend; // insure that structs are initialized
pipes = getentarray("pipe_shootable","targetname");
if(!pipes.size)
return;
level.num_pipe_fx = 0;
level.limit_pipe_fx = 32;
pipes thread precacheFX();
pipes thread methodsInit();
array_thread(pipes, ::pipesetup);
pipearray = pipes;
pipebreak = getentarray("pipe_break","targetname");
if(pipebreak.size)
{
pipebreak pipebreakInit(pipearray);
pipemasterInit(pipebreak);
array_thread(pipebreak, ::pipebreakthink);
}
}
methodsInit()
{
level._pipe_methods = [];
level._pipe_methods["MOD_UNKNOWN"] = ::pipe_calc_splash;
level._pipe_methods["MOD_PISTOL_BULLET"] = ::pipe_calc_ballistic;
level._pipe_methods["MOD_RIFLE_BULLET"] = ::pipe_calc_ballistic;
level._pipe_methods["MOD_GRENADE"] = ::pipe_calc_splash;
level._pipe_methods["MOD_GRENADE_SPLASH"] = ::pipe_calc_splash;
level._pipe_methods["MOD_PROJECTILE"] = ::pipe_calc_splash;
level._pipe_methods["MOD_PROJECTILE_SPLASH"] = ::pipe_calc_splash;
level._pipe_methods["MOD_MELEE"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_HEAD_SHOT"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_CRUSH"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_TELEFRAG"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_FALLING"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_SUICIDE"] = ::pipe_calc_nofx;
level._pipe_methods["MOD_TRIGGER_HURT"] = ::pipe_calc_splash;
level._pipe_methods["MOD_EXPLOSIVE"] = ::pipe_calc_splash;
level._pipe_methods["MOD_IMPACT"] = ::pipe_calc_nofx;
}
pipe_calc_ballistic(P, type)
{
return P;
}
pipe_calc_splash(P, type)
{
vec = vectornormalize( vectorFromLineToPoint(self.A, self.B, P) );
P = pointOnSegmentNearestToPoint(self.A, self.B, P);
return ( P + vector_multiply(vec, 4) );
}
pipe_calc_nofx(P, type)
{
return undefined;
}
pipe_calc_assert(P, type)
{
assertMsg("BUG to MOHAMMAD ALAVI under LEVEL DESIGN. Pipe at (" + self getorigin() + ") was impacted with unknown type: " + type + ".");
}
pipemasterInit(breaks)
{
level.pipe_breaks = breaks;
while(level.pipe_breaks.size)
{
sample = level.pipe_breaks[level.pipe_breaks.size-1];
master = spawnstruct();
master.name = "pipe master at (" + sample.origin + ") position";
sample.master = master;
level.pipe_breaks = array_remove(level.pipe_breaks, sample);
master pipemasterIterate(sample);
}
}
pipemasterIterate(sample)
{
family = get_pipes_in_range(sample, level.pipe_breaks);
//if we didn't find anything then head back
if(!isdefined(family) || family.size == 0)
return;
//if we found more - give them the current master and remove them from the list
for(i=0; i<family.size; i++)
{
family[i].master = self;
level.pipe_breaks = array_remove(level.pipe_breaks, family[i]);
}
//since we found new ones - we must see if there are more in the list that are near these
for(i=0; i<family.size; i++)
self pipemasterIterate(family[i]);
}
get_pipes_in_range(sample, pipes)
{
testdist = 34;
if (pipes.size < 1)
return;
ents = [];
foundit = false;
for (i=0;i<pipes.size;i++)
{
foundit = false;
for(e = 0; e < pipes[i].ends.size; e++)
{
for(j = 0; j < sample.ends.size; j++)
{
dist = distance(pipes[i].ends[e], sample.ends[j]);
if(dist > testdist)
continue;
foundit = true;
ents[ents.size] = pipes[i];
break;
}
if(foundit)
break;
}
}
return ents;
}
pipebreakInit(pipes)
{
for(j=0; j<self.size; j++)
{
self[j].whole = getClosest(self[j] getorigin(), pipes);
pipes = array_remove(pipes, self[j].whole);
self[j].fxnode = spawnstruct();
self[j].fxnode.origin = self[j].origin;
self[j].fxnode.forward = vector_multiply(anglestoright(self[j].angles), -1);
self[j].fxnode.up = anglestoforward(self[j].angles);
/****************************************************************/
/* THIS IS A HACK UNTIL I GET A MODEL FOR THIS THING */
/****************************************************************/
if(self[j].script_noteworthy == "fueltanker")
{
node = getstruct(self[j].whole.target, "targetname");
self[j].fxnode.origin = node.origin;
self[j].fxnode.forward = anglestoup(node.angles);
self[j].fxnode.up = anglestoforward(node.angles);
self[j].fxnode.right = anglestoright(node.angles);
}
/****************************************************************/
/* THIS IS A HACK UNTIL I GET A MODEL FOR THIS THING */
/****************************************************************/
self[j].hurtnode = [];
switch(self[j].script_noteworthy)
{
case "fire64":{
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin;
}break;
case "fire96":{
vec1 = vector_multiply(self[j].fxnode.up, 16);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
vec1 = vector_multiply(self[j].fxnode.up, -16);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
}break;
case "fire128":{
vec1 = vector_multiply(self[j].fxnode.up, 32);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
vec1 = vector_multiply(self[j].fxnode.up, -32);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
}break;
case "fire256":{
self[j].fx_multinode = [];
newnode = spawnstruct();
vec1 = vector_multiply(self[j].fxnode.up, 64);
newnode.origin = self[j].fxnode.origin + vec1;
newnode.forward = self[j].fxnode.forward;
newnode.up = self[j].fxnode.up;
self[j].fx_multinode[self[j].fx_multinode.size] = newnode;
newnode = spawnstruct();
vec1 = vector_multiply(self[j].fxnode.up, -64);
newnode.origin = self[j].fxnode.origin + vec1;
newnode.forward = self[j].fxnode.forward;
newnode.up = self[j].fxnode.up;
self[j].fx_multinode[self[j].fx_multinode.size] = newnode;
vec1 = vector_multiply(self[j].fxnode.up, 64);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
vec1 = vector_multiply(self[j].fxnode.up, -64);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
}break;
case "fueltanker":{
self[j].fx_multinode = [];
self[j].fx_multinode[self[j].fx_multinode.size] = self[j].fxnode;
/****************************************************************/
/* THIS IS A HACK UNTIL I GET A PROPER EFFECT */
/****************************************************************/
newnode2 = spawnstruct();
newnode2.origin = self[j].fxnode.origin;
newnode2.up = self[j].fxnode.up;
newnode2.forward = self[j].fxnode.forward + vector_multiply(self[j].fxnode.right, 1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
newnode2 = spawnstruct();
newnode2.origin = self[j].fxnode.origin;
newnode2.up = self[j].fxnode.up;
newnode2.forward = self[j].fxnode.forward + vector_multiply(self[j].fxnode.right, -1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
newnode = spawnstruct();
vec1 = vector_multiply(self[j].fxnode.up, 112);
newnode.origin = self[j].fxnode.origin + vec1;
newnode.forward = self[j].fxnode.forward;
newnode.up = self[j].fxnode.up;
self[j].fx_multinode[self[j].fx_multinode.size] = newnode;
newnode2 = spawnstruct();
newnode2.origin = newnode.origin;
newnode2.up = newnode.up;
newnode2.forward = newnode.forward + vector_multiply(self[j].fxnode.right, 1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
newnode2 = spawnstruct();
newnode2.origin = newnode.origin;
newnode2.up = newnode.up;
newnode2.forward = newnode.forward + vector_multiply(self[j].fxnode.right, -1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
newnode = spawnstruct();
vec1 = vector_multiply(self[j].fxnode.up, -112);
newnode.origin = self[j].fxnode.origin + vec1;
newnode.forward = self[j].fxnode.forward;
newnode.up = self[j].fxnode.up;
self[j].fx_multinode[self[j].fx_multinode.size] = newnode;
newnode2 = spawnstruct();
newnode2.origin = newnode.origin;
newnode2.up = newnode.up;
newnode2.forward = newnode.forward + vector_multiply(self[j].fxnode.right, 1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
newnode2 = spawnstruct();
newnode2.origin = newnode.origin;
newnode2.up = newnode.up;
newnode2.forward = newnode.forward + vector_multiply(self[j].fxnode.right, -1);
self[j].fx_multinode[self[j].fx_multinode.size] = newnode2;
/****************************************************************/
/* THIS IS A HACK UNTIL I GET A PROPER EFFECT */
/****************************************************************/
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin;
vec1 = vector_multiply(self[j].fxnode.up, 184);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
vec1 = vector_multiply(self[j].fxnode.up, -184);
self[j].hurtnode[self[j].hurtnode.size] = self[j].fxnode.origin + vec1;
}break;
}
//find the ends of the pipe so we can calculate in a later function what other pipes are attached to this one
//we'll include the center of the pipe as well for the calculations
self[j].ends = [];
displacement = 0;
switch(self[j].script_noteworthy)
{
case "fire64":{
displacement = 32;
}break;
case "fire96":{
displacement = 48;
}break;
case "fire128":{
displacement = 64;
}break;
case "fire256":{
displacement = 128;
}break;
case "fueltanker":{
displacement = 184;
}break;
}
self[j].ends[self[j].ends.size] = self[j].fxnode.origin;
vec1 = vector_multiply(self[j].fxnode.up, displacement);
self[j].ends[self[j].ends.size] = self[j].fxnode.origin + vec1;
vec1 = vector_multiply(self[j].fxnode.up, (displacement * -1));
self[j].ends[self[j].ends.size] = self[j].fxnode.origin + vec1;
}
}
pipebreak_damage()
{
minDamage = 1;
maxDamage = 250;
blastRadius = 200;
if(self.script_noteworthy == "fueltanker")
blastRadius = 350;
for(i=0; i<self.hurtnode.size; i++)
radiusDamage(self.hurtnode[i], blastRadius, maxDamage, minDamage);
}
pipebreakthink()
{
self hide();
self notsolid();
self thread pipebreakthink2();
self thread pipebreakthink3();
self thread pipebreakthink4();
self.whole endon("pipe_breaking");
while(1)
{
self.whole waittill("pipe_ruptured");
badplace_cylinder("",2, self.whole.origin, 250, 250);
self.master notify("pipe_ruptured");
self thread pipebreakthink2();
}
}
pipebreakthink2()
{
self.whole endon("pipe_ruptured");
self.whole endon("deleting");
self.master waittill("pipe_ruptured");
self.whole.numfx++;
self thread pipebreakthink2();
}
pipebreakthink3()
{
self.whole endon("pipe_breaking");
self.master waittill("hurtme");
wait randomfloat(.2);
self.whole notify("pipe_breaking");
}
pipebreakthink4()
{
self.whole waittill("pipe_breaking");
self.master notify("hurtme");
switch(self.script_noteworthy)
{
case "fueltanker":{
thread play_sound_in_space("explo_rock", self.fxnode.origin);
}break;
default:{
if(isdefined(self.master.firstsnd))
thread play_sound_in_space("expl_gas_pipe_burst", self.fxnode.origin);
else
{
self.master.firstsnd = true;
thread play_sound_in_space("expl_gas_pipe_burst_decay", self.fxnode.origin);
}
}break;
}
//DO DAMAGE
self thread pipebreak_damage();
self.A = self.whole.A;
self.B = self.whole.B;
self setcandamage(true);
self.whole notify("deleting");
self.whole delete();
self show();
self solid();
if(isdefined(self.fx_multinode))
{
for(i=0; i<self.fx_multinode.size; i++)
playfx( level._effect["pipe_interactive"][self.script_noteworthy], self.fx_multinode[i].origin, self.fx_multinode[i].forward, self.fx_multinode[i].up);
}
else
playfx( level._effect["pipe_interactive"][self.script_noteworthy], self.fxnode.origin, self.fxnode.forward, self.fxnode.up);
if(self.script_noteworthy == "fueltanker")
earthquake(0.4, 1.5, self.fxnode.origin, 600);
self thread pipeimpact();
}
pipesetup()
{
self setcandamage(true);
node = undefined;
if(isdefined(self.target))
{
node = getstruct(self.target, "targetname");
self.A = node.origin;
vec = anglesToForward (node.angles);
vec = vector_multiply(vec, 128);
self.B = self.A+vec;
}
else
{
vec = anglestoforward(self.angles);
vec1 = vector_multiply(vec, 64);
self.A = self.origin + vec1;
vec1 = vector_multiply(vec, -64);
self.B = self.origin + vec1;
}
if( self.script_noteworthy == "fire")
self.limit = 4;
self thread pipethink();
}
pipethink()
{
P = (0,0,0);//just to initialize P as a vector
self.numfx = 0;
self endon("deleting");
//FIRE
if(isdefined(self.limit))
{
while(1)
{
self waittill("damage", other, damage, direction_vec, P, type );
if(type == "MOD_MELEE" || type == "MOD_IMPACT")
continue;
self pipethink_logic(self.numfx, self.limit, direction_vec, P, type);
self.numfx++;
}
}
//EVERYTHING ELSE
else
{
while(1)
{
self waittill("damage", other, damage, direction_vec, P, type );
if(type == "MOD_MELEE" || type == "MOD_IMPACT")
continue;
self pipethink_logic(level.num_pipe_fx, level.limit_pipe_fx, direction_vec, P, type);
level.num_pipe_fx++;
self thread pipethink2();
}
}
}
pipethink_logic(num, limit, direction_vec, P, type)
{
if(num < limit )
{
P = self [[ level._pipe_methods[type] ]](P, type);
if( !isdefined( P ) )
return;
//calculate the vector derived from the center line of our pipe and the point of damage
vec = vectorFromLineToPoint(self.A, self.B, P);
self thread pipefx(P, vec);
self notify("pipe_ruptured");
}
else
self notify("pipe_breaking");
}
pipethink2()
{
//self endon("deleting");
wait level.pipe_fx_time[self.script_noteworthy];
level.num_pipe_fx--;
}
pipefx(P, vec)
{
if(self.script_noteworthy != "fire")
{
playfx ( level._effect["pipe_interactive"][self.script_noteworthy], P, vec);
thread play_sound_in_space(level._sound["pipe_interactive"][self.script_noteworthy], P);
return;
}
self endon("pipe_breaking");
time = .1;
if(!isdefined(self.burnsec))
{
self.burnsec = int(2 / time); //2 secs / time = num of times to loop
self.burninterval = int(self.burnsec * .15);
}
else
self.burnsec -= self.burninterval;
thread play_sound_in_space("mtl_gas_pipe_hit", P);
self thread pipesndloopfx("mtl_gas_pipe_flame_loop", P, "pipe_breaking");
if(vec == (0,0,0))
vec = (0,360,0);
for(i=0; i<self.burnsec; i++)
{
playfx ( level._effect["pipe_interactive"][self.script_noteworthy], P, vec);
wait time;
}
self notify("pipe_breaking");
}
pipeimpact()
{
P = (0,0,0);//just to initialize P as a vector
self endon("deleting");
while(1)
{
self waittill("damage", other, damage, direction_vec, P , type);
if(type == "MOD_MELEE" || type == "MOD_IMPACT")
continue;
P = self [[ level._pipe_methods[type] ]](P, type);
//play the metal hit fx
direction_vec = vector_multiply(direction_vec, -1);
playfx( level._effect["pipe_interactive"]["impact"], P, direction_vec);
}
}
pipesndloopfx(snd, P, msg, time)
{
self endon(msg);
if(isdefined(time))
wait time;
while(1)
{
play_sound_in_space(snd, P);
}
}
precacheFX()
{
for(i=0; i< self.size; i++)
{
if(self[i].script_noteworthy != "steam")
continue;
level._effect["pipe_interactive"][self[i].script_noteworthy] = loadfx("impacts/pipe_steam");
level._sound["pipe_interactive"][self[i].script_noteworthy] = "mtl_steam_pipe_hit";
level.pipe_fx_time[self[i].script_noteworthy] = 5;
break;
}
for(i=0; i< self.size; i++)
{
if(self[i].script_noteworthy != "water")
continue;
level._effect["pipe_interactive"][self[i].script_noteworthy] = loadfx("impacts/pipe_water");
level._sound["pipe_interactive"][self[i].script_noteworthy] = "mtl_water_pipe_hit";
level.pipe_fx_time[self[i].script_noteworthy] = 2.6;
break;
}
for(i=0; i< self.size; i++)
{
if(self[i].script_noteworthy != "fire")
continue;
level._effect["pipe_interactive"][self[i].script_noteworthy ] = loadfx("impacts/pipe_fire");
level._effect["pipe_interactive"]["fire64"] = loadfx("explosions/pipe_explosion64");
level._effect["pipe_interactive"]["fire96"] = loadfx("explosions/pipe_explosion64");
level._effect["pipe_interactive"]["fire128"] = loadfx("explosions/pipe_explosion128");
level._effect["pipe_interactive"]["fire256"] = loadfx("explosions/pipe_explosion128");
level._effect["pipe_interactive"]["fueltanker"] = loadfx("explosions/pipe_explosion128");
break;
}
level._effect["pipe_interactive"]["impact"] = loadfx("impacts/small_metalhit_1");
}