BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: s_hDll = hModule; DisableThreadLibraryCalls(hModule); SetHook(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: DropHook();//UNHOOK break; } return TRUE; }
void HookAirborne (edict_t *ent) { vec3_t chainvec; // chain's vector float chainlen; // length of extended chain // get info about chain _VectorSubtract (ent->s.origin, ent->owner->s.origin, chainvec); chainlen = VectorLength (chainvec); if ( (!(ent->owner->client->hookstate_ & HOOK_ON)) || (chainlen > hook_max_len->value) ) { DropHook(ent); return; } MaintainLinks (ent); ent->nextthink = level.time + FRAMETIME; }
void HookTouch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t offset, start; vec3_t forward, right; vec3_t chainvec; // chain's vector // derive start point of chain AngleVectors (ent->owner->client->v_angle, forward, right, NULL); VectorSet(offset, 8, 8, ent->owner->viewheight-8); P_ProjectSource_Reverse (ent->owner->client, ent->owner->s.origin, offset, forward, right, start); // member angle is used to store the length of the chain _VectorSubtract(ent->s.origin,start,chainvec); ent->angle = VectorLength (chainvec); // don't attach hook to sky if (surf && (surf->flags & SURF_SKY)) { DropHook(ent); return; } // inflict damage on damageable items if (other->takedamage) T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 100, 0, MOD_HIT); if (other->solid == SOLID_BBOX) { if ((other->svflags & SVF_MONSTER) || (other->client)) gi.sound (ent, CHAN_VOICE, gi.soundindex("hook/smack.wav"), 1, ATTN_IDLE, 0); DropHook(ent); return; } if (other->solid == SOLID_BSP) { // create puff of smoke gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_SHOTGUN); gi.WritePosition (ent->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (ent->s.origin, MULTICAST_PVS); gi.sound (ent, CHAN_VOICE, gi.soundindex("hook/hit.wav"), 1, ATTN_IDLE, 0); VectorClear (ent->avelocity); } else if (other->solid == SOLID_TRIGGER) { // debugging line; don't know if this will ever happen gi.cprintf (ent->owner, PRINT_HIGH, "Hook touched a SOLID_TRIGGER\n"); } // hook gets the same velocity as the item it attached to VectorCopy (other->velocity,ent->velocity); // flags hook as being attached to something ent->owner->client->hookstate_ |= HOOK_IN; ent->enemy = other; ent->touch = NULL; ent->think = HookBehavior; ent->nextthink = level.time + FRAMETIME; }
void HookBehavior(edict_t *ent) { vec3_t offset, start; vec3_t forward, right; vec3_t chainvec; // chain's vector float chainlen; // length of extended chain vec3_t velpart; // player's velocity component moving to or away from hook float force; // restrainment force qboolean chain_moving; // decide when to disconnect hook if ( (!(ent->owner->client->hookstate_ & HOOK_ON)) ||// if hook has been retracted (ent->enemy->solid == SOLID_NOT) || // if target is no longer solid (i.e. hook broke glass; exploded barrels, gibs) (ent->owner->deadflag) || // if player died (ent->owner->s.event == EV_PLAYER_TELEPORT) ) // if player goes through teleport { DropHook(ent); return; } // gives hook same velocity as the entity it is stuck in VectorCopy (ent->enemy->velocity,ent->velocity); // chain sizing chain_moving = false; // grow the length of the chain if ((ent->owner->client->hookstate_ & GROW_ON) && (ent->angle < hook_max_len->value)) { ent->angle += hook_rpf->value; if (ent->angle > hook_max_len->value) ent->angle = hook_max_len->value; chain_moving = true; } // shrink the length of the chain if ((ent->owner->client->hookstate_ & SHRINK_ON) && (ent->angle > hook_min_len->value)) { ent->angle -= hook_rpf->value; if (ent->angle < hook_min_len->value) ent->angle = hook_min_len->value; chain_moving = true; } // determine sound play if climbing or sliding if (chain_moving) { // play start of climb sound if (ent->sounds == MOTOR_OFF) { gi.sound (ent->owner, CHAN_HOOK, gi.soundindex("hook/motor1.wav"), 1, ATTN_IDLE, 0); ent->sounds = MOTOR_START; } // play repetitive climb sound else if (ent->sounds == MOTOR_START) { gi.sound (ent->owner, CHAN_HOOK, gi.soundindex("hook/motor2.wav"), 1, ATTN_IDLE, 0); ent->sounds = MOTOR_ON; } } else if (ent->sounds != MOTOR_OFF) { gi.sound (ent->owner, CHAN_HOOK, gi.soundindex("hook/motor3.wav"), 1, ATTN_IDLE, 0); ent->sounds = MOTOR_OFF; } // chain physics // derive start point of chain AngleVectors (ent->owner->client->v_angle, forward, right, NULL); VectorSet(offset, 8, 8, ent->owner->viewheight-8); P_ProjectSource_Reverse (ent->owner->client, ent->owner->s.origin, offset, forward, right, start); // get info about chain _VectorSubtract (ent->s.origin, start, chainvec); chainlen = VectorLength (chainvec); // if player's location is beyond the chain's reach if (chainlen > ent->angle) { // determine player's velocity component of chain vector VectorScale (chainvec, _DotProduct (ent->owner->velocity, chainvec) / _DotProduct (chainvec, chainvec), velpart); // restrainment default force force = (chainlen - ent->angle) * 5; // if player's velocity heading is away from the hook if (_DotProduct (ent->owner->velocity, chainvec) < 0) { // if chain has streched for 25 units if (chainlen > ent->angle + 25) // remove player's velocity component moving away from hook _VectorSubtract(ent->owner->velocity, velpart, ent->owner->velocity); } else // if player's velocity heading is towards the hook { if (VectorLength (velpart) < force) force -= VectorLength (velpart); else force = 0; } } else force = 0; // disable prediction while suspended in air by hook // if server console variable hook_no_pred is set if (!(ent->owner->client->ps.pmove.pm_flags & PMF_ON_GROUND)) { if (hook_no_pred->value) ent->owner->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; } else ent->owner->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; // applys chain restrainment VectorNormalize (chainvec); VectorMA (ent->owner->velocity, force, chainvec, ent->owner->velocity); MaintainLinks (ent); // prep for next think ent->nextthink = level.time + FRAMETIME; }