Esempio n. 1
0
void multi_touch(  )
{
	gedict_t *te;

	if ( !other->s.v.classname )
		return;
	if ( strneq( other->s.v.classname, "player" ) )
		return;

	if ( !Activated( self, other ) )
	{
		if ( self->else_goal )
		{
			te = Findgoal( self->else_goal );
			if ( te )
				AttemptToActivate( te, other, self );
		}
		return;
	}

	if ( !VectorCompareF( self->s.v.movedir, 0, 0, 0 ) )
	{
		trap_makevectors( other->s.v.angles );
		if ( DotProduct( g_globalvars.v_forward, self->s.v.movedir ) < 0 )
			return;	// not facing the right way
	}

	self->s.v.enemy = EDICT_TO_PROG( other );
	multi_trigger(  );
}
Esempio n. 2
0
/*
   ====================================
   FireSentryBulletsMTFL2
   ====================================
   */
static void sgAimMTFL2( gedict_t*self, gedict_t*  targ, vec3_t src, vec3_t  dir )
{
    vec3_t  dst;

    trap_makevectors( self->s.v.v_angle );

    VectorAdd( self->s.v.origin, self->s.v.view_ofs, src );
    VectorAdd( targ->s.v.origin, targ->s.v.view_ofs, dst );
    VectorSubtract( dst, src, dir );
}
Esempio n. 3
0
static void BotDodgeMovement(gedict_t* self, vec3_t dir_move, float dodge_factor) {
	if (dodge_factor) {
		if (dodge_factor < 0) {
			++dodge_factor;
		}
		else {
			--dodge_factor;
		}
		trap_makevectors(self->s.v.v_angle);
		VectorMA(dir_move, g_random() * self->fb.skill.dodge_amount * dodge_factor, g_globalvars.v_right, dir_move);
	}
}
Esempio n. 4
0
static void BotOnGroundMovement(gedict_t* self, vec3_t dir_move) {
	float dodge_factor = 0;

	if ((int)self->s.v.flags & FL_ONGROUND) {
		if (!(self->fb.path_state & NO_DODGE)) {
			// Dodge a rocket our enemy is firing at us
			if (self->fb.missile_dodge && g_globalvars.time - self->fb.missile_dodge->fb.missile_spawntime >= self->fb.skill.missile_dodge_time) {
				if (PROG_TO_EDICT(self->fb.missile_dodge->s.v.owner)->ct == ctPlayer) {
					vec3_t rel_pos;

					VectorSubtract(self->s.v.origin, self->fb.missile_dodge->s.v.origin, rel_pos);
					if (DotProduct(rel_pos, self->fb.missile_dodge->fb.missile_forward) > 0.7071067) {
						vec3_t temp;
						normalize(rel_pos, temp);
						dodge_factor = DotProduct(temp, self->fb.missile_dodge->fb.missile_right);
					}
				}
				else {
					self->fb.missile_dodge = NULL;
				}
			}

			// Not dodging a missile, dodge away from the player instead
			if (self->fb.look_object && self->fb.look_object->ct == ctPlayer) {
				if (!dodge_factor) {
					vec3_t rel_pos;

					VectorSubtract (self->s.v.origin, self->fb.look_object->s.v.origin, rel_pos);
					trap_makevectors(self->fb.look_object->s.v.v_angle);
					if (DotProduct(rel_pos, g_globalvars.v_forward) > 0) {
						vec3_t temp;
						normalize(rel_pos, temp);
						dodge_factor = DotProduct(temp, g_globalvars.v_right);
					}
				}
			}

			BotDodgeMovement(self, dir_move, dodge_factor);
		}
	}

	// If we're not in water, cannot have vertical direction (think of markers heading up stairs)
	if (self->s.v.waterlevel <= 1) {
		dir_move[2] = 0;
	}
}
Esempio n. 5
0
////////////////
// GlobalParams:
// time
// self
///////////////
void SpectatorThink()
{
	gedict_t *wizard = self->wizard;

	if ( self->last_goal != self->s.v.goalentity ) {
		SpecGoalChanged();

		self->last_goal = self->s.v.goalentity;
	}

	if ( self->autotrack )
		DoAutoTrack();

	if ( self->s.v.impulse )
		SpectatorImpulseCommand();

	if ( self->sc_stats && self->sc_stats_time && self->sc_stats_time <= g_globalvars.time && match_in_progress != 1 )
		Print_Scores ();

	if ( self->wp_stats && self->wp_stats_time && self->wp_stats_time <= g_globalvars.time && match_in_progress != 1 )
		Print_Wp_Stats ();

	if ( wizard ) {
		// set model angles
		wizard->s.v.angles[0] = -self->s.v.v_angle[0] / 2;
		wizard->s.v.angles[1] = self->s.v.v_angle[1];
        // wizard model blinking at spectator screen - so move model behind spec camera a bit		
		trap_makevectors( self->s.v.v_angle );
		VectorMA (self->s.v.origin, -32, g_globalvars.v_forward, wizard->s.v.origin);
		// model bobbing
		wizard->s.v.origin[2] += sin( g_globalvars.time * 2.5 );
		setorigin( wizard, PASSVEC3( wizard->s.v.origin ) );

		if ( GetSpecWizard () ) {
			gedict_t *goal = PROG_TO_EDICT( self->s.v.goalentity );

			if ( goal && goal->ct == ctPlayer ) // tracking player, so turn model off
				wizard->s.v.model = "";
			else // turn model on
				setmodel( wizard, "progs/wizard.mdl" );
		}
		else {
			wizard->s.v.model = ""; // turn model off
		}
	}
}
Esempio n. 6
0
/*
=============
infront

returns 1 if the entity is in front (in sight) of self
=============
*/
float infront( gedict_t *targ )
{
	vec3_t	vec;
	float	dot;

	trap_makevectors( self->s.v.angles );
	VectorSubtract(targ->s.v.origin, self->s.v.origin, vec);
	VectorNormalize( vec );
	dot = DotProduct( vec, g_globalvars.v_forward );

	if ( dot > 0.3 )
	{
		return true;
	}

	return false;
}
Esempio n. 7
0
// Called from weapons.c
void GrappleThrow()
{
    if ( self->hook_out ) // only throw once
        return;

    g_globalvars.msg_entity = EDICT_TO_PROG( self );
    WriteByte( MSG_ONE, SVC_SMALLKICK );

    // chain out sound (loops)
    sound ( self, CHAN_WEAPON, "weapons/chain1.wav", 1, ATTN_NORM );

    newmis                = spawn();
    g_globalvars.newmis   = EDICT_TO_PROG( newmis );
    newmis->s.v.movetype  = MOVETYPE_FLYMISSILE;
    newmis->s.v.solid     = SOLID_BBOX;
    newmis->s.v.owner     = EDICT_TO_PROG( self );
    self->hook            = newmis;
    newmis->s.v.classname = "hook";

    trap_makevectors ( self->s.v.v_angle );

    // Weapon velocitys should not be based on server maxspeed imo
    // Removing purectf velocity changes ( 2.5 * self->maxspeed )

    if ( self->ctf_flag & CTF_RUNE_HST )
        VectorScale( g_globalvars.v_forward, 1000, newmis->s.v.velocity );
    else
        VectorScale( g_globalvars.v_forward, 800, newmis->s.v.velocity );
    SetVector( newmis->s.v.avelocity, 0, 0, -500 );

    newmis->s.v.touch     = (func_t) GrappleAnchor;
    newmis->s.v.think     = (func_t) BuildChain;
    newmis->s.v.nextthink = g_globalvars.time + 0.1;

    if ( k_ctf_custom_models )
        setmodel ( newmis, "progs/star.mdl" );
    else
        setmodel ( newmis, "progs/v_spike.mdl" );

    setorigin(newmis, self->s.v.origin[0] + g_globalvars.v_forward[0] * 16,
              self->s.v.origin[1] + g_globalvars.v_forward[1] * 16,
              self->s.v.origin[2] + g_globalvars.v_forward[2] * 16 + 16);
    setsize( newmis, 0, 0, 0, 0, 0, 0 );
    self->hook_out = true;
}
Esempio n. 8
0
//
// GrappleTrack - Constantly updates the hook's position relative to
//                 what it's hooked to. Inflicts damage if attached to
//                 a player that is not on the same team as the hook's
//                 owner.
//
void GrappleTrack()
{
    gedict_t *enemy = PROG_TO_EDICT(self->s.v.enemy);
    gedict_t *owner = PROG_TO_EDICT(self->s.v.owner);

    // Release dead targets
    if ( enemy->ct == ctPlayer && ISDEAD( enemy ) )
        owner->on_hook = false;

    // drop the hook if owner is dead or has released the button
    if ( !owner->on_hook || owner->s.v.health <= 0 )
    {
        GrappleReset( self );
        return;
    }

    if ( enemy->ct == ctPlayer )
    {
        if ( !CanDamage(enemy, owner) )
        {
            GrappleReset( self );
            return;
        }

        // move the hook along with the player.  It's invisible, but
        // we need this to make the sound come from the right spot
        setorigin( self, PASSVEC3(enemy->s.v.origin) );

        sound ( self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM );
        enemy->deathtype = dtHOOK;
        T_Damage ( enemy, self, owner, 1 );
        trap_makevectors ( self->s.v.v_angle );
        SpawnBlood( enemy->s.v.origin, 1 );
    }

    // If the hook is not attached to the player, constantly copy
    // the target's velocity. Velocity copying DOES NOT work properly
    // for a hooked client.
    if ( enemy->ct != ctPlayer )
        VectorCopy( enemy->s.v.velocity, self->s.v.velocity );

    self->s.v.nextthink = g_globalvars.time + 0.1;
}
Esempio n. 9
0
void ai_charge_side()
{
	vec3_t	tmpv;
	float	heading;

	// aim to the left of the enemy for a flyby

	VectorSubtract( PROG_TO_EDICT( self->s.v.enemy )->s.v.origin, self->s.v.origin, tmpv );
	self->s.v.ideal_yaw = vectoyaw( tmpv );
	changeyaw( self );

	trap_makevectors( self->s.v.angles );

	VectorMA( PROG_TO_EDICT( self->s.v.enemy )->s.v.origin, -30, g_globalvars.v_right, tmpv );
	VectorSubtract( tmpv, self->s.v.origin, tmpv );
	heading = vectoyaw( tmpv );

	walkmove( self, heading, 20 );
}
Esempio n. 10
0
void sgAimNew( gedict_t* self, gedict_t* targ, vec3_t src, vec3_t dst, vec3_t norm_dir)
{
    vec3_t  dir,  tmp;
    trap_makevectors( self->s.v.v_angle );

    VectorAdd( self->s.v.origin, self->s.v.view_ofs, src );
    VectorAdd( targ->s.v.origin, targ->s.v.view_ofs, dst );
    VectorSubtract( dst, src, dir );

    normalize(dir, norm_dir);

    //чтобы не попадать в подставку
    traceline( PASSVEC3( src ), PASSVEC3( dst ), 0, self );

    if( (PROG_TO_EDICT(g_globalvars.trace_ent) == self->trigger_field) && vlen(dir) > 100 )
    {
        VectorScale( norm_dir, 60, tmp);
        VectorAdd(src,tmp,src);
    }
}
Esempio n. 11
0
void    FireSentryLighting( gedict_t * targ )  
{
    vec3_t  src;
    vec3_t  dst;
    vec3_t  dir, end, norm_dir;
    gedict_t*trace_ent;

    switch( tfset_sg_sfire )
    {
        case SG_SFIRE_NEW:
            VectorCopy( self->s.v.angles, self->s.v.v_angle );
            sgAimNew( self, targ, src, dst, norm_dir );

            VectorCopy(dst,end);
            break;
        case SG_SFIRE_MTFL2:
            VectorCopy( self->s.v.angles, self->s.v.v_angle );
            sgAimMTFL2( self, targ, src, dir );

            VectorNormalize( dir );
            VectorScale( dir, 2048, end );
            VectorAdd( end, src, end );
            break;

        case SG_SFIRE_MTFL1:
            VectorCopy( self->s.v.angles, self->s.v.v_angle );
        case SG_SFIRE_281:
            trap_makevectors( self->s.v.v_angle );
            VectorScale( g_globalvars.v_forward, 10, src );
            VectorAdd( self->s.v.origin, src, src );
            src[2] = self->s.v.absmin[2] + self->s.v.size[2] * 0.7;
            VectorSubtract( targ->s.v.origin, self->s.v.origin, dir );
            VectorScale( dir, 2048, end );
            VectorAdd( end, src, end );
            break;
        default:
            return;
    }
    g_globalvars.trace_ent = 0;

    traceline( PASSVEC3( src ), PASSVEC3( end ), 0, self );


    trap_WriteByte( MSG_MULTICAST, SVC_TEMPENTITY );
    trap_WriteByte( MSG_MULTICAST, TE_LIGHTNING2 );
    WriteEntity( MSG_MULTICAST, self );
    trap_WriteCoord( MSG_MULTICAST, src[0] );
    trap_WriteCoord( MSG_MULTICAST, src[1] );
    trap_WriteCoord( MSG_MULTICAST, src[2] );
    trap_WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[0] );
    trap_WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[1] );
    trap_WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[2] );
    trap_multicast( PASSVEC3( src ), 1 );
    if ( g_globalvars.trace_ent )
    {
        trace_ent = PROG_TO_EDICT(g_globalvars.trace_ent);
        if ( streq( trace_ent->s.v.classname, "player" ) )
        {
            switch((int)( g_random(  ) * 30) )  
            {
                case 0:
                    sound( trace_ent, 2, "player/pain1.wav" , 1, 1 );
                    break;
                case 1:
                    sound( trace_ent, 2, "player/pain1.wav" , 1, 1 );
                    break;
                case 2:
                    sound( trace_ent, 2, "player/pain2.wav" , 1, 1 );
                    break;
                case 3:
                    sound( trace_ent, 2, "player/pain3.wav" , 1, 1 );
                    break;
                case 4:
                    sound( trace_ent, 2, "player/pain4.wav" , 1, 1 );
                    break;
                case 5:
                    sound( trace_ent, 2, "player/pain5.wav" , 1, 1 );
                    break;
                case 6:
                    sound( trace_ent, 2, "player/pain6.wav" , 1, 1 );
                    break;
                default:break;
            }
        }
    }
}
Esempio n. 12
0
void DropFlag( gedict_t *flag, qbool tossed )
{
	gedict_t *p = PROG_TO_EDICT( flag->s.v.owner );
	gedict_t *p1;

	p->ctf_flag -= ( p->ctf_flag & CTF_FLAG );
	p->s.v.effects -= ( (int) p->s.v.effects & ( EF_FLAG1 | EF_FLAG2 ));
	p->s.v.items -= ( (int) p->s.v.items & (int) flag->s.v.items );

	setorigin( flag, PASSVEC3(p->s.v.origin) );
	flag->s.v.origin[2] -= 24;
	flag->cnt = FLAG_DROPPED;
	if ( tossed )
	{
		trap_makevectors( p->s.v.v_angle );
		if ( p->s.v.v_angle[0] )
		{
			flag->s.v.velocity[0] = g_globalvars.v_forward[0] * 300 + g_globalvars.v_up[0] * 200;
			flag->s.v.velocity[1] = g_globalvars.v_forward[1] * 300 + g_globalvars.v_up[1] * 200;
			flag->s.v.velocity[2] = g_globalvars.v_forward[2] * 300 + g_globalvars.v_up[2] * 200;
		}
		else
		{
			aim( flag->s.v.velocity );
			VectorScale( flag->s.v.velocity, 300, flag->s.v.velocity );
			flag->s.v.velocity[2] = 200;
		}
	}
	else
	{
		SetVector( flag->s.v.velocity, 0, 0, 300 );
	}
	flag->s.v.flags = FL_ITEM;
	flag->s.v.solid = SOLID_TRIGGER;
	flag->s.v.movetype = MOVETYPE_TOSS;
	setmodel( flag, flag->mdl );
	setsize ( flag, -16, -16, 0, 16, 16, 74 );
	flag->super_time = g_globalvars.time + FLAG_RETURN_TIME;
	if ( tossed )
	{
		flag->s.v.nextthink = g_globalvars.time + 0.75;
		flag->s.v.think = (func_t) FlagResetOwner;
	}
	else
	{
		flag->s.v.owner = EDICT_TO_PROG( flag );
	}

	G_bprint( 2, "%s", p->s.v.netname );
	if ( streq(getteam(p), "red") )
		G_bprint( 2, " %s the %s flag!\n", tossed ? redtext("tossed") : redtext("lost"), redtext("BLUE") );
	else
		G_bprint( 2, " %s the %s flag!\n", tossed ? redtext("tossed") : redtext("lost"), redtext("RED") );

	for ( p1 = world; (p1 = find_plr( p1 )); )
	{
		if ( strneq(getteam(p), getteam(p1)) )
			p1->carrier_hurt_time = -1;
	}

	refresh_plus_scores (); // update players status bar faster
}
Esempio n. 13
0
void BotSetCommand (gedict_t* self)
{
	extern float last_frame_time;
	float msec_since_last = (last_frame_time - self->fb.last_cmd_sent) * 1000;
	int cmd_msec = (int)msec_since_last;
	int weapon_script_impulse = 0;
	int impulse = 0;
	qbool jumping;
	qbool firing;
	vec3_t direction;

	BotPerformRocketJump (self);

	if (cmd_msec) {
		self->fb.cmd_msec_lost += (msec_since_last - cmd_msec);
		if (self->fb.cmd_msec_lost >= 1) {
			self->fb.cmd_msec_lost -= 1;
			cmd_msec += 1;
		}
	}
	else if (self->fb.cmd_msec_last) {
		// Probably re-sending after blocked(), re-use old number
		cmd_msec = self->fb.cmd_msec_last;
	}
	else {
		cmd_msec = 12;
	}

	//G_sprint(self, PRINT_HIGH, "Movement length @ %f: %d\n", last_frame_time, cmd_msec);

	// dir_move_ is the direction we want to move in, but need to take inertia into effect
	// ... as rough guide (and save doubling physics calculations), scale command > 
	VectorNormalize (self->fb.dir_move_);
	VectorScale (self->fb.dir_move_, sv_maxspeed, self->fb.last_cmd_direction);

	trap_makevectors (self->fb.desired_angle);

	// During intermission, always do nothing and leave humans to change level
	if (intermission_running) {
		self->fb.firing = self->fb.jumping = false;
	}
	else if (teamplay && deathmatch == 1 && !self->fb.firing) {
		// Weaponscripts
		if (self->s.v.weapon != IT_SHOTGUN && self->s.v.weapon != IT_AXE) {
			weapon_script_impulse = (self->s.v.ammo_shells ? 2 : 1);
		}
	}

	impulse =
		self->fb.botchose ? self->fb.next_impulse :
		self->fb.firing ? self->fb.desired_weapon_impulse :
		weapon_script_impulse;

	if (self->fb.firing && BotUsingCorrectWeapon (self)) {
		impulse = 0; // we already have the requested weapon
	}

	jumping = self->fb.jumping || self->fb.waterjumping;
	firing = self->fb.firing;

	self->fb.waterjumping = false;

	if (self->fb.dbg_countdown > 0) {
		jumping = firing = false;
		VectorClear (direction);
		--self->fb.dbg_countdown;
	}
	else {
		if (jumping && ((int)self->s.v.flags & FL_ONGROUND)) {
			BestJumpingDirection (self);
		}
		else {
			ApplyPhysics (self);
		}

		if (self->s.v.waterlevel <= 1) {
			vec3_t hor;

			VectorCopy (self->fb.dir_move_, hor);
			hor[2] = 0;
			VectorNormalize (hor);
			VectorScale (hor, 800, hor);

			direction[0] = DotProduct (g_globalvars.v_forward, hor);
			direction[1] = DotProduct (g_globalvars.v_right, hor);
			direction[2] = 0;
		}
		else {
			direction[0] = DotProduct (g_globalvars.v_forward, self->fb.dir_move_) * 800;
			direction[1] = DotProduct (g_globalvars.v_right, self->fb.dir_move_) * 800;
			direction[2] = DotProduct (g_globalvars.v_up, self->fb.dir_move_) * 800;
		}
#ifdef DEBUG_MOVEMENT
		if (self->fb.debug_path) {
			G_bprint (PRINT_HIGH, "     : final direction sent [%4.1f %4.1f %4.1f]\n", PASSVEC3 (self->fb.dir_move_));
		}
#endif
	}
	self->fb.desired_angle[2] = 0;

	if (ISDEAD (self)) {
		firing = false;
		jumping = BotRequestRespawn (self);
		VectorClear (direction);
		impulse = 0;
	}
	else if (self->fb.min_move_time > g_globalvars.time) {
		VectorClear (direction);
	}

	// Keep bots on spawns before match start
	if (match_in_progress != 2 && cvar(FB_CVAR_FREEZE_PREWAR)) {
		jumping = firing = false;
		VectorClear(direction);
		impulse = 0;
	}

	trap_SetBotCMD (
		NUM_FOR_EDICT (self),
		cmd_msec,
		PASSVEC3(self->fb.desired_angle),
		PASSVEC3(direction),
		(firing ? 1 : 0) | (jumping ? 2 : 0),
		impulse
	);

	self->fb.next_impulse = 0;
	self->fb.botchose = false;
	self->fb.last_cmd_sent = last_frame_time;
	self->fb.cmd_msec_last = cmd_msec;

	VectorClear (self->fb.obstruction_normal);
	if (self->s.v.button0 && !firing) {
		// Stopped firing, randomise next time
		self->fb.last_rndaim_time = 0;
	}
	self->fb.prev_look_object = self->fb.look_object;
	VectorCopy (self->s.v.velocity, self->fb.prev_velocity);
}
Esempio n. 14
0
float AverageTraceAngle (gedict_t* self, qbool debug, qbool report)
{
	vec3_t back_left, projection, incr;
	int angles[] = { 45, 30, 15, 0, -15, -30, -45 };
	int i;
	float best_angle = 0;
	float best_angle_frac = 0;
	float total_angle = 0;
	float avg_angle;

	float distance = 320;

	if (self->fb.path_state & JUMP_LEDGE)
		return 0;

	if (debug) {
		trap_makevectors (self->s.v.angles);
	}
	else {
		trap_makevectors (self->fb.dir_move_);
	}
	VectorMA (self->s.v.origin, -VEC_HULL_MIN[0], g_globalvars.v_forward, back_left);
	VectorMA (back_left, VEC_HULL_MIN[1], g_globalvars.v_right, back_left);

	VectorScale (g_globalvars.v_right, (VEC_HULL_MAX[0] - VEC_HULL_MIN[0]) / (sizeof(angles) / sizeof(angles[0]) - 1), incr);

	if (debug) {
		G_bprint (2, "Current origin: %d %d %d\n", PASSINTVEC3 (self->s.v.origin));
		G_bprint (2, "Current angles: %d %d\n", PASSINTVEC3 (self->s.v.angles));
	}

	for (i = 0; i < sizeof (angles) / sizeof (angles[0]); ++i) {
		int angle = angles[i];

		RotatePointAroundVector (projection, g_globalvars.v_up, g_globalvars.v_forward, angle);
		VectorMA (back_left, distance, projection, projection);
		traceline (PASSVEC3 (back_left), PASSVEC3 (projection), false, self);

		if (g_globalvars.trace_fraction == 1) {
			total_angle += angle * 1.5; // bonus for success
		}
		else if (g_globalvars.trace_fraction > 0.4) {
			total_angle += angle * g_globalvars.trace_fraction;
		}

		if (debug) {
			G_bprint (2, "Angle: %d => [%d %d %d] [%d %d %d] = %f\n", angle, PASSINTVEC3 (back_left), PASSINTVEC3 (projection), g_globalvars.trace_fraction);
		}

		if (i == 0 || g_globalvars.trace_fraction > best_angle_frac) {
			best_angle = angle;
			best_angle_frac = g_globalvars.trace_fraction;
		}

		VectorAdd (back_left, incr, back_left);
	}

	avg_angle = total_angle / (sizeof (angles) / sizeof (angles[0]));

	if (debug) {
		G_bprint (2, "Best angle: %d\n", best_angle);
		G_bprint (2, "Total angle: %f\n", avg_angle);
	}
	return avg_angle;
}
Esempio n. 15
0
void teleport_touch(  )
{
	gedict_t *t, *te;
	vec3_t  org;

	if ( self->s.v.targetname )
	{
		if ( self->s.v.nextthink < g_globalvars.time )
		{
			return;	// not fired yet
		}
	}
	if ( ( int ) ( self->s.v.spawnflags ) & PLAYER_ONLY )
	{
		if ( strneq( other->s.v.classname, "player" ) )
			return;
	}
	if ( !Activated( self, other ) )
	{
		if ( self->else_goal )
		{
			te = Findgoal( self->else_goal );
			if ( te )
				AttemptToActivate( te, other, self );
		}
		return;
	}
// only teleport living creatures
	if ( other->s.v.health <= 0 || other->s.v.solid != SOLID_SLIDEBOX )
		return;

//        activator = other;
	SUB_UseTargets(  );

	//put a tfog where the player was
	spawn_tfog( other->s.v.origin );

	t = trap_find( world, FOFS( s.v.targetname ), self->s.v.target );
	if ( !t )
		G_Error( "couldn't find target" );

// spawn a tfog flash in front of the destination
	trap_makevectors( t->mangle );
	org[0] = t->s.v.origin[0] + 32 * g_globalvars.v_forward[0];
	org[1] = t->s.v.origin[1] + 32 * g_globalvars.v_forward[1];
	org[2] = t->s.v.origin[2] + 32 * g_globalvars.v_forward[2];

	spawn_tfog( org );
	spawn_tdeath( t->s.v.origin, other );

// move the player and lock him down for a little while
	if ( !other->s.v.health )
	{
		VectorCopy( t->s.v.origin, other->s.v.origin );
		other->s.v.velocity[0] =
		    ( g_globalvars.v_forward[0] * other->s.v.velocity[0] ) +
		    ( g_globalvars.v_forward[0] * other->s.v.velocity[1] );
		other->s.v.velocity[1] =
		    ( g_globalvars.v_forward[1] * other->s.v.velocity[0] ) +
		    ( g_globalvars.v_forward[1] * other->s.v.velocity[1] );
		other->s.v.velocity[2] =
		    ( g_globalvars.v_forward[2] * other->s.v.velocity[0] ) +
		    ( g_globalvars.v_forward[2] * other->s.v.velocity[1] );

		//other->s.v.velocity = (v_forward * other->s.v.velocity[0]) + (v_forward * other->s.v.velocity[1]);
		return;
	}
	setorigin( other, PASSVEC3( t->s.v.origin ) );
	VectorCopy( t->mangle, other->s.v.angles );
// other.angles = t.mangle;
	if ( streq( other->s.v.classname, "player" ) )
	{
		if ( other->s.v.weapon == 1 && other->hook_out )
		{
			sound( other, 1, "weapons/bounce2.wav", 1, 1 );
			other->on_hook = 0;
			other->hook_out = 0;
			other->fire_held_down = 0;
			other->s.v.weaponframe = 0;
			other->attack_finished = g_globalvars.time + 0.75;
		}
		other->s.v.fixangle = 1;	// turn this way immediately
		other->s.v.teleport_time = g_globalvars.time + 0.7;
		if ( ( int ) other->s.v.flags & FL_ONGROUND )
			other->s.v.flags = other->s.v.flags - FL_ONGROUND;
		VectorScale( g_globalvars.v_forward, 300, other->s.v.velocity );
//  other->s.v.velocity = v_forward * 300;
	}
	other->s.v.flags -= ( int ) other->s.v.flags & FL_ONGROUND;
}