static int STACK_ARGS segcmp(const void * a, const void * b)
{
	seg_t * seg1 = *((seg_t**)a);
	seg_t * seg2 = *((seg_t**)b);

	return
		P_AproxDistance(seg2->v1->x - compareseg->v1->x, seg2->v1->y - compareseg->v1->y) -
		P_AproxDistance(seg1->v1->x - compareseg->v1->x, seg1->v1->y - compareseg->v1->y);

	//return (seg2->v1 - compareseg->v1).LengthSquared() - (seg1->v1 - compareseg->v1).LengthSquared();
}
void A_InquisitorJump (AActor *self)
{
	fixed_t dist;
	fixed_t speed;
	angle_t an;

	if (self->target == NULL)
		return;

	S_LoopedSound (self, CHAN_ITEM, "inquisitor/jump", 1, ATTN_NORM);
	self->z += 64*FRACUNIT;
	A_FaceTarget (self);
	an = self->angle >> ANGLETOFINESHIFT;
	speed = self->Speed * 2/3;
	self->momx += FixedMul (speed, finecosine[an]);
	self->momy += FixedMul (speed, finesine[an]);
	dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y);
	dist /= speed;
	if (dist < 1)
	{
		dist = 1;
	}
	self->momz = (self->target->z - self->z) / dist;
	self->reactiontime = 60;
	self->flags |= MF_NOGRAVITY;
}
示例#3
0
int DEarthquake::StaticGetQuakeIntensity (AActor *victim)
{
	int intensity = 0;
	TThinkerIterator<DEarthquake> iterator (STAT_EARTHQUAKE);
	DEarthquake *quake;

	if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP))
	{
		return 0;
	}

	while ( (quake = iterator.Next()) != NULL)
	{
		if (quake->m_Spot != NULL)
		{
			fixed_t dist = P_AproxDistance (victim->x - quake->m_Spot->x,
				victim->y - quake->m_Spot->y);
			if (dist < quake->m_TremorRadius)
			{
				if (intensity < quake->m_Intensity)
					intensity = quake->m_Intensity;
			}
		}
	}
	return intensity;
}
示例#4
0
void APowerSpeed::DoEffect ()
{
	if (Owner->player->cheats & CF_PREDICTING)
		return;

	if (level.time & 1)
		return;

	if (P_AproxDistance (Owner->momx, Owner->momy) <= 12*FRACUNIT)
		return;

	AActor *speedMo = Spawn<APlayerSpeedTrail> (Owner->x, Owner->y, Owner->z);
	if (speedMo)
	{
		speedMo->angle = Owner->angle;
		speedMo->Translation = Owner->Translation;
		speedMo->target = Owner;
		speedMo->sprite = Owner->sprite;
		speedMo->frame = Owner->frame;
		speedMo->floorclip = Owner->floorclip;
		if (Owner == players[consoleplayer].camera &&
			!(Owner->player->cheats & CF_CHASECAM))
		{
			speedMo->renderflags |= RF_INVISIBLE;
		}
	}
}
void A_ImpMsAttack (AActor *self)
{
	AActor *dest;
	angle_t an;
	int dist;

	if (!self->target || pr_impmsatk() > 64)
	{
		self->SetState (self->SeeState);
		return;
	}
	dest = self->target;
	self->flags |= MF_SKULLFLY;
	S_SoundID (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
	A_FaceTarget (self);
	an = self->angle >> ANGLETOFINESHIFT;
	self->momx = FixedMul (12*FRACUNIT, finecosine[an]);
	self->momy = FixedMul (12*FRACUNIT, finesine[an]);
	dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
	dist = dist/(12*FRACUNIT);
	if (dist < 1)
	{
		dist = 1;
	}
	self->momz = (dest->z + (dest->height>>1) - self->z)/dist;
}
示例#6
0
void A_Tracer2 (AActor *self)
{
	AActor *dest;
	angle_t exact;
	fixed_t dist;
	fixed_t slope;

	dest = self->tracer;

	if (dest == NULL || dest->health <= 0 || self->Speed == 0)
		return;

	// change angle
	exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y);

	if (exact != self->angle)
	{
		if (exact - self->angle > 0x80000000)
		{
			self->angle -= TRACEANGLE;
			if (exact - self->angle < 0x80000000)
				self->angle = exact;
		}
		else
		{
			self->angle += TRACEANGLE;
			if (exact - self->angle > 0x80000000)
				self->angle = exact;
		}
	}

	exact = self->angle >> ANGLETOFINESHIFT;
	self->momx = FixedMul (self->Speed, finecosine[exact]);
	self->momy = FixedMul (self->Speed, finesine[exact]);

	// change slope
	dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
	dist /= self->Speed;

	if (dist < 1)
	{
		dist = 1;
	}
	if (dest->height >= 56*FRACUNIT)
	{
		slope = (dest->z+40*FRACUNIT - self->z) / dist;
	}
	else
	{
		slope = (dest->z + self->height*2/3 - self->z) / dist;
	}
	if (slope < self->momz)
	{
		self->momz -= FRACUNIT/8;
	}
	else
	{
		self->momz += FRACUNIT/8;
	}
}
示例#7
0
//MAKEME: Make this a smart decision
AActor *DCajunMaster::Find_enemy (AActor *bot)
{
	int count;
	fixed_t closest_dist, temp; //To target.
	AActor *target;
	angle_t vangle;
	AActor *observer;

	if (!deathmatch)
	{ // [RH] Take advantage of the Heretic/Hexen code to be a little smarter
		return P_RoughMonsterSearch (bot, 20);
	}

	//Note: It's hard to ambush a bot who is not alone
	if (bot->player->allround || bot->player->mate)
		vangle = ANGLE_MAX;
	else
		vangle = ENEMY_SCAN_FOV;
	bot->player->allround = false;

	target = NULL;
	closest_dist = FIXED_MAX;
	if (bot_observer)
		observer = players[consoleplayer].mo;
	else
		observer = NULL;

	for (count = 0; count < MAXPLAYERS; count++)
	{
		player_t *client = &players[count];
		if (playeringame[count]
			&& !bot->IsTeammate (client->mo)
			&& client->mo != observer
			&& client->mo->health > 0
			&& bot != client->mo)
		{
			if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be f****n wierd screded up. 
			//if(P_CheckSight( bot, players[count].mo))
			{
				temp = P_AproxDistance (client->mo->x - bot->x,
										client->mo->y - bot->y);

				//Too dark?
				if (temp > DARK_DIST &&
					client->mo->Sector->lightlevel < WHATS_DARK &&
					bot->player->Powers & PW_INFRARED)
					continue;

				if (temp < closest_dist)
				{
					closest_dist = temp;
					target = client->mo;
				}
			}
		}
	}

	return target;
}
bool Sys_1ed64 (AActor *self)
{
	if (P_CheckSight (self, self->target) && self->reactiontime == 0)
	{
		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
	}
	return false;
}
示例#9
0
bool InquisitorCheckDistance (AActor *self)
{
	if (self->reactiontime == 0 && P_CheckSight (self, self->target))
	{
		return P_AproxDistance (self->x - self->target->x, self->y - self->target->y) < 264*FRACUNIT;
	}
	return false;
}
示例#10
0
angle_t DCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
{
	fixed_t dist;
	angle_t ang;
	AActor *actor;
	int m;

	SetBodyAt (bot->x + FixedMul(bot->momx, 5*FRACUNIT),
			   bot->y + FixedMul(bot->momy, 5*FRACUNIT),
			   bot->z + (bot->height / 2), 2);

	actor = bglobal.body2;

	dist = P_AproxDistance (actor->x-enemy->x, actor->y-enemy->y);
	if (dist < SAFE_SELF_MISDIST)
		return 0;
	//Predict.
	m = (((dist+1)/FRACUNIT) / GetDefault<ARocket>()->Speed);

	SetBodyAt (enemy->x + FixedMul (enemy->momx, (m+2*FRACUNIT)),
			   enemy->y + FixedMul(enemy->momy, (m+2*FRACUNIT)), ONFLOORZ, 1);
	dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y);
	//try the predicted location
	if (P_CheckSight (actor, bglobal.body1, 1)) //See the predicted location, so give a test missile
	{
		if (SafeCheckPosition (bot, actor->x, actor->y))
		{
			if (FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
			{
				ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y);
				return ang;
			}
		}
	}
	//Try fire straight.
	if (P_CheckSight (actor, enemy, 0))
	{
		if (FakeFire (bot, enemy, cmd) >= SAFE_SELF_MISDIST)
		{
			ang = R_PointToAngle2(bot->x, bot->y, enemy->x, enemy->y);
			return ang;
		}
	}
	return 0;
}
示例#11
0
void DBot::Pitch (AActor *target)
{
	double aim;
	double diff;

	diff = target->z - player->mo->z;
	aim = atan (diff / (double)P_AproxDistance (player->mo->x - target->x, player->mo->y - target->y));
	player->mo->pitch = -(int)(aim * ANGLE_180/M_PI);
}
示例#12
0
void FCajunMaster::Pitch (AActor *actor, AActor *target)
{
	double aim;
	double diff;

	diff = target->z - actor->z;
	aim = atan (diff / (double)P_AproxDistance (actor->x - target->x, actor->y - target->y));
	actor->pitch = -(int)(aim * ANGLE_180/M_PI);
}
示例#13
0
/**	\brief	The P_Teleport function

	\param	thing	mobj_t to teleport
	\param	x	new x pos
	\param	y	new y pos
	\param	z	new y pos
	\param	angle	new angle to look at

	\return	if true, the thing "teleported"


*/
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove)
{
	if (!P_TeleportMove(thing, x, y, z))
		return false;

	thing->angle = angle;

	if (!dontstopmove)
		thing->momx = thing->momy = thing->momz = 0;
	else // Change speed to match direction
		P_InstaThrust(thing, thing->angle, P_AproxDistance(thing->momx, thing->momy));

	if (thing->player)
	{
		if (thing->eflags & MFE_VERTICALFLIP)
			thing->player->viewz = thing->z + thing->height - thing->player->viewheight;
		else
			thing->player->viewz = thing->z + thing->player->viewheight;

		if (!dontstopmove)
			thing->reactiontime = TICRATE/2; // don't move for about half a second

		// absolute angle position
		if (thing->player == &players[consoleplayer])
			localangle = angle;
		if (splitscreen && thing->player == &players[secondarydisplayplayer])
			localangle2 = angle;

		// move chasecam at new player location
		if (splitscreen && cv_chasecam2.value
			&& thing->player == &players[secondarydisplayplayer])
		{
			P_ResetCamera(thing->player, &camera2);
		}
		else if (cv_chasecam.value && thing->player == &players[displayplayer])
			P_ResetCamera(thing->player, &camera);

		// don't run in place after a teleport
		if (!dontstopmove)
		{
			thing->player->cmomx = thing->player->cmomy = 0;
			thing->player->rmomx = thing->player->rmomy = 0;
			thing->player->speed = 0;
			P_ResetPlayer(thing->player);
			P_SetPlayerMobjState(thing, S_PLAY_STND);
		}

		if (flash)
			thing->player->bonuscount = 10; // flash the palette
	}

	return true;
}
示例#14
0
DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
{
	int weaveindex = self->special1;
	AActor *target = self->target;
	angle_t ang;
	fixed_t dist;

	if (self->reactiontime) self->reactiontime--;
	if (self->threshold) self->threshold--;

	// Float up and down
	self->z += finesine[weaveindex << BOBTOFINESHIFT] * 8;
	self->special1 = (weaveindex + 2) & 63;

	// Ensure it stays above certain height
	if (self->z < self->floorz + (64*FRACUNIT))
	{
		self->z += 2*FRACUNIT;
	}

	if(!self->target || !(self->target->flags&MF_SHOOTABLE))
	{	// Invalid target
		P_LookForPlayers (self,true, NULL);
		return;
	}

	// Strafe
	if (self->special2 > 0)
	{
		self->special2--;
	}
	else
	{
		self->special2 = 0;
		self->velx = self->vely = 0;
		dist = P_AproxDistance (self->x - target->x, self->y - target->y);
		if (dist < FIREDEMON_ATTACK_RANGE)
		{
			if (pr_firedemonchase() < 30)
			{
				ang = R_PointToAngle2 (self->x, self->y, target->x, target->y);
				if (pr_firedemonchase() < 128)
					ang += ANGLE_90;
				else
					ang -= ANGLE_90;
				ang >>= ANGLETOFINESHIFT;
				self->velx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]);
				self->vely = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]);
				self->special2 = 3;		// strafe time
			}
		}
	}
示例#15
0
void A_FiredChase (AActor *actor)
{
	int weaveindex = actor->special1;
	AActor *target = actor->target;
	angle_t ang;
	fixed_t dist;

	if (actor->reactiontime) actor->reactiontime--;
	if (actor->threshold) actor->threshold--;

	// Float up and down
	actor->z += FloatBobOffsets[weaveindex];
	actor->special1 = (weaveindex+2)&63;

	// Ensure it stays above certain height
	if (actor->z < actor->floorz + (64*FRACUNIT))
	{
		actor->z += 2*FRACUNIT;
	}

	if(!actor->target || !(actor->target->flags&MF_SHOOTABLE))
	{	// Invalid target
		P_LookForPlayers (actor,true);
		return;
	}

	// Strafe
	if (actor->special2 > 0)
	{
		actor->special2--;
	}
	else
	{
		actor->special2 = 0;
		actor->momx = actor->momy = 0;
		dist = P_AproxDistance (actor->x - target->x, actor->y - target->y);
		if (dist < FIREDEMON_ATTACK_RANGE)
		{
			if (pr_firedemonchase() < 30)
			{
				ang = R_PointToAngle2 (actor->x, actor->y, target->x, target->y);
				if (pr_firedemonchase() < 128)
					ang += ANGLE_90;
				else
					ang -= ANGLE_90;
				ang >>= ANGLETOFINESHIFT;
				actor->momx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]);
				actor->momy = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]);
				actor->special2 = 3;		// strafe time
			}
		}
	}
示例#16
0
void P_DSparilTeleport (AActor *actor)
{
	int i;
	fixed_t prevX;
	fixed_t prevY;
	fixed_t prevZ;
	AActor *mo;
	ASorcerer2 *self = static_cast<ASorcerer2 *> (actor);
	ABossSpot *spot;
	ABossSpot *initial;

	if (!self->NumBossSpots)
	{ // No spots
		return;
	}
	i = pr_dst () % self->NumBossSpots;
	spot = static_cast<ABossSpot *> (self->FirstBossSpot);
	while (i-- > 0)
	{
		spot = spot->NextSpot;
	}
	initial = spot;
	while (P_AproxDistance (actor->x - spot->x, actor->y - spot->y) < 128*FRACUNIT)
	{
		spot = spot->NextSpot;
		if (spot == NULL)
		{
			spot = static_cast<ABossSpot *> (self->FirstBossSpot);
		}
		if (spot == initial)
		{
			// [RH] Don't inifinite loop if no spots further than 128*FRACUNIT
			return;
		}
	}
	prevX = actor->x;
	prevY = actor->y;
	prevZ = actor->z;
	if (P_TeleportMove (actor, spot->x, spot->y, spot->z, false))
	{
		mo = Spawn<ASorcerer2Telefade> (prevX, prevY, prevZ, ALLOW_REPLACE);
		S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
		actor->SetState (&ASorcerer2::States[S_SOR2_TELE]);
		S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
		actor->z = actor->floorz;
		actor->angle = spot->angle;
		actor->momx = actor->momy = actor->momz = 0;
	}
}
示例#17
0
文件: a_quake.cpp 项目: eevee/zdoom
void DEarthquake::Tick ()
{
	int i;

	if (m_Spot == NULL)
	{
		Destroy ();
		return;
	}
	
	if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX))
	{
		S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM);
	}
	if (m_DamageRadius > 0)
	{
		for (i = 0; i < MAXPLAYERS; i++)
		{
			if (playeringame[i] && !(players[i].cheats & CF_NOCLIP))
			{
				AActor *victim = players[i].mo;
				fixed_t dist;

				dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y);
				// Check if in damage radius
				if (dist < m_DamageRadius && victim->z <= victim->floorz)
				{
					if (pr_quake() < 50)
					{
						P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None);
					}
					// Thrust player around
					angle_t an = victim->angle + ANGLE_1*pr_quake();
					if (m_IntensityX == m_IntensityY)
					{ // Thrust in a circle
						P_ThrustMobj (victim, an, m_IntensityX << (FRACBITS-1));
					}
					else
					{ // Thrust in an ellipse
						an >>= ANGLETOFINESHIFT;
						// So this is actually completely wrong, but it ought to be good
						// enough. Otherwise, I'd have to use tangents and square roots.
						victim->velx += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]);
						victim->vely += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]);
					}
				}
			}
		}
	}
示例#18
0
//
// P_CheckMissileRange
//
boolean P_CheckMissileRange (mobj_t* actor)
{
    fixed_t	dist;
	
    if (! P_CheckSight (actor, actor->target) )
	return false;
	
    if ( actor->flags & MF_JUSTHIT )
    {
	// the target just hit the enemy,
	// so fight back!
	actor->flags &= ~MF_JUSTHIT;
	return true;
    }
	
    if (actor->reactiontime)
	return false;	// do not attack yet
		
    // OPTIMIZE: get this from a global checksight
    dist = P_AproxDistance ( actor->x-actor->target->x,
			     actor->y-actor->target->y) - 64*FRACUNIT;
    
    if (!actor->info->meleestate)
	dist -= 128*FRACUNIT;	// no melee attack, so fire more

    dist >>= 16;

    if (actor->type == MT_VILE)
    {
	if (dist > 14*64)	
	    return false;	// too far away
    }
	

    if (actor->type == MT_UNDEAD)
    {
	if (dist < 196)	
	    return false;	// close for fist attack
	dist >>= 1;
    }
	

    if (actor->type == MT_CYBORG
	|| actor->type == MT_SPIDER
	|| actor->type == MT_SKULL)
    {
	dist >>= 1;
    }
示例#19
0
void DEarthquake::Tick ()
{
	int i;

	if (m_Spot == NULL)
	{
		Destroy ();
		return;
	}

	if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX))
	{
		S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM);
	}
	if (m_DamageRadius > 0)
	{
		for (i = 0; i < MAXPLAYERS; i++)
		{
			if (playeringame[i] && !(players[i].cheats & CF_NOCLIP))
			{
				AActor *victim = players[i].mo;
				fixed_t dist;

				dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y);
				// Check if in damage radius
				if (dist < m_DamageRadius && victim->z <= victim->floorz)
				{
					if (pr_quake() < 50)
					{
						P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None);
					}
					// Thrust player around
					angle_t an = victim->angle + ANGLE_1*pr_quake();
					P_ThrustMobj (victim, an, m_Intensity << (FRACBITS-1));
				}
			}
		}
	}
	if (--m_Countdown == 0)
	{
		if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX))
		{
			S_StopSound(m_Spot, CHAN_BODY);
		}
		Destroy();
	}
}
示例#20
0
//Checks TRUE reachability from
//one actor to another. First mobj (actor) is looker.
bool DCajunMaster::Reachable (AActor *actor, AActor *target)
{
	if (actor == target)
		return false;

	if ((target->Sector->ceilingplane.ZatPoint (target->x, target->y) -
		 target->Sector->floorplane.ZatPoint (target->x, target->y))
		< actor->height) //Where target is, looker can't be.
		return false;

	looker = actor;
	rtarget = target;
	last_s = actor->Sector;
	last_z = last_s->floorplane.ZatPoint (actor->x, actor->y);
	reachable = true;
	estimated_dist = P_AproxDistance (actor->x - target->x, actor->y - target->y);
	P_PathTraverse (actor->x+actor->momx, actor->y+actor->momy, target->x, target->y, PT_ADDLINES|PT_ADDTHINGS, PTR_Reachable);
	return reachable;
}
示例#21
0
void A_SkullAttack(AActor *self, fixed_t speed)
{
	AActor *dest;
	angle_t an;
	int dist;

	// [BC] This is handled server-side.
	if ( NETWORK_InClientMode() )
	{
		return;
	}

	if (!self->target)
		return;
				
	dest = self->target;		
	self->flags |= MF_SKULLFLY;

	S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM);

	// [BC] If we're the server, tell clients play this sound.
	// [BB] And tell them of MF_SKULLFLY.
	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
	{
		SERVERCOMMANDS_SetThingFlags( self, FLAGSET_FLAGS );
		SERVERCOMMANDS_SoundActor( self, CHAN_VOICE, S_GetName( self->AttackSound ), 1, ATTN_NORM );
	}

	A_FaceTarget (self);
	an = self->angle >> ANGLETOFINESHIFT;
	self->velx = FixedMul (speed, finecosine[an]);
	self->vely = FixedMul (speed, finesine[an]);
	dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
	dist = dist / speed;
	
	if (dist < 1)
		dist = 1;
	self->velz = (dest->z + (dest->height>>1) - self->z) / dist;

	// [BC] Update the lost soul's momentum.
	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
		SERVERCOMMANDS_MoveThingExact( self, CM_X|CM_Y|CM_Z|CM_MOMX|CM_MOMY|CM_MOMZ );
}
示例#22
0
END_DEFAULTS

bool AArtiHealingRadius::Use (bool pickup)
{
	bool effective = false;

	for (int i = 0; i < MAXPLAYERS; ++i)
	{
		if (playeringame[i] &&
			players[i].mo != NULL &&
			players[i].mo->health > 0 &&
			P_AproxDistance (players[i].mo->x - Owner->x, players[i].mo->y - Owner->y) <= HEAL_RADIUS_DIST)
		{
			effective |= static_cast<APlayerPawn*>(Owner)->DoHealingRadius (players[i].mo);
		}
	}
	return effective;

}
示例#23
0
//
// P_CheckMeleeRange
//
boolean P_CheckMeleeRange (mobj_t*	actor)
{
    mobj_t*	pl;
    fixed_t	dist;
	
    if (!actor->target)
	return false;
		
    pl = actor->target;
    dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);

    if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
	return false;
	
    if (! P_CheckSight (actor, actor->target) )
	return false;
							
    return true;		
}
示例#24
0
DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump)
{
	fixed_t dist;
	fixed_t speed;
	angle_t an;

	// [BC] This is handled server-side.
	if ( NETWORK_InClientMode() )
	{
		return;
	}

	if (self->target == NULL)
		return;

	S_Sound (self, CHAN_ITEM|CHAN_LOOP, "inquisitor/jump", 1, ATTN_NORM);
	self->z += 64*FRACUNIT;
	A_FaceTarget (self);
	an = self->angle >> ANGLETOFINESHIFT;
	speed = self->Speed * 2/3;
	self->velx += FixedMul (speed, finecosine[an]);
	self->vely += FixedMul (speed, finesine[an]);
	dist = P_AproxDistance (self->target->x - self->x, self->target->y - self->y);
	dist /= speed;
	if (dist < 1)
	{
		dist = 1;
	}
	self->velz = (self->target->z - self->z) / dist;
	self->reactiontime = 60;
	self->flags |= MF_NOGRAVITY;

	// [BC] If we're the server, update the thing's position.
	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
	{
		SERVERCOMMANDS_MoveThingExact( self, CM_Z|CM_MOMX|CM_MOMY|CM_MOMZ );

		// [CW] Also, set the flags to ensure the actor can fly.
		SERVERCOMMANDS_SetThingFlags( self, FLAGSET_FLAGS );
	}
}
示例#25
0
/// Bot pathing: Continue the path from a node to its neighbours.
void SearchNode_t::PushSuccessors(priorityQ_t *q, int destgx, int destgy)
{
  for (int angle=0; angle<NUMBOTDIRS; angle++)
    {
      if (dir[angle])
	{
	  SearchNode_t *node = dir[angle];
	  fixed_t n_cost = costDir[angle] + cost;
	  fixed_t n_heuristic = P_AproxDistance(destgx - node->gx, destgy - node->gy) * 10000;
	  //CONS_Printf("got heuristic of %d\n", node->heuristic);
	  fixed_t n_f = n_cost + n_heuristic;

	  if (node->visited && (node->f <= n_f))
	    continue;  //if already been looked at before, and before look was better
 
	  if (q->FindNode(node))
	    {
	      //this node has already been pushed on the todo list
	      if (node->f <= n_f)
		continue;

	      //the path to get here this way is better then the old one's
	      //so use this instead, remove the old
	      //CONS_Printf("found better path\n");
	      q->RemoveNode(node);
	    }

	  node->cost = n_cost;
	  node->heuristic = n_heuristic;
	  node->f = n_f;
	  node->pprevious = this;
	  q->Push(node);
	  //CONS_Printf("pushed node at x:%d, y:%d\n", node->x>>FRACBITS, node->y>>FRACBITS);
	}
    }
}
示例#26
0
void A_SkullAttack (AActor *self)
{
	AActor *dest;
	angle_t an;
	int dist;

	if (!self->target)
		return;
				
	dest = self->target;		
	self->flags |= MF_SKULLFLY;

	S_SoundID (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM);
	A_FaceTarget (self);
	an = self->angle >> ANGLETOFINESHIFT;
	self->momx = FixedMul (SKULLSPEED, finecosine[an]);
	self->momy = FixedMul (SKULLSPEED, finesine[an]);
	dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
	dist = dist / SKULLSPEED;
	
	if (dist < 1)
		dist = 1;
	self->momz = (dest->z+(dest->height>>1) - self->z) / dist;
}
示例#27
0
DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
{
	bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER);
	angle_t angle;
	AActor *target;
	int dist;

	target = self->target;
	if (!target)
	{
		return;
	}
	if (!friendly)
	{
		S_Sound (self, CHAN_WEAPON, "minotaur/sight", 1, ATTN_NORM);
	}
	dist = P_AproxDistance (self->x-target->x, self->y-target->y);
	if (target->z+target->height > self->z
		&& target->z+target->height < self->z+self->height
		&& dist < (friendly ? 16*64*FRACUNIT : 8*64*FRACUNIT)
		&& dist > 1*64*FRACUNIT
		&& pr_minotaurdecide() < 150)
	{ // Charge attack
		// Don't call the state function right away
		self->SetState (self->FindState ("Charge"), true);
		self->flags |= MF_SKULLFLY;
		if (!friendly)
		{ // Heretic's Minotaur is invulnerable during charge attack
			self->flags2 |= MF2_INVULNERABLE;
		}
		A_FaceTarget (self);
		angle = self->angle>>ANGLETOFINESHIFT;
		self->velx = FixedMul (MNTR_CHARGE_SPEED, finecosine[angle]);
		self->vely = FixedMul (MNTR_CHARGE_SPEED, finesine[angle]);
		self->special1 = TICRATE/2; // Charge duration
	}
示例#28
0
/// Main pathfinding routine
bool BotNodes::FindPath(list<SearchNode_t *> &path, SearchNode_t *start, SearchNode_t *dest)
{
  bool found = false;
  SearchNode_t *best = NULL; // if can't reach destination, try heading towards this closest point
  int numNodesSearched = 0;

  if (start)// || P_AproxDistance(pawn->x - start->x, pawn->y - start->y) > (BOTNODEGRIDSIZE<<1)) //no nodes can get here
    {
      path.clear();

      priorityQ_t pq;
      deque<SearchNode_t *> visitedList;

      //CONS_Printf("closest node found is x:%d, y:%d\n", start->x>>FRACBITS, start->y>>FRACBITS);
      start->pprevious = NULL;
      start->cost = 0;
      start->f = start->heuristic = P_AproxDistance(start->gx - dest->gx, start->gy - dest->gy) * 10000;

      pq.Push(start);

      while (!pq.Empty() && !found) // while there are nodes left to check 
	{
	  SearchNode_t *temp = pq.Pop();

	  //CONS_Printf("doing node a node at x:%d, y:%d\n", temp->x>>FRACBITS, temp->y>>FRACBITS);
	  if (temp == dest)
	    {
	      //I have found the sector where I want to get to
	      best = temp;
	      found = true;
	    }
	  else
	    {
	      if (!best || (temp->heuristic < best->heuristic))
		best = temp;

	      temp->PushSuccessors(&pq, dest->gx, dest->gy);
 
	      if (!temp->visited)
		{
		  visitedList.push_front(temp); //so later can set this back to not visited
		  temp->visited = true;
		}
	    }
	  numNodesSearched++;
	}

      // reset all visited nodes to not visited
      while (!visitedList.empty())
	{
	  visitedList.front()->visited = false;
	  visitedList.pop_front();
	}

      if (best && (best != start))
	{
	  while (best->pprevious) // backtrack the route, store the nodes in the path list
	    {
#ifdef SHOWBOTPATH
	      fixed_t x = posX2x(best->gx);
	      fixed_t y = posY2y(best->gy);
	      best->marker = mp->SpawnDActor(x, y, ONFLOORZ, MT_MISC49);
#endif
	      path.push_front(best);
	      best = best->pprevious;
	    }

	  found = true;
	}
    }
  //else
  // CONS_Printf("Bot is stuck here x:%d y:%d\n", pawn->x>>FRACBITS, pawn->y>>FRACBITS);

  return found;
}
void FPortal::AddVertexToShape(vertex_t *vertex)
{
	for(unsigned i=0;i<Shape.Size(); i++)
	{
		if (vertex->x == Shape[i]->x && vertex->y == Shape[i]->y) return;
	}

	if (Shape.Size() < 2) 
	{
		Shape.Push(vertex);
	}
	else if (Shape.Size() == 2)
	{
		// Special case: We need to check if the vertex is on an extension of the line between the first two vertices.
		int pos = PointOnShapeLineSide(vertex->x, vertex->y, 0);

		if (pos == 0)
		{
			fixed_t distv1 = P_AproxDistance(vertex->x - Shape[0]->x, vertex->y - Shape[0]->y);
			fixed_t distv2 = P_AproxDistance(vertex->x - Shape[1]->x, vertex->y - Shape[1]->y);
			fixed_t distvv = P_AproxDistance(Shape[0]->x - Shape[1]->x, Shape[0]->y - Shape[1]->y);

			if (distv1 > distvv)
			{
				Shape[1] = vertex;
			}
			else if (distv2 > distvv)
			{
				Shape[0] = vertex;
			}
			return;
		}
		else if (pos > 0)
		{
			Shape.Insert(1, vertex);
		}
		else
		{
			Shape.Push(vertex);
		}
	}
	else
	{
		for(unsigned i=0; i<Shape.Size(); i++)
		{
			int startlinepos = PointOnShapeLineSide(vertex->x, vertex->y, i);
			if (startlinepos >= 0)
			{
				int previouslinepos = PointOnShapeLineSide(vertex->x, vertex->y, (i+Shape.Size()-1)%Shape.Size());

				if (previouslinepos < 0)	// we found the first line for which the vertex lies in front
				{
					unsigned int nextpoint = i;

					do
					{
						nextpoint = (nextpoint+1) % Shape.Size();
					}
					while (PointOnShapeLineSide(vertex->x, vertex->y, nextpoint) >= 0);

					int removecount = (nextpoint - i + Shape.Size()) % Shape.Size() - 1;

					if (removecount == 0)
					{
						if (startlinepos > 0) 
						{
							Shape.Insert(i+1, vertex);
						}
					}
					else if (nextpoint > i || nextpoint == 0)
					{
						// The easy case: It doesn't wrap around
						Shape.Delete(i+1, removecount-1);
						Shape[i+1] = vertex;
					}
					else
					{
						// It does wrap around.
						Shape.Delete(i+1, removecount);
						Shape.Delete(1, nextpoint-1);
						Shape[0] = vertex;
					}
					return;
				}
			}
		}
	}
}
示例#30
0
DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
{
	angle_t exact;
	fixed_t dist;
	fixed_t slope;
	AActor *dest;
	AActor *smoke;
				
	// killough 1/18/98: this is why some missiles do not have smoke
	// and some do. Also, internal demos start at random gametics, thus
	// the bug in which revenants cause internal demos to go out of sync.
	//
	// killough 3/6/98: fix revenant internal demo bug by subtracting
	// levelstarttic from gametic:
	//
	// [RH] level.time is always 0-based, so nothing special to do here.

	if (level.time & 3)
		return;
	
	// spawn a puff of smoke behind the rocket
	P_SpawnPuff (self, PClass::FindClass(NAME_BulletPuff), self->x, self->y, self->z, 0, 3);
		
	smoke = Spawn ("RevenantTracerSmoke", self->x - self->velx,
		self->y - self->vely, self->z, ALLOW_REPLACE);
	
	smoke->velz = FRACUNIT;
	smoke->tics -= pr_tracer()&3;
	if (smoke->tics < 1)
		smoke->tics = 1;
	
	// adjust direction
	dest = self->tracer;
		
	if (!dest || dest->health <= 0 || self->Speed == 0 || !self->CanSeek(dest))
		return;
	
	// change angle 	
	exact = R_PointToAngle2 (self->x, self->y, dest->x,  dest->y);

	if (exact != self->angle)
	{
		if (exact - self->angle > 0x80000000)
		{
			self->angle -= TRACEANGLE;
			if (exact - self->angle < 0x80000000)
				self->angle = exact;
		}
		else
		{
			self->angle += TRACEANGLE;
			if (exact - self->angle > 0x80000000)
				self->angle = exact;
		}
	}
		
	exact = self->angle>>ANGLETOFINESHIFT;
	self->velx = FixedMul (self->Speed, finecosine[exact]);
	self->vely = FixedMul (self->Speed, finesine[exact]);

	if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
	{
		// change slope
		dist = P_AproxDistance (dest->x - self->x,
								dest->y - self->y);
		
		dist = dist / self->Speed;

		if (dist < 1)
			dist = 1;

		if (dest->height >= 56*FRACUNIT)
		{
			slope = (dest->z+40*FRACUNIT - self->z) / dist;
		}
		else
		{
			slope = (dest->z + self->height*2/3 - self->z) / dist;
		}

		if (slope < self->velz)
			self->velz -= FRACUNIT/8;
		else
			self->velz += FRACUNIT/8;
	}
}