Created
November 18, 2014 12:39
-
-
Save Kolesias123/9794faaa12c2a2e76c7c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//==== InfoSmart 2014. http://creativecommons.org/licenses/by/2.5/mx/ ===========// | |
#include "cbase.h" | |
#include "bot.h" | |
#include "in_utils.h" | |
// memdbgon must be the last include file in a .cpp file!!! | |
#include "tier0/memdbgon.h" | |
float CBot::GetEndAimTime() | |
{ | |
static const int iAngDiff = 40; // 30 degrees to make time difference in bot's aim. | |
static const int iEndAimSize = 180/iAngDiff + 1; | |
static const float aEndAimTime[LAST_AIM_SPEED][iEndAimSize] = | |
{ | |
{ 0.50f, 0.70f, 0.90f, 1.10f, 1.30f }, // AIM_SPEED_VERYLOW | |
{ 0.50f, 0.60f, 0.70f, 0.80f, 0.90f }, // AIM_SPEED_LOW | |
{ 0.50f, 0.55f, 0.60f, 0.65f, 0.70f }, // AIM_SPEED_NORMAL | |
{ 0.40f, 0.45f, 0.50f, 0.55f, 0.60f }, // AIM_SPEED_FAST | |
{ 0.25f, 0.30f, 0.35f, 0.40f, 0.45f }, // AIM_SPEED_VERYFAST | |
}; | |
int aimSpeed = AIM_SPEED_LOW; | |
// ¡Estamos en combate! | |
if ( Owner()->InCombat() ) | |
aimSpeed = AIM_SPEED_NORMAL; | |
// Bajo ataque | |
if ( Owner()->IsUnderAttack() || GetEnemy() ) | |
aimSpeed = AIM_SPEED_FAST; | |
QAngle angNeeded( m_lookAt ); | |
Utils::GetAngleDifference( Owner()->GetLocalAngles(), angNeeded, angNeeded ); | |
int iPitch = abs( (int)angNeeded.x ); | |
int iYaw = abs( (int)angNeeded.y ); | |
iPitch /= iAngDiff; | |
iYaw /= iAngDiff; | |
if ( iPitch < iYaw) | |
iPitch = iYaw; // iPitch = MAX2( iPitch, iYaw ); | |
float aimTime = aEndAimTime[aimSpeed][iPitch]; | |
return aimTime; | |
} | |
void CBot::GetAimCenter( CBaseEntity *pEntity, Vector &vecAim ) | |
{ | |
vecAim = pEntity->edict()->GetCollideable()->GetCollisionOrigin(); | |
// TODO | |
if ( pEntity->MyCombatCharacterPointer() ) | |
vecAim.z += HalfHumanHeight; | |
} | |
bool CBot::GetBodyPartPosition( CBaseAnimating *pEntity, BodyPart part, Vector &vecPosition ) | |
{ | |
if ( !pEntity ) | |
return false; | |
// La ubicación del pie | |
if ( part == FEET ) | |
{ | |
vecPosition = pEntity->GetAbsOrigin(); | |
vecPosition.z += 5.0f; | |
return true; | |
} | |
CStudioHdr *studioHdr = pEntity->GetModelPtr(); | |
if ( !studioHdr ) | |
return false; | |
mstudiohitboxset_t *set = studioHdr->pHitboxSet( pEntity->GetHitboxSet() ); | |
if ( !set ) | |
return false; | |
QAngle angles; | |
mstudiobbox_t *box; | |
// Obtenemos la información con los huesos de la entidad | |
BodyInfo_t pInfo = GetBodyInfo( pEntity ); | |
int hitbox = pInfo.m_iHeadBone; | |
// Seleccionamos la ID del hueso solicitado | |
switch ( part ) | |
{ | |
case HEAD: | |
{ | |
hitbox = pInfo.m_iHeadBone; | |
break; | |
} | |
case GUST: | |
{ | |
hitbox = pInfo.m_iGust; | |
break; | |
} | |
case LEFT_ARM: | |
{ | |
hitbox = pInfo.m_iLeftArm; | |
break; | |
} | |
case RIGHT_ARM: | |
{ | |
hitbox = pInfo.m_iRightArm; | |
break; | |
} | |
case LEFT_FOOT: | |
{ | |
hitbox = pInfo.m_iLeftFoot; | |
break; | |
} | |
case RIGHT_FOOT: | |
{ | |
hitbox = pInfo.m_iRightFoot; | |
break; | |
} | |
} | |
// Obtenemos la posición del Hueso | |
box = set->pHitbox( hitbox ); | |
pEntity->GetBonePosition( box->bone, vecPosition, angles ); | |
vecPosition.z -= 5; | |
return true; | |
} | |
BodyInfo_t CBot::GetBodyInfo( CBaseEntity *pEntity ) | |
{ | |
BodyInfo_t pSurvivor; | |
pSurvivor.m_iHeadBone = 1; | |
pSurvivor.m_iGust = 2; | |
pSurvivor.m_iLeftArm = 4; | |
pSurvivor.m_iRightArm = 5; | |
pSurvivor.m_iLeftFoot = 6; | |
pSurvivor.m_iRightFoot = 7; | |
BodyInfo_t pInfected; | |
pInfected.m_iHeadBone = 10; | |
pInfected.m_iGust = 8; | |
pInfected.m_iLeftArm = 11; | |
pInfected.m_iRightArm = 14; | |
pInfected.m_iLeftFoot = 1; | |
pInfected.m_iRightFoot = 7; | |
return pInfected; | |
} | |
BodyPart CBot::GetBodyPartToAim( CBaseEntity *pEntity ) | |
{ | |
if ( !pEntity ) | |
pEntity = GetEnemy(); | |
CBaseAnimating *pAnimEntity = dynamic_cast<CBaseAnimating *>( pEntity ); | |
// No es una entidad válida | |
if ( !pAnimEntity ) | |
return FEET; | |
CBaseInWeapon *pWeapon = Owner()->GetActiveInWeapon(); | |
// ¡No tiene arma! | |
if ( !pWeapon ) | |
return FEET; | |
BodyPart part = FEET; | |
switch ( m_iSkill ) | |
{ | |
case BOT_SKILL_EASY: | |
part = (BodyPart)RandomInt(2,6); // LEFT_ARM > FEET | |
break; | |
case BOT_SKILL_NORMAL: | |
part = (BodyPart)RandomInt(1,6); // GUST > FEET | |
break; | |
case BOT_SKILL_HARD: | |
part = (BodyPart)RandomInt(0,5); // HEAD > RIGHT_FOOT | |
break; | |
case BOT_SKILL_ULTRA_HARD: | |
part = (BodyPart)RandomInt(0,1); // HEAD | GUST | |
break; | |
} | |
// Obtenemos la posición de la parte del cuerpo | |
Vector vecPosition; | |
GetBodyPartPosition( pAnimEntity, part, vecPosition ); | |
// Esta parte no es visible | |
if ( !Owner()->FVisible(vecPosition) ) | |
{ | |
// Probamos con cada parte del cuerpo | |
for ( int i = 0; i < LAST_BODY_PART; ++i ) | |
{ | |
vecPosition.Invalidate(); | |
GetBodyPartPosition( pAnimEntity, (BodyPart)i, vecPosition ); | |
if ( Owner()->FVisible(vecPosition) ) | |
return (BodyPart)i; | |
} | |
return FEET; | |
} | |
return part; | |
} | |
void CBot::LookAt( CBaseEntity *pEntity, ActionPriority priority ) | |
{ | |
if ( !pEntity ) | |
priority = PRI_NONE; | |
else | |
{ | |
// Ya estamos mirando a esta entidad | |
if ( pEntity == m_pLookAt.Get() ) | |
return; | |
} | |
// Estamos mirando otra cosa con mayor prioridad | |
if ( m_iLookPriority > priority && pEntity ) | |
return; | |
m_pLookAt = pEntity; | |
m_iLookPriority = priority; | |
} | |
void CBot::LookAt( const Vector &vecPosition, ActionPriority priority ) | |
{ | |
Vector vecDestination( vecPosition ); | |
vecDestination -= Owner()->EarPosition(); | |
// Transformamos Vector a QAngle | |
QAngle destination; | |
VectorAngles( vecDestination, destination ); | |
// Apuntamos | |
LookAt( destination, priority ); | |
} | |
void CBot::LookAt( const QAngle &lookAt, ActionPriority priority ) | |
{ | |
// Ya estamos mirando a este lugar | |
if ( m_lookAt == lookAt ) | |
return; | |
// Estamos mirando otra cosa con mayor prioridad | |
if ( m_iLookPriority > priority ) | |
return; | |
m_lookAt = lookAt; | |
m_pLookAt = NULL; | |
m_iLookPriority = priority; | |
// Necesitamos apuntar | |
SetNeedAim(); | |
} | |
void CBot::UpdateEntityAim() | |
{ | |
if ( !IsAimingEntity() ) | |
return; | |
CBaseEntity *pEntity = GetAimingEntity(); | |
// Transformamos la entidad a un "CBaseAnimating" | |
CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating *>( pEntity ); | |
Vector vecPosition; | |
if ( pEntity == GetEnemy() && HasCondition(COND_BOT_LOST_ENEMY) ) | |
{ | |
if ( !GetLastEnemyPosition( vecPosition, pEntity ) ) | |
{ | |
LookAt( NULL ); | |
return; | |
} | |
} | |
else if ( pAnimating ) | |
{ | |
GetBodyPartPosition( pAnimating, GetBodyPartToAim(pAnimating), vecPosition ); | |
} | |
else | |
{ | |
GetAimCenter( pEntity, vecPosition ); | |
} | |
Vector vecDestination( vecPosition ); | |
vecDestination -= Owner()->EarPosition(); | |
// Transformamos Vector a QAngle | |
VectorAngles( vecDestination, m_lookAt ); | |
// Necesitamos apuntar | |
SetNeedAim(); | |
} | |
void CBot::UpdateAim() | |
{ | |
// Estamos apuntando a una entidad | |
if ( IsAimingEntity() ) | |
UpdateEntityAim(); | |
// Estamos apuntando al lugar deseado | |
if ( m_lookAt == GetLastUserCommand()->viewangles ) | |
return; | |
QAngle lookAt( m_lookAt ); | |
// Es necesario simular el movimiento de mouse al apuntar | |
if ( m_bNeedAim ) | |
{ | |
// Obtenemos los frames que faltan para terminar de apuntar | |
float timeLeft = m_flEndAimTime - gpGlobals->curtime; | |
int framesLeft = (int)( 60.0f * timeLeft ); | |
// Aún faltan frames, apuntamos poco a poco... (humanamente) | |
if ( framesLeft > 0 ) | |
{ | |
Utils::GetAngleDifference( m_nCmd.viewangles, lookAt, lookAt ); | |
lookAt /= framesLeft; | |
m_nCmd.viewangles += lookAt; | |
} | |
else | |
{ | |
// Hemos terminado de apuntar | |
m_bNeedAim = false; | |
} | |
} | |
Utils::DeNormalizeAngle( m_nCmd.viewangles.x ); | |
Utils::DeNormalizeAngle( m_nCmd.viewangles.y ); | |
} | |
void CBot::SetNeedAim() | |
{ | |
if ( m_bNeedAim ) | |
return; | |
m_bNeedAim = true; | |
m_flEndAimTime = gpGlobals->curtime + GetEndAimTime(); | |
} | |
void CBot::UpdateLookAt() | |
{ | |
// Miramos al enemigo | |
if ( GetEnemy() ) | |
{ | |
LookAt( GetEnemy() ); | |
return; | |
} | |
// Miramos el destino | |
if ( HasGoal() ) | |
{ | |
LookAt( m_pNavPath.GetEndpoint() ); | |
return; | |
} | |
if ( RandomInt(0,10) == 1 ) | |
{ | |
// Miramos a una ubicación al azar | |
float angleDelta = RandomInt( -180, 180 ); | |
QAngle angle = Owner()->GetLocalAngles(); | |
angle.x = RandomInt( -30, 30 ); | |
angle.z = m_nCmd.viewangles.z; | |
angle.y = angleDelta; | |
LookAt( angle ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment