Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /====================================================================
- //
- // SWINGING GRAPPLING HOOK by: Perecli Manole AKA Bort
- //
- //====================================================================
- // Aside from this new file, the following are the modifications
- // done to id's original source files:
- //--------------------------------------------------------------------
- // File: Progs.src
- // Location: before the "weapons.qc" line
- // Added: hook.qc
- //--------------------------------------------------------------------
- // File: Client.qc
- // Procedure: PlayerPostThink
- // Location: before line "W_WeaponFrame ();"
- // Added: CheckGrapHook ();
- //--------------------------------------------------------------------
- // File: World.qc
- // Procedure: worldspawn
- // Location: after line "precache_model ("progs/s_spike.mdl");"
- // Added: precache_model ("progs/hook.mdl");
- // precache_model ("progs/chain.mdl");
- //--------------------------------------------------------------------
- // File: Weapons.qc
- // Procedure: W_Precache
- // Location: end of procedure
- // Added: precache_sound ("shambler/smack.wav");
- // precache_sound ("blob/land1.wav");
- // precache_sound ("hook/chain1.wav");
- // precache_sound ("hook/chain2.wav");
- // precache_sound ("hook/retract.wav");
- //--------------------------------------------------------------------
- // File: Defs.qc
- // Declaration group: player only fields
- // Location: after line ".float pain_finished;"
- // Added: .float hook;
- //--------------------------------------------------------------------
- /*
- Rob;
- <hook>.ammo_shells: grading raise/lower
- <hook>.ammo_nails: damageable entity flag
- */
- void(vector org, vector vel, float damage) SpawnBlood; // prototype
- float () crandom; // prototype
- // hook bit flags
- float HOOK_ON = 1; // set if hook command is active
- float HOOK_IN = 2; // set if hook has attached
- float SHRINK_ON = 4; // set if shrink chain is active
- float GROW_ON = 8; // set if grow chain is active
- // impulse constants
- float I_HOOK = 64;
- float I_GROW = 65;
- float I_SHRINK = 66;
- float I_STOP = 67;
- // constants
- float MIN_CHAIN_LEN = 40; // minimum chain length
- float MAX_CHAIN_LEN = 1000; // maximum chain length
- float CHAIN_LINK_LEN = 55; // length between chain link origins
- //--------------------------------------------------------------------
- // Vector dot product function
- //--------------------------------------------------------------------
- float (vector from, vector onto) Dot =
- {
- return from_x * onto_x + from_y * onto_y + from_z * onto_z;
- };
- //--------------------------------------------------------------------
- // Removes hook and detaches player
- //--------------------------------------------------------------------
- void () DropHook =
- {
- local entity linkptr, nextptr;
- // remove all hook flags
- self.owner.shook = 0;
- sound (self.owner, CHAN_AUTO, "weapons/bounce2.wav", 1, ATTN_NORM);
- // removes hook and chain
- linkptr = self.goalentity;
- while (linkptr != world)
- {
- nextptr = linkptr.goalentity;
- remove (linkptr);
- linkptr = nextptr;
- }
- remove( self );
- };
- //--------------------------------------------------------------------
- // Spawn and removes and refreshes chain links
- //--------------------------------------------------------------------
- void () MaintainLinks =
- {
- local vector chainvec, // vector of the chain
- p_self_origin, // predicted future hook origin
- chainunit; // vector of chain with distance of 1
- local entity newlink, // pointer to chain link being added
- currlink, // pointer to current link being traversed
- nextlink; // pointer to next link after current link
- local float chainlen, // length of chain
- currpos, // numeric position of currlink
- linknum, // number of links that should exist
- linkstart; // length from hook at which currlink starts
- // predicts hook's future position since chain links fall behind
- currpos = vlen(self.velocity) / 22; // currpos used here just as an intermediate value
- p_self_origin = self.origin + normalize(self.velocity) * currpos;
- // get info about chain
- // Rob; put 8 units back for appearances in cam view
- if ( (self.dest2_x & (self.owner.flags & FL_CREEPCAM)) )
- {
- makevectors( self.owner.v_angle );
- chainvec = (((self.owner.origin + '0 0 16') - v_forward * 8) - p_self_origin);
- }
- else
- chainvec = ((self.owner.origin + '0 0 16') - p_self_origin);
- chainunit = normalize(chainvec);
- chainvec = chainvec - chainunit * 18;
- chainlen = vlen(chainvec);
- currlink = self;
- currpos = 0;
- // generate and refresh links
- linknum = ceil(chainlen / CHAIN_LINK_LEN);
- while (currpos < linknum)
- {
- // add entities if chain's length grows
- if (currlink.goalentity == world)
- {
- newlink = spawn();
- newlink.movetype = MOVETYPE_NOCLIP;
- newlink.solid = SOLID_NOT;
- newlink.effects = EF_NOMODELFLAGS | EF_LOWPRECISION;
- setmodel (newlink, "progs/chain.mdl");
- setsize (newlink, '0 0 0', '0 0 0');
- newlink.goalentity = world;
- currlink.goalentity = newlink;
- }
- currlink = currlink.goalentity;
- currpos = currpos + 1;
- // set angles
- currlink.angles = vectoangles(chainvec);
- // fixes vectoangles round off error
- if ((currlink.angles_y > 0) && (currlink.angles_y < 180))
- currlink.angles = currlink.angles + '0 1 0';
- // vibrates chain links on the z axis
- //currlink.angles_z = currlink.angles_z + crandom() * 30;
- // set position and frames
- linkstart = (currpos - 1) * CHAIN_LINK_LEN;
- if (currpos < linknum)
- {
- setorigin (currlink, p_self_origin + chainunit * (linkstart + CHAIN_LINK_LEN / 2 ));
- currlink.frame = 9;
- }
- else
- {
- setorigin (currlink, p_self_origin + chainunit * (linkstart + (chainlen - linkstart) / 2 ));
- currlink.frame = floor((chainlen - linkstart) / CHAIN_LINK_LEN * 10);
- }
- }
- // remove remaining entities if chain's length shrinks
- nextlink = currlink.goalentity;
- currlink.goalentity = world;
- currlink = nextlink;
- while (currlink != world)
- {
- nextlink = currlink.goalentity;
- remove (currlink);
- currlink = nextlink;
- }
- };
- //--------------------------------------------------------------------
- // Hook behavior function
- //--------------------------------------------------------------------
- float GROW_RATE = 16;
- float SHRINK_RATE = -20;
- void () HookBehavior =
- {
- local vector spray; // for blood
- local vector chainvec; // chain vector
- local vector velpart; // player's velocity component moving to or away from hook
- local float chainlen; // length of extended chain
- //local float framestep; // grow or shrink step per frame
- local float f1, f2; // restrainment forces
- local float i1, i2; // intermediate values
- local float gs; // Rob
- self.nextthink = time + sys_ticrate;
- // decide when to disconnect hook
- if ( !(self.owner.shook & HOOK_ON) || // if hook has been retracted
- self.owner.teleport_time > time || // if player goes through teleport
- self.owner.solid == SOLID_NOT || // if player dies
- self.enemy.solid == SOLID_NOT || !self.owner.button0) // if target dies
- {
- DropHook();
- return;
- }
- // give some damage to entities that take damage
- if (self.enemy.takedamage)
- {
- if (time > self.wait)
- {
- if (ODDFRAME)
- T_Damage (self.enemy, self, self.owner, 5);
- // when hook hits live entity add blood and sounds
- if (self.enemy.solid == SOLID_SLIDEBOX)
- {
- // .ammo_nails flag used only here
- if (! self.ammo_nails)
- {
- sound (self, CHAN_AUTO, "shambler/smack.wav", 1, ATTN_NORM);
- self.ammo_nails = TRUE;
- }
- else
- sound (self, CHAN_AUTO, "blob/land1.wav", 0.8, ATTN_NORM);
- spray_x = 100 * crandom();
- spray_y = 100 * crandom();
- spray_z = 100 * crandom() + 50;
- SpawnBlood (self.origin, spray, 20);
- setorigin (self, self.enemy.origin + self.enemy.mins + self.enemy.size * 0.5);
- }
- self.wait = time + 0.3;
- }
- }
- self.velocity = self.enemy.velocity;
- chainvec = self.origin - (self.owner.origin + '0 0 16');
- chainlen = vlen (chainvec);
- // .ammo_shells = +- amount to size
- gs = self.ammo_shells;
- ////////////////////////////////////////////////
- if (self.owner.button0)
- { gs = gs + 2;
- if (gs > GROW_RATE) gs = GROW_RATE;
- }
- else
- {
- DropHook();
- return;
- gs = gs - 4;
- if (gs < SHRINK_RATE) gs = SHRINK_RATE;
- }
- /*
- else
- {
- if (gs > 0)
- { gs = gs - 2; // fade from grow
- if (gs < 0) gs = 0;
- }
- if (gs < 0)
- { gs = gs + 4; // fade from shrink
- if (gs > 0) gs = 0;
- }
- }
- */
- self.armorvalue = self.armorvalue + gs;
- if (gs > 0)
- {
- if ( (self.owner.flags & FL_ONGROUND) )
- self.armorvalue = chainlen;
- else
- {
- if (self.delay < time)
- {
- f1 = gs / GROW_RATE;
- //sound (self.owner, CHAN_AUTO, "weapons/chain1.wav", f1, ATTN_NORM);
- self.delay = time + 0.2;
- }
- }
- if ( self.armorvalue > MAX_CHAIN_LEN )
- self.armorvalue = MAX_CHAIN_LEN;
- }
- if (gs < 0)
- {
- // fixes not raising when directly under the hook
- if ( (self.owner.flags & FL_ONGROUND) )
- self.owner.flags = self.owner.flags - FL_ONGROUND;
- if (self.armorvalue < MIN_CHAIN_LEN)
- self.armorvalue = MIN_CHAIN_LEN;
- else
- {
- if (self.delay < time)
- {
- i1 = fabs(gs);
- i2 = fabs(SHRINK_RATE);
- f1 = i1 / i2;
- //sound (self.owner, CHAN_AUTO, "weapons/chain2.wav", f1, ATTN_NORM);
- self.delay = time + 0.2;
- }
- }
- }
- ///////////////////////////////////////////////
- self.ammo_shells = gs;
- // chain physics
- // if player's location is beyond the chain's reach
- if (chainlen > self.armorvalue)
- {
- // determine player's velocity component of chain vector
- i1 = Dot(self.owner.velocity,chainvec);
- i2 = Dot(chainvec,chainvec);
- velpart = chainvec * (i1 / i2);
- // restrainment default force
- f2 = (chainlen - self.armorvalue) * 5;
- // if player's velocity heading is away from the hook
- if (Dot(self.owner.velocity,chainvec) < 0)
- {
- if (chainlen > self.armorvalue)
- self.owner.velocity = self.owner.velocity - (velpart * 0.4);
- // if chain has streched for 25 units
- //if (chainlen > self.armorvalue + 25)
- // remove player's velocity component moving away from hook
- // self.owner.velocity = self.owner.velocity - velpart;
- f1 = f2;
- }
- else // if player's velocity heading is towards the hook
- {
- if (vlen(velpart) < f2)
- f1 = f2 - vlen(velpart);
- else
- f1 = 0;
- }
- }
- else
- f1 = 0;
- // applys chain restrainment
- self.owner.velocity = 0.5 *(self.owner.velocity + normalize(chainvec) * f1);
- MaintainLinks ();
- };
- //--------------------------------------------------------------------
- // Hook's touch function
- //--------------------------------------------------------------------
- void() HookTouch =
- {
- // armorvalue is used to hold current length of chain
- self.armorvalue = vlen(self.origin - (self.owner.origin + '0 0 16'));
- // flags hook as being attached to something
- self.owner.shook = self.owner.shook | HOOK_IN;
- if (other.solid != SOLID_SLIDEBOX)
- {
- sound (self, CHAN_AUTO, "player/axhit2.wav", 1, ATTN_NORM);
- self.avelocity = '0 0 0';
- }
- self.velocity = other.velocity;
- self.enemy = other;
- self.think = HookBehavior;
- self.nextthink = time + sys_ticrate;
- self.touch = SUB_Null;
- };
- //--------------------------------------------------------------------
- // Limit hook length during launch
- //--------------------------------------------------------------------
- void() LaunchHook =
- {
- // armorvalue is used to hold current length of chain
- self.armorvalue = vlen(self.origin - (self.owner.origin + '0 0 32'));
- if ( !(self.owner.shook & HOOK_ON) ||
- self.armorvalue > MAX_CHAIN_LEN ||
- self.owner.solid == SOLID_NOT || !self.owner.button0 )
- {
- DropHook();
- return;
- }
- MaintainLinks ();
- self.nextthink = time + sys_ticrate;
- };
- //--------------------------------------------------------------------
- // Initiates the hook
- //--------------------------------------------------------------------
- void(entity myself) InitiateHook =
- {
- local entity newhook;
- newhook = spawn ();
- newhook.owner = myself;
- newhook.classname = "hook";
- newhook.movetype = MOVETYPE_FLY;
- newhook.solid = SOLID_BBOX;
- newhook.effects = EF_NOMODELFLAGS | EF_LOWPRECISION;
- setmodel (newhook, "progs/hook.mdl");
- setsize (newhook, '0 0 0', '0 0 0');
- makevectors (myself.v_angle);
- setorigin (newhook, myself.origin + (v_forward*16) + '0 0 32' );
- newhook.velocity = v_forward*2000;
- newhook.angles = vectoangles(v_forward);
- newhook.avelocity = '0 0 600';
- sound (myself, CHAN_AUTO, "weapons/ax1.wav", 1, ATTN_NORM);
- // used as pointer to first chain link
- newhook.goalentity = world;
- // Rob; (reminders 0 init values used)
- // self.wait = 0; // damage to ents wait cycle
- // self.ammo_shells = 0; // graded shrink/grow variable
- // self.ammo_nails = FALSE; // initial hit flag for live ents
- // self.delay = 0; // wait cycle for chain raising/lowering sounds
- newhook.touch = HookTouch;
- newhook.nextthink = time + sys_ticrate;
- newhook.think = LaunchHook;
- };
- // called by player jump events (weapons.qc: W_WeaponFrame() )
- void() CheckGrapHookJump =
- {
- if ( (self.shook & HOOK_IN) )
- {
- if ( (self.flags & FL_JUMPRELEASED) && // previous jump cycle has finished
- !(self.flags & FL_ONGROUND) ) // player not on ground
- {
- self.shook = 0; // let hook entity's next think know it's dead
- self.velocity_z = self.velocity_z + 200;
- sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
- }
- }
- };
- //--------------------------------------------------------------------
- // Checks impulse
- //--------------------------------------------------------------------
- void() CheckGrapHook =
- {
- if ((!(self.shook & HOOK_ON)) && self.button0)
- {
- // flags hook as being active
- self.shook = HOOK_ON;
- InitiateHook (self);
- return;
- }
- /*
- if (self.shook & HOOK_ON)
- {
- // release hook
- if (self.impulse == I_HOOK)
- {
- self.shook = self.shook - (self.shook & HOOK_ON);
- return;
- }
- // deactivate chain growth or shrink
- if (!self.button0)
- {
- self.shook = self.shook - (self.shook & (GROW_ON | SHRINK_ON));
- return;
- }
- // activate chain growth
- if (self.impulse == I_GROW)
- {
- self.shook = self.shook | GROW_ON;
- self.shook = self.shook - (self.shook & SHRINK_ON);
- return;
- }
- // activate chain shrinking
- if (self.button0 )
- {
- self.shook = self.shook | SHRINK_ON;
- self.shook = self.shook - (self.shook & GROW_ON);
- }
- }
- */
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement