Hosting and domain costs until October 2024 have been generously sponsored by dumptruck_ds. Thank you!

Editing Hunter Killer Missiles by Sestze

From Quake Wiki

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 4: Line 4:
 
<br>
 
<br>
 
Difficulty Scale: Easy/Medium (up to the reader)
 
Difficulty Scale: Easy/Medium (up to the reader)
<br>
 
<br>
 
Step 1.
 
<br>
 
Add the following code to weapons.qc, near the top.
 
<br>
 
/*
 
<br>
 
=================
 
<br>
 
Hunter Killer
 
<br>
 
By: Sestze (enjoy!)
 
<br>
 
=================
 
<br>
 
*/
 
<br>
 
<br>
 
//Function Prototypes
 
<br>
 
void() W_HunterFire;
 
<br>
 
void() T_HunterTouch;
 
<br>
 
void() S_HunterThink;
 
<br>
 
entity(entity startz, float cr_range, float wall) Checkrad;
 
<br>
 
<br>
 
//Fire Function
 
<br>
 
<br>
 
void() W_HunterFire =
 
<br>
 
{
 
<br>
 
sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM); //Classic rocket fire
 
<br>
 
<br>
 
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1; //Subtract a rocket
 
<br>
 
<br>
 
local entity hunter; //Make an entity
 
<br>
 
<br>
 
hunter = spawn();
 
<br> //Spawn it
 
hunter.classname = "Hunter killer"; //Give it a classname
 
<br>
 
hunter.owner = self; //You own this baby.
 
<br>
 
hunter.oldenemy = self; //You will need this
 
<br>
 
hunter.movetype = MOVETYPE_FLY; //Flies around
 
<br>
 
hunter.solid = SOLID_BBOX; //Solid - Touch on edge, block
 
<br>
 
(Pickable items and missiles)
 
<br>
 
<br>
 
makevectors(self.v_angle); //Make vectors from your
 
<br>
 
current viewing angle
 
<br>
 
hunter.velocity = v_forward * 240; //Fly forward at 240 units (trust me, you will want this)
 
hunter.angles = vectoangles(hunter.velocity); //Set the angles for the object
 
 
hunter.nextthink = time + 0.25; //Quarter second out, activate
 
hunter.think = S_HunterThink; //Activation and thinking function
 
 
hunter.touch = T_HunterTouch; //Touch Function
 
 
setmodel(hunter, "progs/missile.mdl"); //Set the model
 
setsize(hunter, '0 0 0', '0 0 0'); //Set the size
 
setorigin(hunter, self.origin + '0 0 16'); //Set the origin
 
};
 
 
//Touch function
 
void() T_HunterTouch =
 
{
 
if(other == self.owner) //Don't want it blowin up on ya, do ya?
 
return;
 
 
T_RadiusDamage (self, self.oldenemy, 100, world); //Damage!
 
 
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); //Temp entity - Explosion
 
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
 
WriteCoord (MSG_BROADCAST, self.origin_x);
 
WriteCoord (MSG_BROADCAST, self.origin_y);
 
WriteCoord (MSG_BROADCAST, self.origin_z);
 
BecomeExplosion();
 
};
 
 
//Think code
 
void() S_HunterThink =
 
{
 
//Hunter finds an enemy
 
if((self.enemy == world) || (self.enemy.health < 0)) //Checks if enemy is dead or doesnt have enemy
 
self.enemy = Checkrad(self, 1000, TRUE);
 
 
//Declarations
 
local vector vele, vels; //velocity enemy, velocity self
 
local vector ph; //Place holder
 
 
//The tack to opponent
 
vele = (self.enemy.origin + '0 0 16') - self.origin; //Finds the unit vector towards the enemy
 
vele = normalize(vele);
 
 
//Current tack
 
vels = normalize(self.velocity); //defines current vector
 
 
//Check tack to enemy
 
traceline(self.origin, self.origin + vele * 10000, FALSE, self); //Traceline to enemy
 
 
if((trace_fraction != 0) && (self.enemy != world))
 
{
 
//Placeholder
 
ph = vele + vels + vels + vels + vels; //Enemy velocity plus 4 times self velocity
 
 
//Placeholder over three
 
ph = ph * (1/5); //Averaging
 
 
//Setvelocity and here we go!
 
self.velocity = normalize(vels + ph); //Set the velocity
 
self.velocity = self.velocity * 240; //And you are on your way
 
}
 
 
//Check current tack 320 units ahead
 
traceline(self.origin, self.origin + vels * 320, FALSE, self); //Traceline in front (check for walls)
 
 
if((trace_fraction < 0.2))
 
{
 
ph = trace_plane_normal; //Find direction that is perpindicular to the wall
 
ph = ph + vels + vels; //Add that direction plus two times your own
 
ph = ph * (1/3); //Averaging
 
 
self.velocity = normalize(vels + ph); //Set the velocity
 
self.velocity = self.velocity * 240; //And you are on your way
 
}
 
 
//Set the angles
 
self.angles = vectoangles(self.velocity); //Set angle
 
self.aflag = self.aflag + 1; //Add to "idle hands" counter
 
 
if(self.aflag >= 500) //5.25 seconds is up....
 
{
 
self.owner = world; //No more owner, it will attack spawner
 
}
 
 
//Hunter thinks
 
self.nextthink = time + 0.01; //Nextthink will be quick to avoid running into walls
 
};
 
 
//Check radius function
 
entity(entity startz, float cr_range, float wall) Checkrad =
 
{
 
local entity finder; //The .chain entity
 
local float cr_ran; //The range holder
 
local entity blodger; //Entity placeholder
 
cr_ran = 1200; //Set to above the detection radius
 
 
finder = findradius(startz.origin, cr_range); //Finds anything within cr_range units of self
 
 
while(finder)
 
{
 
if((CanDamage(finder, self)) || (!wall)) //If I can see him, or if I just ignore walls alltogether
 
{
 
if(finder.health > 0) //If he lives
 
{
 
if(finder != self.owner) //If he aint my daddy
 
{
 
if(vlen(finder.origin - self.origin) < cr_ran) //If the range of that guy is less than the previous
 
{
 
blodger = finder; //Blodger holds who that is
 
cr_ran = vlen(finder.origin - self.origin); //resets cr_ran for next time
 
}
 
}
 
}
 
}
 
finder = finder.chain; //Loop chain
 
}
 
if(blodger != world) //If Blodger isn't the world
 
return blodger; //blodger is returned
 
else //If blodger = world
 
return world; //return the world
 
};
 
 
 
 
Step 2.
 
 
Scroll down to this line: 977 of weapons.qc. Where it should read: W_FireRocket(); Replace W_FireRocket with W_HunterFire();
 
A quick rundown of what happens (in english):
 
 
The Missile is spawned via the W_HunterFire() function, and it flys at 240 units, it constantly checks a radius of 1000 units for an enemy or other silly bugger, and targets them. It then flies towards the target, trying to avoid walls and other odd things on the way. On contact, it makes itself into an explosion, then calls the T_RadiusDamage function, dealing 100 damage, at the epicenter.
 
 
The reason why I used an entity function to find opponents was for simplicity for any other homing weapons in future. It finds anything within a giant radius (or a small one, your call), and finds the closest one possible.
 
 
Alright, I'm done here, Have fun with new rockets that fly after opponents.
 

Please note that all contributions to Quake Wiki are considered to be released under the GNU Free Documentation License 1.3 or later (see Quake Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)