Exemplo n.º 1
0
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;
}