quake-hipnotic-sdk/progs/hipitems.qc
1997-03-11 00:00:00 +00:00

885 lines
23 KiB
C++

/* items quickc program
by jim dose' 9/13/96
copyright (c)1996 hipnotic interactive, inc.
all rights reserved.
do not distribute.
*/
float underwater = 2;
/*
===============================================================================
hipnotic items
===============================================================================
*/
//
// hip_powerup_touch function
//
void() hip_powerup_touch =
{
local entity stemp;
local float best;
if (other.classname != "player")
return;
if (other.health <= 0)
return;
sprint (other, "you got the ");
sprint (other, self.netname);
sprint (other,"\n");
if (deathmatch)
{
self.mdl = self.model;
// if ((self.classname == "item_artifact_invulnerability") ||
// (self.classname == "item_artifact_invisibility"))
// self.nextthink = time + 60*5;
// else
self.nextthink = time + 60;
self.think = sub_regen;
}
sound (other, chan_voice, self.noise, 1, attn_norm);
stuffcmd (other, "bf\n");
self.solid = solid_not;
other.items2 = other.items2 | self.items2;
self.model = string_null;
// do the apropriate action
if ( self.classname == "item_artifact_wetsuit" )
{
other.wetsuit_time = 1;
other.wetsuit_finished = time + 30;
}
if ( self.classname == "item_artifact_empathy_shields" )
{
other.empathy_time = 1;
other.empathy_finished = time + 30;
}
activator = other;
sub_usetargets(); // fire all targets / killtargets
};
/*quaked item_artifact_wetsuit (0 .5 .8) (-16 -16 -24) (16 16 32)
player takes no damage from electrical attacks and swims faster for 30 seconds
*/
void() item_artifact_wetsuit =
{
self.touch = hip_powerup_touch;
precache_model ("progs/wetsuit.mdl");
precache_sound ("misc/wetsuit.wav");
precache_sound ("misc/weton.wav");
precache_sound ("items/suit2.wav");
self.noise = "misc/weton.wav";
setmodel (self, "progs/wetsuit.mdl");
self.netname = "wetsuit";
self.items2 = hip_it_wetsuit;
setsize (self, '-16 -16 -24', '16 16 32');
startitem ();
};
/*
===============================================================================
//
// horn of conjuring
//
===============================================================================
*/
void() horn_touch =
{
local float amount;
local float value;
if (other.classname != "player")
return;
if (deathmatch)
{
self.mdl = self.model;
self.nextthink = time + 60;
self.think = sub_regen;
}
self.solid = solid_not;
self.model = string_null;
sprint (other, "you got the horn of conjuring\n");
sound (other, chan_voice, self.noise, 1, attn_none);
stuffcmd (other, "bf\n");
activator = other;
horn_active = 1;
horn_charmer = other;
sub_usetargets(); // fire all targets / killtargets
horn_active = 0;
};
/*quaked item_hornofconjuring (0 .5 .8) (-16 -16 0) (16 16 32)
horn of conjuring.
you must make func_spawn entities connected to this entity
to spawn the charmed creature.
*/
void() item_hornofconjuring =
{
self.touch = horn_touch;
precache_model("progs/horn.mdl");
precache_sound("hipitems/horn.wav");
setmodel(self, "progs/horn.mdl");
self.noise = "hipitems/horn.wav";
setsize (self, '-16 -16 0', '16 16 32');
startitem ();
};
/*quaked item_artifact_empathy_shields (0 .5 .8) (-16 -16 0) (16 16 32)
empathy shield.
*/
void() item_artifact_empathy_shields =
{
self.touch = hip_powerup_touch;
precache_model("progs/empathy.mdl");
precache_sound("hipitems/empathy.wav");
precache_sound("hipitems/empathy2.wav");
precache_sound ("items/suit2.wav");
setmodel(self, "progs/empathy.mdl");
self.noise = "hipitems/empathy.wav";
self.netname = "empathy shields";
self.items2 = hip_it_empathy_shields;
setsize (self, '-16 -16 0', '16 16 32');
startitem ();
};
/*
===============================================================================
hipnotic weapons
===============================================================================
*/
/*quaked weapon_mjolnir (0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_mjolnir =
{
precache_model ("progs/g_hammer.mdl");
setmodel (self, "progs/g_hammer.mdl");
self.weapon = 3;
self.netname = "mjolnir";
self.items = it_mjolnir;
self.touch = weapon_touch;
setsize (self, '-16 -16 0', '16 16 56');
startitem ();
};
/*quaked weapon_laser_gun (0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_laser_gun =
{
precache_model ("progs/g_laserg.mdl");
setmodel (self, "progs/g_laserg.mdl");
self.weapon = 3;
self.netname = "laser cannon";
self.items = it_laser_cannon;
self.touch = weapon_touch;
setsize (self, '-16 -16 0', '16 16 56');
startitem ();
};
/*quaked weapon_proximity_gun (0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_proximity_gun =
{
precache_model ("progs/g_prox.mdl");
setmodel (self, "progs/g_prox.mdl");
self.weapon = 3;
self.netname = "proximity gun";
self.items = it_proximity_gun;
self.touch = weapon_touch;
setsize (self, '-16 -16 0', '16 16 56');
startitem ();
};
/*
===============================================================================
hipnotic hazards
===============================================================================
*/
void() spikemine_home =
{
local entity head;
local entity selected;
local float cur_dist;
local float head_dist;
local vector dir, vtemp;
self.frame = self.frame + 1;
if (self.frame==9) self.frame = 0;
self.nextthink = time + 0.2;
self.think = spikemine_home;
// look in our immediate vicinity
if (self.search_time < time)
{
selected = world;
cur_dist = 2000;
head = findradius(self.origin, 2000);
while(head)
{
if(!(head.flags & fl_notarget) && (head.flags & fl_client))
{
if (visible(head) && (head.health > 0))
{
head_dist = vlen(head.origin-self.origin);
if (head_dist < cur_dist)
{
selected = head;
cur_dist = head_dist;
}
}
}
head = head.chain;
}
// if (selected != world && selected != self.enemy)
if (selected != world)
sound (self, chan_voice, "hipitems/spikmine.wav", 1, attn_norm);
self.enemy = selected;
self.search_time = time + 1.3;
}
if (self.enemy == world)
{
sound (self, chan_voice, "misc/null.wav", 1, attn_norm);
self.velocity = '0 0 0';
return;
}
vtemp = self.enemy.origin + '0 0 10';
dir = normalize(vtemp - self.origin);
if (infront(self.enemy))
{
self.velocity = dir * ((skill*50) + 50);
}
else
{
self.velocity = dir * ((skill*50) + 150);
}
};
void() spikemine_touch =
{
if (self.health>0)
{
if (other.classname == "trap_spike_mine")
return;
if (other.classname == "missile")
return;
if (other.classname == "grenade")
return;
if (other.classname == "hiplaser")
return;
if (other.classname == "proximity_grenade")
return;
t_damage(self,self,self,self.health+10);
// killed_monsters = killed_monsters + 1;
// writebyte (msg_all, svc_killedmonster);
}
// self.effects = self.effects | ef_muzzleflash;
t_radiusdamage (self, self, 110, world);
sound (self, chan_weapon, "weapons/r_exp3.wav", 1, attn_norm);
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);
sound (self, chan_voice, "misc/null.wav", 1, attn_norm);
self.velocity = '0 0 0';
self.touch = sub_null;
setmodel (self, "progs/s_explod.spr");
self.solid = solid_not;
s_explode1 ();
};
/*
spike_mine_first_think
*/
void() spike_mine_first_think =
{
self.think = spikemine_home;
self.nextthink = time + 0.1;
self.search_time = 0;
self.takedamage = damage_aim;
self.use = monster_use;
};
/*quaked trap_spike_mine (0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() trap_spike_mine =
{
if (deathmatch)
{
remove(self);
return;
}
precache_model ("progs/spikmine.mdl");
precache_sound ("weapons/r_exp3.wav");
precache_sound ("hipitems/spikmine.wav");
precache_sound ("misc/null.wav");
setmodel (self, "progs/spikmine.mdl");
// setmodel (self, "progs/spike.mdl");
setsize (self, self.mins, self.maxs);
self.classname = "trap_spike_mine";
self.solid = solid_bbox;
self.movetype = movetype_flymissile;
// setsize (self, '0 0 0', '0 0 0');
// self.avelocity = '-100 100 -100';
self.avelocity = '-50 100 150';
if (cvar("skill") <= 1)
self.health = 200;
else
self.health = 400;
self.frame = 0;
self.think = spike_mine_first_think;
self.touch = spikemine_touch;
self.th_die = spikemine_touch;
self.th_stand = spikemine_home;
self.th_walk = spikemine_home;
self.th_run = spikemine_home;
self.th_melee = spikemine_home;
self.th_missile = spikemine_home;
self.nextthink = time + 0.2;
total_monsters = total_monsters + 1;
self.flags = self.flags | fl_monster;
self.deathtype = "was blasted by a spike mine";
};
//============================================================================
float lightning_random = 1;
float lightning_boom = 2;
void() spawnlightningthink =
{
if (time > self.delay)
{
remove(self);
return;
}
self.think = spawnlightningthink;
if (checkclient())
{
writebyte (msg_broadcast, svc_tempentity);
writebyte (msg_broadcast, te_lightning2);
writeentity (msg_broadcast, self);
writecoord (msg_broadcast, self.origin_x);
writecoord (msg_broadcast, self.origin_y);
writecoord (msg_broadcast, self.origin_z);
writecoord (msg_broadcast, self.oldorigin_x);
writecoord (msg_broadcast, self.oldorigin_y);
writecoord (msg_broadcast, self.oldorigin_z);
}
lightningdamage(self.origin, self.oldorigin, self.lastvictim, self.dmg);
self.nextthink = time + 0.1;
};
void() trap_lightning_use =
{
local vector p1, p2;
local vector dir;
local float dst;
local float remainder;
if (time >= self.pausetime)
{
if (self.spawnflags & lightning_boom)
sound (self, chan_auto, "weapons/lstart.wav", 1, attn_norm);
else
sound (self, chan_auto, "weapons/lhit.wav", 1, attn_norm);
if (self.classname == "trap_lightning_triggered")
self.pausetime = time + 0.1;
}
if (self.target)
{
p1 = self.origin;
p2 = self.enemy.origin;
}
else
{
makevectors (self.angles);
self.movedir = v_forward;
traceline (self.origin, self.origin + self.movedir*600, true, self);
p1 = self.origin;
p2 = trace_endpos;
}
// fix up both ends of the lightning
// lightning bolts are 30 units long each
dir = normalize( p2-p1 );
dst = vlen(p2-p1);
dst = dst / 30.0;
remainder = dst - floor(dst);
if (remainder > 0)
{
remainder = remainder - 1;
// split half the remainder with the front and back
remainder = remainder * 15;
p1 = p1 + (remainder*dir);
p2 = p2 - (remainder*dir);
}
if (self.duration > 0.1)
{
local entity temp;
temp = self;
self = spawn();
self.origin = p1;
self.oldorigin = p2;
self.lastvictim = temp;
self.dmg = temp.dmg;
self.delay = time + temp.duration;
spawnlightningthink();
self = temp;
}
else if (checkclient())
{
writebyte (msg_broadcast, svc_tempentity);
writebyte (msg_broadcast, te_lightning2);
writeentity (msg_broadcast, self);
writecoord (msg_broadcast, p1_x);
writecoord (msg_broadcast, p1_y);
writecoord (msg_broadcast, p1_z);
writecoord (msg_broadcast, p2_x);
writecoord (msg_broadcast, p2_y);
writecoord (msg_broadcast, p2_z);
lightningdamage(p1, p2, self, self.dmg);
}
else
lightningdamage(p1, p2, self, self.dmg);
};
void() lightning_think =
{
local float timedelay;
if (self.state)
{
trap_lightning_use();
}
if (self.cnt == 0)
{
if (self.spawnflags & lightning_random)
{
timedelay = self.wait*random();
}
else
{
timedelay = self.wait;
}
self.cnt = 1;
self.t_length = time + self.duration - 0.1;
self.pausetime = time + self.duration - 0.1;
if (self.pausetime < time + 0.3)
self.pausetime = time + 0.3;
if (timedelay < self.duration)
timedelay = self.duration;
self.t_width = time + timedelay;
}
if (time >= self.t_length)
{
self.cnt = 0;
self.nextthink = self.t_width;
}
else
{
self.nextthink = time + 0.2;
}
};
void() lightning_firstthink =
{
local entity targ;
if (self.target)
{
targ = find(world,targetname,self.target);
self.dest = targ.origin;
self.enemy = targ;
}
self.think = sub_null;
self.nextthink = 0;
if (self.classname != "trap_lightning_triggered")
{
self.nextthink = self.huntingcharmer + self.wait + self.ltime;
self.think = lightning_think;
}
};
/*quaked trap_lightning_triggered (0 .5 .8) (-8 -8 -8) (8 8 8) random boom
when triggered, fires lightning in the direction set in quakeed.
"wait" how long to wait between blasts (1.0 default)
if in random mode wait is multiplied by random
"dmg" how much damage lightning should inflict (30 default)
"duration" how long each lightning attack should last (0.1 default)
*/
void() trap_lightning_triggered =
{
if (self.wait == 0)
self.wait = 1.0;
if (self.dmg == 0)
self.dmg = 30;
if (self.duration == 0)
self.duration = 0.1;
self.cnt = 0;
self.use = trap_lightning_use;
precache_sound ("weapons/lhit.wav");
precache_sound ("weapons/lstart.wav");
self.huntingcharmer = self.nextthink;
self.think = lightning_firstthink;
self.nextthink = time + 0.25;
self.deathtype = "is electrocuted";
};
/*quaked trap_lightning (0 .5 .8) (-8 -8 -8) (8 8 8) random boom
continuously fire lightning.
"wait" how long to wait between blasts (1.0 default)
if in random mode wait is multiplied by random
"nextthink" delay before firing first lightning, so multiple traps can be stagered.
"dmg" how much damage lightning should inflict (30 default)
"duration" how long each lightning attack should last (0.1 default)
*/
void() trap_lightning =
{
trap_lightning_triggered ();
self.state = 1;
};
void() trap_lightning_switched_use =
{
self.state = 1 - self.state;
if (self.state == 1)
self.nextthink = self.huntingcharmer;
};
/*quaked trap_lightning_switched (0 .5 .8) (-8 -8 -8) (8 8 8) random boom
continuously fires lightning.
"wait" how long to wait between blasts (1.0 default)
if in random mode wait is multiplied by random
"nextthink" delay before firing first lightning, so multiple traps can be stagered.
"dmg" how much damage lightning should inflict (30 default)
"duration" how long each lightning attack should last (0.1 default)
"state" 0 (default) initially off, 1 initially on.
*/
void() trap_lightning_switched =
{
trap_lightning_triggered ();
self.use = trap_lightning_switched_use;
};
entity tesla_target;
float tesla_numtargets;
void() trap_tesla_scan =
{
local entity head;
local entity prev;
// look in our immediate vicinity
tesla_numtargets = 0;
head = findradius(self.origin, self.distance);
while(head)
{
if(!(head.flags & fl_notarget) && (head.flags & self.cnt))
{
if (visible(head) && (head.health > 0) && (head.struck_by_mjolnir==0))
{
if (tesla_numtargets == 0)
{
tesla_target = head;
}
else
{
prev.next_ent = head;
}
tesla_numtargets = tesla_numtargets + 1;
prev = head;
if (tesla_numtargets==self.count)
return;
}
}
head = head.chain;
}
};
void() teslalightningthink =
{
self.owner.attack_state = 2;
if (time > self.delay)
{
self.enemy.struck_by_mjolnir = 0;
remove(self);
return;
}
traceline (self.origin, self.enemy.origin, true, self);
if (trace_fraction != 1.0 || self.enemy.health<=0 || vlen(self.origin-self.enemy.origin) > (self.distance+10))
{
self.enemy.struck_by_mjolnir = 0;
remove(self);
return;
}
writebyte (msg_broadcast, svc_tempentity);
writebyte (msg_broadcast, te_lightning2);
writeentity (msg_broadcast, self);
writecoord (msg_broadcast, self.origin_x);
writecoord (msg_broadcast, self.origin_y);
writecoord (msg_broadcast, self.origin_z);
writecoord (msg_broadcast, trace_endpos_x);
writecoord (msg_broadcast, trace_endpos_y);
writecoord (msg_broadcast, trace_endpos_z);
lightningdamage(self.origin, trace_endpos, self.lastvictim, self.dmg);
self.nextthink = time + 0.1;
};
void(entity targ) spawnteslalightning =
{
local entity lgt;
// spawn actual lightning
lgt = spawn();
if (self.duration>0)
{
lgt.delay = time + self.duration;
}
else
{
lgt.delay = time + 9999;
}
lgt.enemy = targ;
targ.struck_by_mjolnir = 1;
lgt.distance = self.distance;
lgt.owner = self;
lgt.lastvictim = self.lastvictim;
lgt.dmg = self.dmg;
lgt.origin = self.origin;
lgt.think = teslalightningthink;
lgt.nextthink = time;
lgt.deathtype = self.deathtype;
};
void() trap_tesla_think =
{
if (self.state == 0)
{
self.nextthink = time + 0.25;
return;
}
if (self.attack_state == 0)
{
self.think = trap_tesla_think;
trap_tesla_scan();
if (tesla_numtargets > 0)
{
if (self.wait > 0)
sound (self, chan_auto, "misc/tesla.wav", 1, attn_norm);
self.attack_state = 1;
self.nextthink = time + self.wait;
return;
}
self.nextthink = time + 0.25;
if (self.delay > 0)
{
if (time > self.search_time)
{
self.attack_state = 3;
}
}
}
else if (self.attack_state == 1)
{
trap_tesla_scan();
while (tesla_numtargets > 0)
{
sound (self, chan_auto, "hipweap/mjolhit.wav", 1, attn_norm);
spawnteslalightning (tesla_target);
tesla_target = tesla_target.next_ent;
tesla_numtargets = tesla_numtargets - 1;
}
self.attack_state = 2;
self.nextthink = time + 1;
}
else if (self.attack_state == 2)
{
self.attack_state = 3;
self.nextthink = time + 0.2;
}
else if (self.attack_state == 3)
{
self.attack_state = 0;
self.nextthink = time + 0.1;
if (self.classname == "trap_gods_wrath")
{
self.nextthink = -1;
}
}
};
/*quaked trap_tesla_coil (0 .5 .8) (-8 -8 -8) (8 8 8) targetenemies
targets enemies in vicinity and fires at them
"wait" how long build up should be (2 second default)
"dmg" how much damage lightning should inflict (2 + 5*skill default)
"duration" how long each lightning attack should last (continuous default)
"distance" how far the tesla coil should reach (600 default)
"state" on/off for the coil (0 default is off)
"count" number of people to target (2 default)
*/
void() trap_tesla_coil =
{
precache_sound ("misc/tesla.wav");
precache_sound ("hipweap/mjolhit.wav"); // lightning sound
if (self.wait == 0)
self.wait = 2;
if (self.dmg == 0)
self.dmg = 2 + (5*cvar("skill"));
if (self.duration == 0)
self.duration = -1;
if (self.distance == 0)
self.distance = 600;
if (self.spawnflags & 1)
self.cnt = fl_client | fl_monster;
else
self.cnt = fl_client;
self.use = trap_lightning_switched_use;
if (self.delay == 0)
self.delay = -1;
self.nextthink = time + random();
self.think = trap_tesla_think;
self.lastvictim = world;
tesla_numtargets = 0;
self.attack_state = 0;
self.deathtype = "is electrocuted";
};
void() trap_gods_wrath_use =
{
if (self.attack_state==0)
{
self.search_time = time + self.delay;
self.lastvictim = activator;
trap_tesla_think();
}
};
/*quaked trap_gods_wrath (0 .5 .8) (-8 -8 -8) (8 8 8) targetenemies
targets enemies in vicinity and fires at them
"dmg" how much damage lightning should inflict (5 default)
"duration" how long each lightning attack should last (continuous default)
"distance" how far god's wrath should reach (600 default)
"delay" how long to wait until god calms down
this is only needed if no one is targetted (5 seconds default)
"count" number of people to target (2 default)
*/
void() trap_gods_wrath =
{
if (self.delay == 0)
self.delay = 5;
trap_tesla_coil();
self.wait = 0;
self.state = 1;
self.nextthink = -1;
self.deathtype = "suffers the wrath of god";
// self.attack_state = 1;
self.use = trap_gods_wrath_use;
};
void() trap_gravity_touch =
{
if ( self.attack_finished > time )
return;
if (other.takedamage)
{
t_damage (other, self, self, self.dmg );
self.attack_finished = time + 0.2;
}
};
void() trap_gravity_think =
{
local vector vel;
local vector dir;
local vector delta;
self.ltime = time;
trap_tesla_scan();
while (tesla_numtargets > 0)
{
delta = self.origin - tesla_target.origin;
dir = normalize( delta );
vel = dir * self.speed;
if ( ( tesla_target.wetsuit_finished > time ) &&
( self.spawnflags & underwater ) )
{
vel = vel * 0.6;
}
tesla_target.velocity = tesla_target.velocity + vel;
tesla_target = tesla_target.next_ent;
tesla_numtargets = tesla_numtargets - 1;
}
self.nextthink = time + 0.1;
};
/*quaked trap_gravity_well (.8 .5 0) (-8 -8 -8) (8 8 8) targetenemies underwater
targets enemies in vicinity and draws them near, gibbing them on contact.
underwater cuts the pull in half for players wearing the wetsuit
"distance" how far the gravity well should reach (600 default)
"count" number of people to target (2 default)
"speed" is how strong the pull is. (210 default)
"dmg" is how much damage to do each touch. (10000 default)
*/
void() trap_gravity_well =
{
self.solid = solid_trigger;
self.movetype = movetype_none;
setsize( self, '-16 -16 -16','16 16 16');
if ( self.dmg == 0 )
{
self.dmg = 10000;
}
if ( self.speed == 0 )
self.speed = 210;
if (self.distance == 0)
self.distance = 600;
if (self.spawnflags & 1)
self.cnt = fl_client | fl_monster;
else
self.cnt = fl_client;
self.attack_finished = 0;
self.think = trap_gravity_think;
self.touch = trap_gravity_touch;
self.lastvictim = world;
tesla_numtargets = 0;
self.nextthink = time + 0.1;
self.ltime = time;
};