632 lines
15 KiB
C++
632 lines
15 KiB
C++
/*
|
|
=============================
|
|
ewmisc.qc
|
|
coded by
|
|
Michael Rogers a.k.a Xsniper
|
|
ssj_xsniper@yahoo.com
|
|
xsniper.virtualave.net
|
|
|
|
Description:
|
|
This file holds miscellaneous EW things.
|
|
Such as Fire Columns which are a new
|
|
object that can be placed into levels.
|
|
=============================
|
|
*/
|
|
|
|
void() fire_column_remove;
|
|
void() BecomeExplosion;
|
|
float(float hamount) set_health;
|
|
|
|
//====================================================================================================
|
|
//Statue Code Below
|
|
|
|
/*
|
|
====================
|
|
misc_statue
|
|
|
|
This is a statue that just sits in the level, its eyecandy only.
|
|
|
|
Spawnflags
|
|
1 : skin 1
|
|
2 : skin 2
|
|
4 : skin 3
|
|
====================
|
|
*/
|
|
void() misc_statue =
|
|
{
|
|
local entity statue;
|
|
|
|
// start entity and place it in world
|
|
statue = spawn();
|
|
setorigin (statue, self.origin);
|
|
|
|
// set size and shape
|
|
statue.solid = SOLID_SLIDEBOX;
|
|
precache_model ("models/map/statue.md2");
|
|
setmodel (statue, "models/map/statue.md2");
|
|
setsize (statue, '-16 -16 -24', '16 16 40');
|
|
|
|
// set up angles
|
|
statue.angles = self.angles;
|
|
|
|
//set skin based on spawnflags
|
|
if (self.spawnflags & 1)
|
|
statue.skin = 0;
|
|
else if (self.spawnflags & 2)
|
|
statue.skin = 1;
|
|
else if (self.spawnflags & 4)
|
|
statue.skin = 2;
|
|
};
|
|
|
|
//====================================================================================================
|
|
//Fire Column Code Below
|
|
|
|
/*
|
|
====================
|
|
fire_column_touch
|
|
|
|
If you touch the fire column then get burned!
|
|
====================
|
|
*/
|
|
void() fire_column_touch =
|
|
{
|
|
//don't burn our owner
|
|
if (self.owner == other)
|
|
return;
|
|
|
|
//don't burn boss monsters
|
|
if (other.classname == "monster_bossf1" || other.classname == "monster_bossf2")
|
|
return;
|
|
|
|
//don't let arrows stick in me
|
|
if (other.model == "models/ammo/v_bolt.md2")
|
|
{
|
|
remove(other);
|
|
return;
|
|
}
|
|
|
|
//burn that punk who touched me!
|
|
T_Damage(other,self,self.owner,1);
|
|
};
|
|
|
|
void() fire_column_return =
|
|
{
|
|
self.solid = SOLID_SLIDEBOX;
|
|
self.effects = self.effects + EF_DIMLIGHT;
|
|
setmodel (self, "progs/flame2.mdl");
|
|
setsize (self, '-16 -16 -24', '16 16 40');
|
|
self.nextthink = time + self.firern;
|
|
self.think = fire_column_remove;
|
|
self.touch = fire_column_touch;
|
|
};
|
|
|
|
void() fire_column_remove =
|
|
{
|
|
self.effects = self.effects - EF_DIMLIGHT;
|
|
self.solid = SOLID_NOT;
|
|
setmodel (self, "");
|
|
setsize (self, '-16 -16 -24', '16 16 40');
|
|
self.nextthink = time + self.firere;
|
|
self.think = fire_column_return;
|
|
self.touch = SUB_Null;
|
|
};
|
|
|
|
/*
|
|
====================
|
|
create_fire_column
|
|
|
|
Creates a fire column that remains for x seconds
|
|
|
|
vector spot: place to put the fire
|
|
float continue: controls whether fire comes up and goes down continuously
|
|
0: doesnt do this
|
|
1: it does
|
|
float x: amount of seconds for firecolumn to remain
|
|
float antix: used for continuous fire so they come back from ground up
|
|
====================
|
|
*/
|
|
void(vector spot, float continue, float x, float antix) create_fire_column =
|
|
{
|
|
local entity fire;
|
|
|
|
// start entity and place it in world
|
|
fire = spawn();
|
|
setorigin (fire, spot);
|
|
|
|
// set size and shape
|
|
fire.solid = SOLID_SLIDEBOX;
|
|
setmodel (fire, "progs/flame2.mdl");
|
|
setsize (fire, '-16 -16 -24', '16 16 40');
|
|
fire.frame = 1;
|
|
|
|
//initialize firere and firern
|
|
//firere = fireremove
|
|
//firern = firereturn
|
|
fire.firere = antix + 5;
|
|
fire.firern = x + 5;
|
|
|
|
// polish him up
|
|
fire.classname = "firecolumn";
|
|
fire.effects = fire.effects + EF_DIMLIGHT;
|
|
|
|
// begin his thinking
|
|
fire.nextthink = time + x;
|
|
|
|
// are we continuous or not?
|
|
if (continue == 1)
|
|
fire.think = fire_column_remove;
|
|
else
|
|
fire.think = SUB_Remove;
|
|
|
|
// if you touch him then get burned!
|
|
fire.touch = fire_column_touch;
|
|
|
|
// we need to know who owns us so we dont burn him
|
|
fire.owner = self;
|
|
};
|
|
|
|
/*
|
|
====================
|
|
misc_fire_column
|
|
|
|
This is an object that can be placed into the world and it will create
|
|
a fire column at its origin.
|
|
====================
|
|
*/
|
|
void() misc_fire_column =
|
|
{
|
|
local float firecount, anticount, firetime;
|
|
local vector start, plus;
|
|
|
|
//set the starting height
|
|
start = '0 0 -10';
|
|
|
|
//set the increment amount
|
|
plus = '0 0 25';
|
|
|
|
//initialize firecount and anticount
|
|
firecount = 7;
|
|
anticount = 0;
|
|
|
|
if (self.spawnflags & 1) //fire column stays up forever
|
|
{
|
|
firetime = 999;
|
|
while(firecount > 0)
|
|
{
|
|
create_fire_column((self.origin + start),0,firetime,anticount);
|
|
start = start + plus;
|
|
firecount = firecount - 1;
|
|
}
|
|
}
|
|
else if (self.spawnflags & 2) //fire column comes up for 15 seconds then goes back down and comes up again
|
|
{
|
|
while(firecount > 0)
|
|
{
|
|
create_fire_column((self.origin + start),1,firecount,anticount);
|
|
start = start + plus;
|
|
firecount = firecount - 1;
|
|
anticount = anticount + 1;
|
|
}
|
|
}
|
|
else //default settings, comes up and goes back down, never appears again
|
|
{
|
|
while(firecount > 0)
|
|
{
|
|
create_fire_column((self.origin + start),0,firecount,anticount);
|
|
start = start + plus;
|
|
firecount = firecount - 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
//====================================================================================================
|
|
//Explosion Code Below
|
|
|
|
/*
|
|
====================
|
|
explo_explode
|
|
|
|
Used by create_explosion, this does the blowing up and damaging of things nearby.
|
|
====================
|
|
*/
|
|
void() explo_explode =
|
|
{
|
|
T_RadiusDamage (self, self, self.dmg, self.owner);
|
|
|
|
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WriteByte (MSG_BROADCAST, TE_TAREXPLOSION);
|
|
WriteCoord (MSG_BROADCAST, self.origin_x);
|
|
WriteCoord (MSG_BROADCAST, self.origin_y);
|
|
WriteCoord (MSG_BROADCAST, self.origin_z);
|
|
|
|
BecomeExplosion ();
|
|
};
|
|
|
|
void() explo_nospr_explode =
|
|
{
|
|
T_RadiusDamage (self, self, self.dmg, self.owner);
|
|
|
|
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
|
WriteCoord (MSG_BROADCAST, self.origin_x);
|
|
WriteCoord (MSG_BROADCAST, self.origin_y);
|
|
WriteCoord (MSG_BROADCAST, self.origin_z);
|
|
|
|
//BecomeExplosion();
|
|
remove(self);
|
|
};
|
|
|
|
/*
|
|
==============================
|
|
big explosion animation frames
|
|
==============================
|
|
*/
|
|
|
|
void() big_explo1 =[ 0, big_explo2 ]
|
|
{
|
|
setmodel (self,"models/weapons/gfx/bossboom.mdl");
|
|
setsize (self, '-8 -8 -12', '8 8 20');
|
|
|
|
//make partially transparent
|
|
self.alpha = 0.3;
|
|
|
|
//make some noise
|
|
sound (self, CHAN_VOICE, "weapons/flaskexplode.wav", 1, ATTN_NORM);
|
|
};
|
|
void() big_explo2 =[ 1, big_explo3 ] {};
|
|
void() big_explo3 =[ 2, big_explo4 ] {};
|
|
void() big_explo4 =[ 3, big_explo5 ] {};
|
|
void() big_explo5 =[ 4, big_explo6 ] {};
|
|
void() big_explo6 =[ 5, big_explo7 ] {};
|
|
void() big_explo7 =[ 6, big_explo8 ] {};
|
|
void() big_explo8 =[ 7, big_explo9 ] {};
|
|
void() big_explo9 =[ 8, big_explo10 ] {};
|
|
void() big_explo10 =[ 9, big_explo11 ] {};
|
|
void() big_explo11 =[ 10, big_explo12 ] {};
|
|
void() big_explo12 =[ 11, big_explo13 ] {};
|
|
void() big_explo13 =[ 12, big_explo14 ] {};
|
|
void() big_explo14 =[ 13, big_explo14 ]
|
|
{
|
|
//time to really blow up
|
|
explo_explode();
|
|
};
|
|
|
|
|
|
/*
|
|
====================
|
|
create_explosion
|
|
|
|
Creates an explosion at the specified coordinate that happens in x seconds
|
|
|
|
vector spot: place to create the explosion
|
|
float x: amount of time in seconds to wait before the explosion occurs
|
|
float etype: type of explosion
|
|
0: particle explosion
|
|
1: big explosion
|
|
float damage: amount of damage to do
|
|
====================
|
|
*/
|
|
void(vector spot, float x, float etype, float damage) create_explosion =
|
|
{
|
|
local entity explo;
|
|
|
|
// start entity and place it in world
|
|
explo = spawn();
|
|
setorigin (explo, spot);
|
|
|
|
// set size and shape
|
|
explo.solid = SOLID_SLIDEBOX;
|
|
setmodel (explo, "");
|
|
setsize (explo, '-8 -8 -12', '8 8 20');
|
|
explo.nextthink = time + x;
|
|
|
|
// set our damage
|
|
explo.dmg = damage;
|
|
|
|
// do correct explosion type
|
|
if (etype == 0) //particle explosion with sprite
|
|
explo.think = explo_explode;
|
|
else if (etype == 1) //big explosion
|
|
explo.think = big_explo1;
|
|
else if (etype == 2) //particle explosion
|
|
explo.think = explo_nospr_explode;
|
|
else //incase they put something else in there
|
|
explo.think = explo_explode;
|
|
|
|
// few other things
|
|
explo.classname = "explosion";
|
|
explo.owner = self;
|
|
};
|
|
|
|
//====================================================================================================
|
|
//Black Hole Code Below
|
|
|
|
void () sp_holeremove =
|
|
{
|
|
//keep track of what time it is
|
|
bhtime = time;
|
|
|
|
sound (self, CHAN_VOICE, "weapons/lstart.wav", 1, ATTN_NORM);
|
|
|
|
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WriteByte (MSG_BROADCAST, TE_TELEPORT);
|
|
WriteCoord (MSG_BROADCAST, self.origin_x);
|
|
WriteCoord (MSG_BROADCAST, self.origin_y);
|
|
WriteCoord (MSG_BROADCAST, self.origin_z);
|
|
|
|
remove (self);
|
|
};
|
|
|
|
void () sp_holetouch =
|
|
{
|
|
local float bhdmg;
|
|
local vector org, dir;
|
|
|
|
if ( (other.takedamage == DAMAGE_YES) || (other.takedamage == DAMAGE_AIM) )
|
|
{
|
|
bhdmg = 1;
|
|
T_Damage (other, self, self, bhdmg);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
void () sp_holesuck =
|
|
{
|
|
local entity head;
|
|
local vector tohole;
|
|
local float disttohole, weakness;
|
|
|
|
//if bf2 is dead then its time to dissapear
|
|
if (bf2_dead == 1)
|
|
sp_holeremove();
|
|
|
|
head = findradius (self.origin, 1280);
|
|
|
|
while (head)
|
|
{
|
|
if ( (head.classname != "blackhole") && (head.classname != "plat") && (head.classname != "monster_bossf2") )
|
|
{
|
|
if ( (head.movetype != MOVETYPE_NONE) && (head.movetype != MOVETYPE_PUSH) )
|
|
{
|
|
disttohole = vlen(self.origin - head.origin);
|
|
if (disttohole > 80)
|
|
{
|
|
tohole = normalize(self.origin - head.origin);
|
|
tohole_x = tohole_x*375 + (40*random());
|
|
tohole_y = tohole_y*375 + (40*random());
|
|
if ( head.classname == "player" )
|
|
{
|
|
tohole_z = tohole_z*210;
|
|
}
|
|
else
|
|
{
|
|
tohole_z = tohole_z*320;
|
|
}
|
|
weakness = (1280 - disttohole) / 1280;
|
|
weakness = (weakness * weakness);
|
|
head.velocity = head.velocity + (tohole * weakness);
|
|
}
|
|
else
|
|
{
|
|
head.velocity = head.velocity * 0.9;
|
|
}
|
|
}
|
|
}
|
|
head = head.chain;
|
|
}
|
|
self.touch = sp_holetouch;
|
|
|
|
self.nextthink = time + 0.1;
|
|
self.think = sp_holesuck;
|
|
};
|
|
|
|
/*
|
|
====================
|
|
create_black_hole
|
|
|
|
Creates a spot in 3d space that draws everything towards it
|
|
|
|
vector spot: place to create the black hole
|
|
====================
|
|
*/
|
|
void(vector spot) create_black_hole =
|
|
{
|
|
local entity hole;
|
|
|
|
//put him into the world
|
|
hole = spawn();
|
|
hole.owner = self;
|
|
hole.movetype = MOVETYPE_FLYMISSILE;
|
|
hole.solid = SOLID_BBOX;
|
|
hole.classname = "blackhole";
|
|
|
|
//make him take damage so we can kill him
|
|
hole.takedamage = DAMAGE_AIM;
|
|
|
|
//set up health
|
|
hole.health = set_health(50);
|
|
|
|
//what to do if it dies
|
|
hole.th_die = sp_holeremove;
|
|
|
|
hole.ltime = time;
|
|
hole.avelocity = '800 650 500';
|
|
hole.velocity = '0 0 0';
|
|
|
|
//turn it into a monster
|
|
hole.monflag = "TRUE";
|
|
|
|
setmodel (hole, "models/enemies/demonorb.md2");
|
|
setsize (hole, '-6 -6 -6', '6 6 6');
|
|
|
|
sound (hole, CHAN_WEAPON, "misc/r_tele1.wav", 1, ATTN_NORM);
|
|
setorigin (hole, spot);
|
|
|
|
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
|
WriteByte (MSG_BROADCAST, TE_TELEPORT);
|
|
WriteCoord (MSG_BROADCAST, hole.origin_x);
|
|
WriteCoord (MSG_BROADCAST, hole.origin_y);
|
|
WriteCoord (MSG_BROADCAST, hole.origin_z);
|
|
|
|
hole.touch = sp_holetouch;
|
|
|
|
hole.nextthink = time + 0.1;
|
|
hole.think = sp_holesuck;
|
|
};
|
|
|
|
//====================================================================================================
|
|
//On Fire / Burning Code Below
|
|
|
|
/*
|
|
=================
|
|
FirePhysical
|
|
|
|
This function is called by AmBurning and applies the
|
|
physical aspects of being on fire to the entity.
|
|
=================
|
|
*/
|
|
void() FirePhysical =
|
|
{
|
|
local float rdamage;
|
|
|
|
//set up the damage
|
|
rdamage = 1;
|
|
|
|
//do the damage
|
|
T_Damage(self,self.burninflictor,self.burninflictor,rdamage);
|
|
};
|
|
|
|
void() FireGFXThink =
|
|
{
|
|
//do some angles stuff
|
|
makevectors(self.owner.angles);
|
|
|
|
//dissapear if our time is up
|
|
if (time > self.ltime || time > self.owner.burningtime)
|
|
remove(self);
|
|
else //update our origin
|
|
setorigin(self, (self.owner.origin + (v_forward * 10) - (v_right * self.firern) + '0 0 5'));
|
|
|
|
//make some noise
|
|
sound (self, CHAN_WEAPON, "weapons/lock4.wav", 1, ATTN_NORM);
|
|
|
|
//gotta keep thinking about this
|
|
self.nextthink = time + 0.1;
|
|
self.think = FireGFXThink;
|
|
};
|
|
|
|
/*
|
|
==================
|
|
FireGraphical
|
|
|
|
This function is called by AmBurning and applies the
|
|
graphical aspects of being on fire to the entity.
|
|
|
|
float r: offset to the left or right of self.origin
|
|
==================
|
|
*/
|
|
void(float r) FireGraphical =
|
|
{
|
|
local entity firegfx;
|
|
|
|
//do some angles stuff
|
|
makevectors(self.angles);
|
|
|
|
firegfx = spawn();
|
|
setorigin(firegfx, (self.origin + (v_forward * 10) - (v_right * r) + '0 0 5'));
|
|
|
|
//set model
|
|
setmodel (firegfx, "progs/flame2.mdl");
|
|
|
|
//random chance of being a big flame
|
|
if (random() <= 0.2)
|
|
firegfx.frame = 1;
|
|
|
|
//set up our owner
|
|
firegfx.owner = self;
|
|
|
|
//set up duration
|
|
firegfx.ltime = time + 0.5;
|
|
|
|
//misc
|
|
firegfx.firern = r;
|
|
|
|
//lets do some thinking so we can stay with the entity when he moves
|
|
firegfx.nextthink = time + 0.1;
|
|
firegfx.think = FireGFXThink;
|
|
};
|
|
|
|
float() check_liquid =
|
|
{
|
|
local float p;
|
|
|
|
if (self.classname == "player")
|
|
makevectors(self.v_angle);
|
|
else
|
|
makevectors(self.angles);
|
|
|
|
//check for water, slime, or lava
|
|
p = pointcontents(self.origin + v_forward*16);
|
|
|
|
return p;
|
|
};
|
|
|
|
/*
|
|
================
|
|
AmBurning
|
|
|
|
This function is called by different entities during their think functions
|
|
or by the player during his playerprethink function. It basically
|
|
checks to see if the entity should be on fire right now. And if this is
|
|
the case then it will apply all the physical and graphical aspects of something
|
|
being on fire.
|
|
================
|
|
*/
|
|
void() AmBurning =
|
|
{
|
|
//check for lava
|
|
if (check_liquid() == CONTENT_LAVA) //standing in lava so ofcourse we are on fire!
|
|
self.onfire = 1;
|
|
|
|
//check if the entity is on fire
|
|
if (self.onfire == 1 && time < self.burningtime)
|
|
{
|
|
//yes we are on fire
|
|
if (time < self.burningtime && random() <= 0.2)
|
|
{
|
|
FirePhysical();
|
|
FireGraphical(-5 + random() * 2);
|
|
FireGraphical(0 + random() * 2);
|
|
FireGraphical(5 + random() *2);
|
|
}
|
|
//see if we are in water
|
|
if (check_liquid() == CONTENT_WATER)
|
|
self.onfire = 0; //not on fire anymore
|
|
}
|
|
else if(self.onfire == 1 && time > self.burningtime)
|
|
{
|
|
//lets stop burning now
|
|
self.onfire = 0;
|
|
self.burningtime = 0;
|
|
}
|
|
|
|
//not on fire so don't do anything
|
|
};
|
|
|
|
void(float numlines, string s1, string s2, string s3, string s4) DebugMsg =
|
|
{
|
|
if (numlines >= 1)
|
|
bprint(s1);
|
|
|
|
if (numlines >= 2)
|
|
bprint(s2);
|
|
|
|
if (numlines >= 3)
|
|
bprint(s3);
|
|
|
|
if (numlines >= 4)
|
|
bprint(s4);
|
|
|
|
};
|