Пример #1
0
/*
==============
BotChangeViewAngles
==============
*/
void BotChangeViewAngles(bot_state_t *bs, float thinktime)
{
    float diff, factor, maxchange, anglespeed, disired_speed;
    int i;

    if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360;
    //
    if (bs->enemy >= 0)
    {
        factor = botlib_export->ai.Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_FACTOR, 0.01f, 1);
        maxchange = botlib_export->ai.Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_MAXCHANGE, 1, 1800);
    }
    else
    {
        factor = 0.05f;
        maxchange = 360;
    }
    if (maxchange < 240) maxchange = 240;
    maxchange *= thinktime;
    for (i = 0; i < 2; i++)
    {
        //
        if (bot_challenge->integer)
        {
            //smooth slowdown view model
            diff = fabs(AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]));
            anglespeed = diff * factor;
            if (anglespeed > maxchange) anglespeed = maxchange;
            bs->viewangles[i] = BotChangeViewAngle(bs->viewangles[i],
                                                   bs->ideal_viewangles[i], anglespeed);
        }
        else
        {
            //over reaction view model
            bs->viewangles[i] = AngleMod(bs->viewangles[i]);
            bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]);
            diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]);
            disired_speed = diff * factor;
            bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed);
            if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange;
            if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange;
            anglespeed = bs->viewanglespeed[i];
            if (anglespeed > maxchange) anglespeed = maxchange;
            if (anglespeed < -maxchange) anglespeed = -maxchange;
            bs->viewangles[i] += anglespeed;
            bs->viewangles[i] = AngleMod(bs->viewangles[i]);
            //demping
            bs->viewanglespeed[i] *= 0.45 * (1 - factor);
        }
        //BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);`
        //bs->viewangles[i] = bs->ideal_viewangles[i];
    }
    //bs->viewangles[PITCH] = 0;
    if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360;
    //elementary action: view
    botlib_export->ea.EA_View(bs->client, bs->viewangles);
}
Пример #2
0
/*
==============
BotChangeViewAngles
==============
*/
void BotChangeViewAngles( bot_state_t *bs, float thinktime ) {
	float diff, factor, maxchange, anglespeed;
	int i;

	if ( bs->ideal_viewangles[PITCH] > 180 ) {
		bs->ideal_viewangles[PITCH] -= 360;
	}
	//
	if ( bs->enemy >= 0 ) {
		factor = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_VIEW_FACTOR, 0.01, 1 );
		maxchange = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_VIEW_MAXCHANGE, 1, 1800 );
	} else {
		factor = 0.25;
		maxchange = 300;
	}
	maxchange *= thinktime;
	for ( i = 0; i < 2; i++ ) {
		diff = abs( AngleDifference( bs->viewangles[i], bs->ideal_viewangles[i] ) );
		anglespeed = diff * factor;
		if ( anglespeed > maxchange ) {
			anglespeed = maxchange;
		}
		bs->viewangles[i] = BotChangeViewAngle( bs->viewangles[i],
												bs->ideal_viewangles[i], anglespeed );
		//BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);`
		//bs->viewangles[i] = bs->ideal_viewangles[i];
	}
	if ( bs->viewangles[PITCH] > 180 ) {
		bs->viewangles[PITCH] -= 360;
	}
	//elementary action: view
	trap_EA_View( bs->client, bs->viewangles );
}
Пример #3
0
float InterpolateAngle(float a1, float a2, const float pour) {
	
	float a = MAKEANGLE(a1);
	
	float diff = AngleDifference(a, MAKEANGLE(a2));
	
	return MAKEANGLE(a + (diff * pour));
}
Пример #4
0
void EntityPlayer::Flash(Vector Position)
{
	Vector dist = Position - Pos;
	float Angle = 180 / 3.14 * atan2f(dist.Y, dist.X);
	FlashTime = worldObj->FlashManager->MaxFlashTime * (1 - (abs(AngleDifference(Rot,Angle))/90));
	if (FlashTime < 2)
	{
		FlashTime = 2;
	}
	//Make entire screen white
	worldObj->FlashManager->AddFlashBangEvent(this,Position);
}
Пример #5
0
void EntityPlayer::UpdatePlayerAngle()
{
	float RotSpeed = 0.1;
	Vector LookVector = MousePosition;
	float Angle = 180/3.14 * atan2f(LookVector.Y, LookVector.X);
	if (Rot < 170 && Angle > 170)
	{
		int i = 0;
	}
	RotOld += 0.01 * AngleDifference(Rot,Angle);
	//RotOld -= 0.1;
}
Пример #6
0
/*
==============
AICast_ChangeViewAngles
==============
*/
void AICast_ChangeViewAngles( cast_state_t *cs, float thinktime ) {
	float diff, factor, maxchange, anglespeed;
	int i;
	bot_state_t *bs;

	bs = cs->bs;
	//
	// restoire locked viewangles if required
	if ( cs->aiFlags & AIFL_VIEWLOCKED ) {
		VectorCopy( cs->viewlock_viewangles, bs->ideal_viewangles );
	}
	//
	if ( bs->ideal_viewangles[PITCH] > 180 ) {
		bs->ideal_viewangles[PITCH] -= 360;
	}
	//
	maxchange = cs->attributes[YAW_SPEED]; //300;
	if ( cs->aiState >= AISTATE_COMBAT ) {
		factor = 2.0;
		maxchange *= 2.0;
	} else {
		factor = 0.7;
	}
	//
	if ( cs->lockViewAnglesTime < level.time ) {
		maxchange *= thinktime;
		for ( i = 0; i < 3; i++ ) {
			diff = c::fabs( AngleDifference( bs->viewangles[i], bs->ideal_viewangles[i] ) );
			anglespeed = diff * factor;
			if ( anglespeed > maxchange ) {
				anglespeed = maxchange;
			}
			bs->viewangles[i] = BotChangeViewAngle( bs->viewangles[i],
													bs->ideal_viewangles[i], anglespeed );
			//BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);`
			//bs->viewangles[i] = bs->ideal_viewangles[i];
		}
	}
	if ( bs->viewangles[PITCH] > 180 ) {
		bs->viewangles[PITCH] -= 360;
	}
	//elementary action: view
	trap_EA_View( bs->client, bs->viewangles );
}
Пример #7
0
/*
==============
BotChangeViewAngles
==============
*/
void BotChangeViewAngles(bot_state_t *bs, float thinktime) {
	float diff, factor, maxchange, anglespeed, disired_speed;
	int i;

	if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360;
	
	factor = bs->skills.turnspeed;

	if (factor > 1)
	{
		factor = 1;
	}
	if (factor < 0.25)
	{
		factor = 0.25f;
	}
	maxchange = bs->skills.maxturn;

	//if (maxchange < 240) maxchange = 240;
	maxchange *= thinktime;
	for (i = 0; i < 2; i++) {
		bs->viewangles[i] = AngleMod(bs->viewangles[i]);
		bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]);
		diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]);
		disired_speed = diff * factor;
		bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed);
		if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange;
		if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange;
		anglespeed = bs->viewanglespeed[i];
		if (anglespeed > maxchange) anglespeed = maxchange;
		if (anglespeed < -maxchange) anglespeed = -maxchange;
		bs->viewangles[i] += anglespeed;
		bs->viewangles[i] = AngleMod(bs->viewangles[i]);
		bs->viewanglespeed[i] *= 0.45 * (1 - factor);
	}
	if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360;
	trap_EA_View(bs->client, bs->viewangles);
}
Пример #8
0
bool CStructure::IsAvailableAreaActive(int iArea) const
{
	if (iArea != 0)
		return BaseClass::IsAvailableAreaActive(iArea);

	if (!GetDigitanksPlayer())
		return false;

	if (!GetDigitanksPlayer()->GetPrimaryCPU())
		return false;

	if (DigitanksGame()->GetCurrentLocalDigitanksPlayer() == GetDigitanksPlayer())
		return false;

	if (DigitanksGame()->GetControlMode() != MODE_AIM)
		return false;

	CDigitank* pTank = DigitanksGame()->GetCurrentLocalDigitanksPlayer()->GetPrimarySelectionTank();

	if (!pTank)
		return false;

	if (!pTank->IsInsideMaxRange(GetGlobalOrigin()))
		return false;

	if (GetVisibility(pTank->GetDigitanksPlayer()) < 0.1f)
		return false;

	if (pTank->FiringCone() < 360 && fabs(AngleDifference(pTank->GetGlobalAngles().y, VectorAngles((GetGlobalOrigin() - pTank->GetGlobalOrigin()).Normalized()).y)) > pTank->FiringCone())
		return false;

	if (pTank->GetCurrentWeapon() == PROJECTILE_TREECUTTER)
		return false;

	return true;
}
void SensorFusion::handleMessage(const MessageBodyFrame& msg)
{
    if (msg.Type != Message_BodyFrame)
        return;
  
    // Put the sensor readings into convenient local variables
    Vector3f angVel    = msg.RotationRate; 
    Vector3f rawAccel  = msg.Acceleration;
    Vector3f mag       = msg.MagneticField;

    // Set variables accessible through the class API
	DeltaT = msg.TimeDelta;
    AngV = msg.RotationRate;
    AngV.y *= YawMult;  // Warning: If YawMult != 1, then AngV is not true angular velocity
    A = rawAccel;

    // Allow external access to uncalibrated magnetometer values
    RawMag = mag;  

    // Apply the calibration parameters to raw mag
    if (HasMagCalibration())
    {
        mag.x += MagCalibrationMatrix.M[0][3];
        mag.y += MagCalibrationMatrix.M[1][3];
        mag.z += MagCalibrationMatrix.M[2][3];
    }

    // Provide external access to calibrated mag values
    // (if the mag is not calibrated, then the raw value is returned)
    CalMag = mag;

    float angVelLength = angVel.Length();
    float accLength    = rawAccel.Length();


    // Acceleration in the world frame (Q is current HMD orientation)
    Vector3f accWorld  = Q.Rotate(rawAccel);

    // Keep track of time
    Stage++;
    float currentTime  = Stage * DeltaT; // Assumes uniform time spacing

    // Insert current sensor data into filter history
    FRawMag.AddElement(RawMag);
    FAccW.AddElement(accWorld);
    FAngV.AddElement(angVel);

    // Update orientation Q based on gyro outputs.  This technique is
    // based on direct properties of the angular velocity vector:
    // Its direction is the current rotation axis, and its magnitude
    // is the rotation rate (rad/sec) about that axis.  Our sensor
    // sampling rate is so fast that we need not worry about integral
    // approximation error (not yet, anyway).
    if (angVelLength > 0.0f)
    {
        Vector3f     rotAxis      = angVel / angVelLength;  
        float        halfRotAngle = angVelLength * DeltaT * 0.5f;
        float        sinHRA       = sin(halfRotAngle);
        Quatf        deltaQ(rotAxis.x*sinHRA, rotAxis.y*sinHRA, rotAxis.z*sinHRA, cos(halfRotAngle));

        Q =  Q * deltaQ;
    }
    
    // The quaternion magnitude may slowly drift due to numerical error,
    // so it is periodically normalized.
    if (Stage % 5000 == 0)
        Q.Normalize();
    
	// Maintain the uncorrected orientation for later use by predictive filtering
	QUncorrected = Q;

    // Perform tilt correction using the accelerometer data. This enables 
    // drift errors in pitch and roll to be corrected. Note that yaw cannot be corrected
    // because the rotation axis is parallel to the gravity vector.
    if (EnableGravity)
    {
        // Correcting for tilt error by using accelerometer data
        const float  gravityEpsilon = 0.4f;
        const float  angVelEpsilon  = 0.1f; // Relatively slow rotation
        const int    tiltPeriod     = 50;   // Req'd time steps of stability
        const float  maxTiltError   = 0.05f;
        const float  minTiltError   = 0.01f;

        // This condition estimates whether the only measured acceleration is due to gravity 
        // (the Rift is not linearly accelerating).  It is often wrong, but tends to average
        // out well over time.
        if ((fabs(accLength - 9.81f) < gravityEpsilon) &&
            (angVelLength < angVelEpsilon))
            TiltCondCount++;
        else
            TiltCondCount = 0;
    
        // After stable measurements have been taken over a sufficiently long period,
        // estimate the amount of tilt error and calculate the tilt axis for later correction.
        if (TiltCondCount >= tiltPeriod)
        {   // Update TiltErrorEstimate
            TiltCondCount = 0;
            // Use an average value to reduce noice (could alternatively use an LPF)
            Vector3f accWMean = FAccW.Mean();
            // Project the acceleration vector into the XZ plane
            Vector3f xzAcc = Vector3f(accWMean.x, 0.0f, accWMean.z);
            // The unit normal of xzAcc will be the rotation axis for tilt correction
            Vector3f tiltAxis = Vector3f(xzAcc.z, 0.0f, -xzAcc.x).Normalized();
            Vector3f yUp = Vector3f(0.0f, 1.0f, 0.0f);
            // This is the amount of rotation
            float    tiltAngle = yUp.Angle(accWMean);
            // Record values if the tilt error is intolerable
            if (tiltAngle > maxTiltError) 
            {
                TiltErrorAngle = tiltAngle;
                TiltErrorAxis = tiltAxis;
            }
        }

        // This part performs the actual tilt correction as needed
        if (TiltErrorAngle > minTiltError) 
        {
            if ((TiltErrorAngle > 0.4f)&&(Stage < 8000))
            {   // Tilt completely to correct orientation
                Q = Quatf(TiltErrorAxis, -TiltErrorAngle) * Q;
                TiltErrorAngle = 0.0f;
            }
            else 
            {
                //LogText("Performing tilt correction  -  Angle: %f   Axis: %f %f %f\n",
                //        TiltErrorAngle,TiltErrorAxis.x,TiltErrorAxis.y,TiltErrorAxis.z);
                //float deltaTiltAngle = -Gain*TiltErrorAngle*0.005f;
                // This uses agressive correction steps while your head is moving fast
                float deltaTiltAngle = -Gain*TiltErrorAngle*0.005f*(5.0f*angVelLength+1.0f);
                // Incrementally "untilt" by a small step size
                Q = Quatf(TiltErrorAxis, deltaTiltAngle) * Q;
                TiltErrorAngle += deltaTiltAngle;
            }
        }
    }

    // Yaw drift correction based on magnetometer data.  This corrects the part of the drift
    // that the accelerometer cannot handle.
    // This will only work if the magnetometer has been enabled, calibrated, and a reference
    // point has been set.
    const float maxAngVelLength = 3.0f;
    const int   magWindow = 5;
    const float yawErrorMax = 0.1f;
    const float yawErrorMin = 0.01f;
    const int   yawErrorCountLimit = 50;
    const float yawRotationStep = 0.00002f;

    if (angVelLength < maxAngVelLength)
        MagCondCount++;
    else
        MagCondCount = 0;

	YawCorrectionInProgress = false;
    if (EnableYawCorrection && MagReady && (currentTime > 2.0f) && (MagCondCount >= magWindow) &&
        (Q.Distance(MagRefQ) < MagRefDistance))
    {
        // Use rotational invariance to bring reference mag value into global frame
        Vector3f grefmag = MagRefQ.Rotate(GetCalibratedMagValue(MagRefM));
        // Bring current (averaged) mag reading into global frame
        Vector3f gmag = Q.Rotate(GetCalibratedMagValue(FRawMag.Mean()));
        // Calculate the reference yaw in the global frame
        float gryaw = atan2(grefmag.x,grefmag.z);
        // Calculate the current yaw in the global frame
        float gyaw = atan2(gmag.x,gmag.z);
        //LogText("Yaw error estimate: %f\n",YawErrorAngle);
        // The difference between reference and current yaws is the perceived error
        YawErrorAngle = AngleDifference(gyaw,gryaw);
        // If the perceived error is large, keep count
        if ((fabs(YawErrorAngle) > yawErrorMax) && (!YawCorrectionActivated))
            YawErrorCount++;
        // After enough iterations of high perceived error, start the correction process
        if (YawErrorCount > yawErrorCountLimit)
            YawCorrectionActivated = true;
        // If the perceived error becomes small, turn off the yaw correction
        if ((fabs(YawErrorAngle) < yawErrorMin) && YawCorrectionActivated) 
        {
            YawCorrectionActivated = false;
            YawErrorCount = 0;
        }
        // Perform the actual yaw correction, due to previously detected, large yaw error
        if (YawCorrectionActivated) 
        {
			YawCorrectionInProgress = true;
            int sign = (YawErrorAngle > 0.0f) ? 1 : -1;
            // Incrementally "unyaw" by a small step size
            Q = Quatf(Vector3f(0.0f,1.0f,0.0f), -yawRotationStep * sign) * Q;
        }
    }
}
Пример #10
0
void AICast_InputToUserCommand( cast_state_t *cs, bot_input_t *bi, usercmd_t *ucmd, int delta_angles[3] ) {
	vec3_t angles, forward, right, up;
	short temp;
	int j;
	signed char movechar;
	gentity_t *ent;

	ent = &g_entities[cs->entityNum];

	//clear the whole structure
	memset( ucmd, 0, sizeof( usercmd_t ) );
	//
	//Com_Printf("dir = %f %f %f speed = %f\n", bi->dir[0], bi->dir[1], bi->dir[2], bi->speed);
	//the duration for the user command in milli seconds
	ucmd->serverTime = serverTime;
	//crouch/movedown
	if ( aiDefaults[cs->aiCharacter].attributes[ATTACK_CROUCH] ) {    // only crouch if this character is physically able to
		//RF, disabled this bit so truck guy in forest_6 doesn't get stuck and then gib
		if ( /*cs->bs->cur_ps.groundEntityNum != ENTITYNUM_NONE &&*/ bi->actionflags & ACTION_CROUCH ) {
			ucmd->upmove -= 127;
		}
	}
	//
	// actions not effected by script pausing
	//
	// set zoom button
	if ( cs->aiFlags & AIFL_ZOOMING ) {
		ucmd->wbuttons |= WBUTTON_ZOOM;
	}
	//set the buttons
	if ( bi->actionflags & ACTION_ATTACK ) {
		vec3_t ofs;
		// don't fire if we are not facing the right direction yet
		if ( ( cs->triggerReleaseTime < level.time ) &&
			 (   ( cs->lockViewAnglesTime >= level.time ) ||
				 ( c::fabs( AngleDifference( cs->bs->ideal_viewangles[YAW], cs->bs->viewangles[YAW] ) ) < 20 ) ) &&
			 // check for radid luger firing by skilled users (release fire between shots)
			 ( ( ( level.time + cs->entityNum * 500 ) / 2000 ) % 2 || !( rand() % ( 1 + g_gameskill.integer ) ) || ( cs->attributes[ATTACK_SKILL] < 0.5 ) || ( cs->bs->weaponnum != WP_LUGER ) || ( cs->bs->cur_ps.weaponTime == 0 ) || ( cs->bs->cur_ps.releasedFire ) ) ) {
			ucmd->buttons |= BUTTON_ATTACK;
			// do some swaying around for some weapons
			AICast_WeaponSway( cs, ofs );
			VectorAdd( bi->viewangles, ofs, bi->viewangles );
		}
	}
	//
	//set the view angles
	//NOTE: the ucmd->angles are the angles WITHOUT the delta angles
	ucmd->angles[PITCH] = ANGLE2SHORT( bi->viewangles[PITCH] );
	ucmd->angles[YAW] = ANGLE2SHORT( bi->viewangles[YAW] );
	ucmd->angles[ROLL] = ANGLE2SHORT( bi->viewangles[ROLL] );
	//subtract the delta angles
	for ( j = 0; j < 3; j++ ) {
		temp = ucmd->angles[j] - delta_angles[j];
		ucmd->angles[j] = temp;
	}


//----(SA)	modified slightly for DM/DK
	ucmd->weapon = bi->weapon;
	//
	// relaxed mode show no weapons
	if ( cs->aiState <= AISTATE_QUERY ) {
		if ( WEAPS_ONE_HANDED & ( 1 << ucmd->weapon ) ) { // one-handed wepons don't draw, others do
			ucmd->weapon = WP_NONE;
		}
	}
//----(SA)	end

	//
	if ( bi->actionflags & ACTION_GESTURE ) {
		ucmd->buttons |= BUTTON_GESTURE;
	}
	if ( bi->actionflags & ACTION_RELOAD ) {
		ucmd->wbuttons |= WBUTTON_RELOAD;
	}
	//
	// if we are locked down, don't do anything
	//
	if ( cs->pauseTime > level.time ) {
		return;
	}
	//
	// if scripted pause, no movement
	//
	if ( cs->castScriptStatus.scriptNoMoveTime > level.time ) {
		return;
	}
	//
	// if viewlock, wait until we are facing ideal angles before we move
	if ( cs->aiFlags & AIFL_VIEWLOCKED ) {
		if ( c::fabs( AngleDifference( cs->bs->ideal_viewangles[YAW], cs->bs->viewangles[YAW] ) ) > 10 ) {
			return;
		}
	}
	//
	if ( bi->actionflags & ACTION_DELAYEDJUMP ) {
		bi->actionflags |= ACTION_JUMP;
		bi->actionflags &= ~ACTION_DELAYEDJUMP;
	}
	//
	// only move if we are in combat or we are facing where our ideal angles
	if ( bi->speed ) {
		if ( ( !( cs->aiFlags & AIFL_WALKFORWARD ) && cs->bs->enemy >= 0 ) || ( c::fabs( AngleDifference( cs->bs->ideal_viewangles[YAW], cs->bs->viewangles[YAW] ) ) < 60 ) ) {
			//NOTE: movement is relative to the REAL view angles
			//get the horizontal forward and right vector
			//get the pitch in the range [-180, 180]
			if ( bi->dir[2] ) {
				angles[PITCH] = bi->viewangles[PITCH];
			} else { angles[PITCH] = 0;}
			angles[YAW] = bi->viewangles[YAW];
			angles[ROLL] = 0;
			AngleVectors( angles, forward, right, up );
			//bot input speed is in the range [0, 400]
			bi->speed = bi->speed * 127 / 400;
			//set the view independent movement
			ucmd->forwardmove = DotProduct( forward, bi->dir ) * bi->speed;
			ucmd->rightmove = DotProduct( right, bi->dir ) * bi->speed;

			// RF, changed this to fix stim soldier flying attack
			if ( !ucmd->upmove ) { // only change it if we don't already have an upmove set
				ucmd->upmove = DotProduct( up, bi->dir ) * bi->speed;
			}
			//if (!ucmd->upmove)	// only change it if we don't already have an upmove set
			//	ucmd->upmove = c::abs(forward[2]) * bi->dir[2] * bi->speed;
		}
	}
	//
	//normal keyboard movement
	if ( cs->actionFlags & CASTACTION_WALK ) {
		movechar = 70;
	} else {
		movechar = 127;
	}
	if ( bi->actionflags & ACTION_MOVEFORWARD ) {
		ucmd->forwardmove = movechar;
	}
	if ( !( cs->aiFlags & AIFL_WALKFORWARD ) ) {    // only do other movements if we are allowed to
		if ( bi->actionflags & ACTION_MOVEBACK ) {
			ucmd->forwardmove = -movechar;
		}
		if ( bi->actionflags & ACTION_MOVELEFT ) {
			ucmd->rightmove = -movechar;
		}
		if ( bi->actionflags & ACTION_MOVERIGHT ) {
			ucmd->rightmove = movechar;
		}
	}
	//jump/moveup
	if ( bi->actionflags & ACTION_JUMP ) {
		ucmd->upmove = 127;                                 // JUMP always takes preference over ducking
	}
	if ( bi->actionflags & ACTION_MOVEDOWN ) {
		ucmd->upmove = -127;                                    // JUMP always takes preference over ducking
	}
	if ( bi->actionflags & ACTION_MOVEUP ) {
		ucmd->upmove = 127;                                     // JUMP always takes preference over ducking
	}
	//
	//Com_Printf("forward = %d right = %d up = %d\n", ucmd.forwardmove, ucmd.rightmove, ucmd.upmove);
}
Пример #11
0
void EntityLiving::Flash(Vector position)
{
	Vector dist = position - Pos;
	float Angle = 180 / 3.14 * atan2f(dist.Y, dist.X);
	FlashTime = worldObj->FlashManager->MaxFlashTime * (1 - (abs(AngleDifference(Rot, Angle)) / 90));
}
Пример #12
0
/*
=================
G_ScriptAction_FaceAngles

  syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME> [ACCEL/DECCEL]

  The entity will face the given angles, taking <duration> to get there. If the
  GOTOTIME is given instead of a timed duration, the duration calculated from the
  last gotomarker command will be used instead.
=================
*/
qboolean G_ScriptAction_FaceAngles( gentity_t *ent, char *params ) {
    char *pString, *token;
    int duration, i;
    vec3_t diff;
    vec3_t angles;
    int trType = TR_LINEAR_STOP;

    if ( !params || !params[0] ) {
        G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
    }

    if ( ent->scriptStatus.scriptStackChangeTime == level.time ) {
        pString = params;
        for ( i = 0; i < 3; i++ ) {
            token = COM_Parse( &pString );
            if ( !token || !token[0] ) {
                G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
            }
            angles[i] = atoi( token );
        }

        token = COM_Parse( &pString );
        if ( !token || !token[0] ) {
            G_Error( "G_Scripting: faceangles requires a <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
        }
        if ( !Q_strcasecmp( token, "gototime" ) ) {
            duration = ent->s.pos.trDuration;
        } else {
            duration = atoi( token );
        }

        token = COM_Parse( &pString );
        if ( token && token[0] ) {
            if ( !Q_strcasecmp( token, "accel" ) ) {
                trType = TR_ACCELERATE;
            }
            if ( !Q_strcasecmp( token, "deccel" ) ) {
                trType = TR_DECCELERATE;
            }
        }

        for ( i = 0; i < 3; i++ ) {
            diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
            while ( diff[i] > 180 )
                diff[i] -= 360;
            while ( diff[i] < -180 )
                diff[i] += 360;
        }

        VectorCopy( ent->s.angles, ent->s.apos.trBase );
        if ( duration ) {
            VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
        } else {
            VectorClear( ent->s.apos.trDelta );
        }
        ent->s.apos.trDuration = duration;
        ent->s.apos.trTime = level.time;
        ent->s.apos.trType = TR_LINEAR_STOP;

        if ( trType != TR_LINEAR_STOP ) { // accel / deccel logic
            // calc the speed from duration and start/end delta
            for ( i = 0; i < 3; i++ ) {
                ent->s.apos.trDelta[i] = 2.0 * 1000.0 * diff[i] / (float)duration;
            }
            ent->s.apos.trType = trType;
        }

    } else if ( ent->s.apos.trTime + ent->s.apos.trDuration <= level.time ) {
        // finished turning
        BG_EvaluateTrajectory( &ent->s.apos, ent->s.apos.trTime + ent->s.apos.trDuration, ent->s.angles );
        VectorCopy( ent->s.angles, ent->s.apos.trBase );
        VectorCopy( ent->s.angles, ent->r.currentAngles );
        ent->s.apos.trTime = level.time;
        ent->s.apos.trDuration = 0;
        ent->s.apos.trType = TR_STATIONARY;
        VectorClear( ent->s.apos.trDelta );

        script_linkentity( ent );

        return qtrue;
    }

    BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles );
    script_linkentity( ent );

    return qfalse;
}
Пример #13
0
/*
===============
G_ScriptAction_GotoMarker

  syntax: gotomarker <targetname> <speed> [accel/deccel] [turntotarget] [wait]

  NOTE: speed may be modified to round the duration to the next 50ms for smooth
  transitions
===============
*/
qboolean G_ScriptAction_GotoMarker( gentity_t *ent, char *params ) {
    char    *pString, *token;
    gentity_t *target;
    vec3_t vec;
    float speed, dist;
    qboolean wait = qfalse, turntotarget = qfalse;
    int trType;
    int duration, i;
    vec3_t diff;
    vec3_t angles;

    if ( params && ( ent->scriptStatus.scriptFlags & SCFL_GOING_TO_MARKER ) ) {
        // we can't process a new movement until the last one has finished
        return qfalse;
    }

    if ( !params || ent->scriptStatus.scriptStackChangeTime < level.time ) {          // we are waiting for it to reach destination
        if ( ent->s.pos.trTime + ent->s.pos.trDuration <= level.time ) {  // we made it
            ent->scriptStatus.scriptFlags &= ~SCFL_GOING_TO_MARKER;

            // set the angles at the destination
            BG_EvaluateTrajectory( &ent->s.apos, ent->s.apos.trTime + ent->s.apos.trDuration, ent->s.angles );
            VectorCopy( ent->s.angles, ent->s.apos.trBase );
            VectorCopy( ent->s.angles, ent->r.currentAngles );
            ent->s.apos.trTime = level.time;
            ent->s.apos.trDuration = 0;
            ent->s.apos.trType = TR_STATIONARY;
            VectorClear( ent->s.apos.trDelta );

            // stop moving
            BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin );
            VectorCopy( ent->s.origin, ent->s.pos.trBase );
            VectorCopy( ent->s.origin, ent->r.currentOrigin );
            ent->s.pos.trTime = level.time;
            ent->s.pos.trDuration = 0;
            ent->s.pos.trType = TR_STATIONARY;
            VectorClear( ent->s.pos.trDelta );

            script_linkentity( ent );

            return qtrue;
        }
    } else {    // we have just started this command

        pString = params;
        token = COM_ParseExt( &pString, qfalse );
        if ( !token[0] ) {
            G_Error( "G_Scripting: gotomarker must have an targetname\n" );
        }

        // find the entity with the given "targetname"
        target = G_Find( NULL, FOFS( targetname ), token );

        if ( !target ) {
            G_Error( "G_Scripting: can't find entity with \"targetname\" = \"%s\"\n", token );
        }

        VectorSubtract( target->r.currentOrigin, ent->r.currentOrigin, vec );

        token = COM_ParseExt( &pString, qfalse );
        if ( !token[0] ) {
            G_Error( "G_Scripting: gotomarker must have a speed\n" );
        }

        speed = atof( token );
        trType = TR_LINEAR_STOP;

        while ( token[0] ) {
            token = COM_ParseExt( &pString, qfalse );
            if ( token[0] ) {
                if ( !Q_stricmp( token, "accel" ) ) {
                    trType = TR_ACCELERATE;
                } else if ( !Q_stricmp( token, "deccel" ) )      {
                    trType = TR_DECCELERATE;
                } else if ( !Q_stricmp( token, "wait" ) )      {
                    wait = qtrue;
                } else if ( !Q_stricmp( token, "turntotarget" ) )      {
                    turntotarget = qtrue;
                }
            }
        }

        // start the movement
        if ( ent->s.eType == ET_MOVER ) {

            VectorCopy( vec, ent->movedir );
            VectorCopy( ent->r.currentOrigin, ent->pos1 );
            VectorCopy( target->r.currentOrigin, ent->pos2 );
            ent->speed = speed;
            dist = VectorDistance( ent->pos1, ent->pos2 );
            // setup the movement with the new parameters
            InitMover( ent );

            // start the movement

            SetMoverState( ent, MOVER_1TO2, level.time );
            if ( trType != TR_LINEAR_STOP ) { // allow for acceleration/decceleration
                ent->s.pos.trDuration = 1000.0 * dist / ( speed / 2.0 );
                ent->s.pos.trType = trType;
            }
            ent->reached = NULL;

            if ( turntotarget ) {
                duration = ent->s.pos.trDuration;
                VectorCopy( target->s.angles, angles );

                for ( i = 0; i < 3; i++ ) {
                    diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
                    while ( diff[i] > 180 )
                        diff[i] -= 360;
                    while ( diff[i] < -180 )
                        diff[i] += 360;
                }
                VectorCopy( ent->s.angles, ent->s.apos.trBase );
                if ( duration ) {
                    VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
                } else {
                    VectorClear( ent->s.apos.trDelta );
                }
                ent->s.apos.trDuration = duration;
                ent->s.apos.trTime = level.time;
                ent->s.apos.trType = TR_LINEAR_STOP;
                if ( trType != TR_LINEAR_STOP ) { // allow for acceleration/decceleration
                    ent->s.pos.trDuration = 1000.0 * dist / ( speed / 2.0 );
                    ent->s.pos.trType = trType;
                }
            }

        } else {
            // calculate the trajectory
            ent->s.pos.trType = TR_LINEAR_STOP;
            ent->s.pos.trTime = level.time;
            VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
            dist = VectorNormalize( vec );
            VectorScale( vec, speed, ent->s.pos.trDelta );
            ent->s.pos.trDuration = 1000 * ( dist / speed );

            if ( turntotarget ) {
                duration = ent->s.pos.trDuration;
                VectorCopy( target->s.angles, angles );

                for ( i = 0; i < 3; i++ ) {
                    diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
                    while ( diff[i] > 180 )
                        diff[i] -= 360;
                    while ( diff[i] < -180 )
                        diff[i] += 360;
                }
                VectorCopy( ent->s.angles, ent->s.apos.trBase );
                if ( duration ) {
                    VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
                } else {
                    VectorClear( ent->s.apos.trDelta );
                }
                ent->s.apos.trDuration = duration;
                ent->s.apos.trTime = level.time;
                ent->s.apos.trType = TR_LINEAR_STOP;
            }

        }

        if ( !wait ) {
            // round the duration to the next 50ms
            if ( ent->s.pos.trDuration % 50 ) {
                float frac;

                frac = (float)( ( ( ent->s.pos.trDuration / 50 ) * 50 + 50 ) - ent->s.pos.trDuration ) / (float)( ent->s.pos.trDuration );
                if ( frac < 1 ) {
                    VectorScale( ent->s.pos.trDelta, 1.0 / ( 1.0 + frac ), ent->s.pos.trDelta );
                    ent->s.pos.trDuration = ( ent->s.pos.trDuration / 50 ) * 50 + 50;
                }
            }

            // set the goto flag, so we can keep processing the move until we reach the destination
            ent->scriptStatus.scriptFlags |= SCFL_GOING_TO_MARKER;
            return qtrue;   // continue to next command
        }

    }

    BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->r.currentOrigin );
    BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles );
    script_linkentity( ent );

    return qfalse;
}