|
|
Line 1: |
Line 1: |
− | <nowiki>Created By: Sestze
| + | Created By: Sestze |
| Email: sestze@yahoo.com | | Email: sestze@yahoo.com |
− | Difficulty Scale: Easy/Medium (up to the reader) | + | Difficulty Scale: Easy/Medium (up to the reader) |
− |
| |
− | | |
− | Step 1.
| |
− | | |
− | Add the following code to weapons.qc, near the top.
| |
− | | |
− | /*
| |
− | =================
| |
− | Hunter Killer
| |
− | By: Sestze (enjoy!)
| |
− | =================
| |
− | */
| |
− | | |
− | //Function Prototypes
| |
− | void() W_HunterFire;
| |
− | void() T_HunterTouch;
| |
− | void() S_HunterThink;
| |
− | entity(entity startz, float cr_range, float wall) Checkrad;
| |
− | | |
− | //Fire Function
| |
− | void() W_HunterFire =
| |
− | {
| |
− | sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM); //Classic rocket fire
| |
− |
| |
− | self.currentammo = self.ammo_rockets = self.ammo_rockets - 1; //Subtract a rocket
| |
− |
| |
− | local entity hunter; //Make an entity
| |
− |
| |
− | hunter = spawn(); //Spawn it
| |
− | hunter.classname = "Hunter killer"; //Give it a classname
| |
− | hunter.owner = self; //You own this baby.
| |
− | hunter.oldenemy = self; //You will need this
| |
− | hunter.movetype = MOVETYPE_FLY; //Flies around
| |
− | hunter.solid = SOLID_BBOX; //Solid - Touch on edge, block (Pickable items and missiles)
| |
− |
| |
− | makevectors(self.v_angle); //Make vectors from your current viewing angle
| |
− | 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.
| |
− | </nowiki>
| |
Created By: Sestze
Email: sestze@yahoo.com
Difficulty Scale: Easy/Medium (up to the reader)