void CCycler :: Spawn( ) { InitBoneControllers(); pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_NONE; pev->takedamage = DAMAGE_YES; pev->effects = 0; pev->health = 80000;// no cycler should die pev->yaw_speed = 5; pev->ideal_yaw = pev->angles.y; ChangeYaw( 360 ); m_flFrameRate = 75; m_flGroundSpeed = 0; pev->nextthink += 1.0; ResetSequenceInfo( ); if (pev->sequence != 0 || pev->frame != 0) { m_animate = 0; pev->framerate = 0; } else { m_animate = 1; } }
// [28/7/2012] Added Monster_StepDirection ~hogsy bool Monster_StepDirection(edict_t *ent,float yaw,float dist) { vec3_t move,oldorg; float delta; ent->v.ideal_yaw = yaw; ChangeYaw(ent); yaw *= (float)pMath_PI*2/360; move[0] = (vec_t)cos(yaw)*dist; move[1] = (vec_t)sin(yaw)*dist; move[2] = 0; Math_VectorCopy(ent->v.origin,oldorg); if(Monster_MoveStep(ent,move,false)) { delta = ent->v.angles[YAW]-ent->v.ideal_yaw; if(delta > 45 && delta < 315) Math_VectorCopy(oldorg,ent->v.origin); Engine.LinkEntity(ent,true); return true; } Engine.LinkEntity(ent,true); return false; }
//========================================================= // roach's move function //========================================================= void CRoach :: Move ( float flInterval ) { float flWaypointDist; Vector vecApex; // local move to waypoint. flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length2D(); MakeIdealYaw ( m_Route[ m_iRouteIndex ].vecLocation ); ChangeYaw ( pev->yaw_speed ); UTIL_MakeVectors( pev->angles ); if ( RANDOM_LONG(0,7) == 1 ) { // randomly check for blocked path.(more random load balancing) if ( !WALK_MOVE( ENT(pev), pev->ideal_yaw, 4, WALKMOVE_NORMAL ) ) { // stuck, so just pick a new spot to run off to PickNewDest( m_iMode ); } } WALK_MOVE( ENT(pev), pev->ideal_yaw, m_flGroundSpeed * flInterval, WALKMOVE_NORMAL ); // if the waypoint is closer than step size, then stop after next step (ok for roach to overshoot) if ( flWaypointDist <= m_flGroundSpeed * flInterval ) { // take truncated step and stop SetActivity ( ACT_IDLE ); m_flLastLightLevel = GETENTITYILLUM( ENT ( pev ) );// this is roach's new comfortable light level if ( m_iMode == ROACH_SMELL_FOOD ) { m_iMode = ROACH_EAT; } else { m_iMode = ROACH_IDLE; } } if ( RANDOM_LONG(0,149) == 1 && m_iMode != ROACH_SCARED_BY_LIGHT && m_iMode != ROACH_SMELL_FOOD ) { // random skitter while moving as long as not on a b-line to get out of light or going to food PickNewDest( FALSE ); } }
//========================================================= // RunTask //========================================================= void CHAssassin :: RunTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_ASSASSIN_FALL_TO_GROUND: MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); if (m_fSequenceFinished) { if (pev->velocity.z > 0) { pev->sequence = LookupSequence( "fly_up" ); } else if (HasConditions ( bits_COND_SEE_ENEMY )) { pev->sequence = LookupSequence( "fly_attack" ); pev->frame = 0; } else { pev->sequence = LookupSequence( "fly_down" ); pev->frame = 0; } ResetSequenceInfo( ); SetYawSpeed(); } if (pev->flags & FL_ONGROUND) { // ALERT( at_console, "on ground\n"); TaskComplete( ); } break; default: CBaseMonster :: RunTask ( pTask ); break; } }
void CCycler :: Spawn( ) { InitBoneControllers(); pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_NONE; pev->takedamage = DAMAGE_YES; pev->effects = 0; pev->health = 80000;// no cycler should die pev->yaw_speed = 5; pev->ideal_yaw = pev->angles.y; ChangeYaw( 360 ); m_flFrameRate = 75; m_flGroundSpeed = 0; pev->nextthink += 1.0; ResetSequenceInfo( ); if (pev->sequence != 0 || pev->frame != 0) { m_animate = 0; pev->framerate = 0; } else { m_animate = 1; } if ( FClassnameIs ( pev, "cine_entity" ) ) { m_bloodColor = DONT_BLEED; pev->origin.z += 1; DROP_TO_FLOOR ( ENT(pev) ); } }
//========================================================= // RunTask //========================================================= void CBullsquid :: RunTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_SQUID_HOPTURN: { MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); if ( m_fSequenceFinished ) { m_iTaskStatus = TASKSTATUS_COMPLETE; } break; } default: { CBaseMonster :: RunTask( pTask ); break; } } }
void CTentacle :: DieThink( void ) { pev->nextthink = gpGlobals-> time + 0.1; DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( 24 ); if (m_fSequenceFinished) { if (pev->sequence == m_iGoalAnim) { switch( m_iGoalAnim ) { case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: m_iGoalAnim = TENTACLE_ANIM_Engine_Sway + RANDOM_LONG( 0, 2 ); break; case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: UTIL_Remove( this ); return; } } // ALERT( at_console, "%d : %d => ", pev->sequence, m_iGoalAnim ); pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); // ALERT( at_console, "%d\n", pev->sequence ); if (m_iDir > 0) { pev->frame = 0; } else { pev->frame = 255; } ResetSequenceInfo( ); float dy; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: case TENTACLE_ANIM_Engine_Idle: case TENTACLE_ANIM_Engine_Sway: case TENTACLE_ANIM_Engine_Swat: case TENTACLE_ANIM_Engine_Bob: case TENTACLE_ANIM_Engine_Death1: case TENTACLE_ANIM_Engine_Death2: case TENTACLE_ANIM_Engine_Death3: pev->framerate = RANDOM_FLOAT( m_iDir - 0.2, m_iDir + 0.2 ); dy = 180; break; default: pev->framerate = 1.5; dy = 0; break; } pev->ideal_yaw = m_flInitialYaw + dy; } }
// // TentacleThink // void CTentacle :: Cycle( void ) { // ALERT( at_console, "%s %.2f %d %d\n", STRING( pev->targetname ), pev->origin.z, m_MonsterState, m_IdealMonsterState ); pev->nextthink = gpGlobals-> time + 0.1; // ALERT( at_console, "%s %d %d %d %f %f\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim, m_iDir, pev->framerate, pev->health ); if (m_MonsterState == MONSTERSTATE_SCRIPT || m_IdealMonsterState == MONSTERSTATE_SCRIPT) { pev->angles.y = m_flInitialYaw; pev->ideal_yaw = m_flInitialYaw; ClearConditions( IgnoreConditions() ); MonsterThink( ); m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; return; } DispatchAnimEvents( ); StudioFrameAdvance( ); ChangeYaw( pev->yaw_speed ); CSound *pSound; Listen( ); // Listen will set this if there's something in my sound list if ( HasConditions( bits_COND_HEAR_SOUND ) ) pSound = PBestSound(); else pSound = NULL; if ( pSound ) { Vector vecDir; if (gpGlobals->time - m_flPrevSoundTime < 0.5) { float dt = gpGlobals->time - m_flPrevSoundTime; vecDir = pSound->m_vecOrigin + (pSound->m_vecOrigin - m_vecPrevSound) / dt - pev->origin; } else { vecDir = pSound->m_vecOrigin - pev->origin; } m_flPrevSoundTime = gpGlobals->time; m_vecPrevSound = pSound->m_vecOrigin; m_flSoundYaw = UTIL_VecToYaw ( vecDir ) - m_flInitialYaw; m_iSoundLevel = Level( vecDir.z ); if (m_flSoundYaw < -180) m_flSoundYaw += 360; if (m_flSoundYaw > 180) m_flSoundYaw -= 360; // ALERT( at_console, "sound %d %.0f\n", m_iSoundLevel, m_flSoundYaw ); if (m_flSoundTime < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_alert1.wav"; break; case 1: sound = "tentacle/te_alert2.wav"; break; } // UTIL_EmitAmbientSound(ENT(pev), pev->origin + Vector( 0, 0, MyHeight()), sound, 1.0, ATTN_NORM, 0, 100); } m_flSoundTime = gpGlobals->time + RANDOM_FLOAT( 5.0, 10.0 ); } // clip ideal_yaw float dy = m_flSoundYaw; switch( pev->sequence ) { case TENTACLE_ANIM_Floor_Rear: case TENTACLE_ANIM_Floor_Rear_Idle: case TENTACLE_ANIM_Lev1_Rear: case TENTACLE_ANIM_Lev1_Rear_Idle: case TENTACLE_ANIM_Lev2_Rear: case TENTACLE_ANIM_Lev2_Rear_Idle: case TENTACLE_ANIM_Lev3_Rear: case TENTACLE_ANIM_Lev3_Rear_Idle: if (dy < 0 && dy > -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > 0 && dy < m_flMaxYaw) dy = m_flMaxYaw; break; default: if (dy < -m_flMaxYaw) dy = -m_flMaxYaw; if (dy > m_flMaxYaw) dy = m_flMaxYaw; } pev->ideal_yaw = m_flInitialYaw + dy; if (m_fSequenceFinished) { // ALERT( at_console, "%s done %d %d\n", STRING( pev->targetname ), pev->sequence, m_iGoalAnim ); if (pev->health <= 1) { m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { pev->health = 75; } } else if ( m_flSoundTime > gpGlobals->time ) { if (m_flSoundYaw >= -(m_flMaxYaw + 30) && m_flSoundYaw <= (m_flMaxYaw + 30)) { // strike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else if (m_flSoundYaw >= -m_flMaxYaw * 2 && m_flSoundYaw <= m_flMaxYaw * 2) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } else { // go into rear idle m_iGoalAnim = LookupActivity( ACT_T_REARIDLE + m_iSoundLevel ); } } else if (pev->sequence == TENTACLE_ANIM_Pit_Idle) { // stay in pit until hear noise m_iGoalAnim = TENTACLE_ANIM_Pit_Idle; } else if (pev->sequence == m_iGoalAnim) { if (MyLevel() >= 0 && gpGlobals->time < m_flSoundTime) { if (RANDOM_LONG(0,9) < m_flSoundTime - gpGlobals->time) { // continue stike m_iGoalAnim = LookupActivity( ACT_T_STRIKE + m_iSoundLevel ); } else { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + m_iSoundLevel ); } } else if (MyLevel( ) < 0) { m_iGoalAnim = LookupActivity( ACT_T_IDLE + 0 ); } else { if (m_flNextSong < gpGlobals->time) { // play "I hear new something" sound char *sound; switch( RANDOM_LONG(0,1) ) { case 0: sound = "tentacle/te_sing1.wav"; break; case 1: sound = "tentacle/te_sing2.wav"; break; } EMIT_SOUND(ENT(pev), CHAN_VOICE, sound, 1.0, ATTN_NORM); m_flNextSong = gpGlobals->time + RANDOM_FLOAT( 10, 20 ); } if (RANDOM_LONG(0,15) == 0) { // idle on new level m_iGoalAnim = LookupActivity( ACT_T_IDLE + RANDOM_LONG(0,3) ); } else if (RANDOM_LONG(0,3) == 0) { // tap m_iGoalAnim = LookupActivity( ACT_T_TAP + MyLevel( ) ); } else { // idle m_iGoalAnim = LookupActivity( ACT_T_IDLE + MyLevel( ) ); } } if (m_flSoundYaw < 0) m_flSoundYaw += RANDOM_FLOAT( 2, 8 ); else m_flSoundYaw -= RANDOM_FLOAT( 2, 8 ); } pev->sequence = FindTransition( pev->sequence, m_iGoalAnim, &m_iDir ); if (m_iDir > 0) { pev->frame = 0; } else { m_iDir = -1; // just to safe pev->frame = 255; } ResetSequenceInfo( ); m_flFramerateAdj = RANDOM_FLOAT( -0.2, 0.2 ); pev->framerate = m_iDir * 1.0 + m_flFramerateAdj; switch( pev->sequence) { case TENTACLE_ANIM_Floor_Tap: case TENTACLE_ANIM_Lev1_Tap: case TENTACLE_ANIM_Lev2_Tap: case TENTACLE_ANIM_Lev3_Tap: { Vector vecSrc; UTIL_MakeVectors( pev->angles ); TraceResult tr1, tr2; vecSrc = pev->origin + Vector( 0, 0, MyHeight() - 4); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr1 ); vecSrc = pev->origin + Vector( 0, 0, MyHeight() + 8); UTIL_TraceLine( vecSrc, vecSrc + gpGlobals->v_forward * 512, ignore_monsters, ENT( pev ), &tr2 ); // ALERT( at_console, "%f %f\n", tr1.flFraction * 512, tr2.flFraction * 512 ); m_flTapRadius = SetBlending( 0, RANDOM_FLOAT( tr1.flFraction * 512, tr2.flFraction * 512 ) ); } break; default: m_flTapRadius = 336; // 400 - 64 break; } pev->view_ofs.z = MyHeight( ); // ALERT( at_console, "seq %d\n", pev->sequence ); } if (m_flPrevSoundTime + 2.0 > gpGlobals->time) { // 1.5 normal speed if hears sounds pev->framerate = m_iDir * 1.5 + m_flFramerateAdj; } else if (m_flPrevSoundTime + 5.0 > gpGlobals->time) { // slowdown to normal pev->framerate = m_iDir + m_iDir * (5 - (gpGlobals->time - m_flPrevSoundTime)) / 2 + m_flFramerateAdj; } }
//========================================================= // RunTask //========================================================= void CHoundeye :: RunTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_HOUND_THREAT_DISPLAY: { MakeIdealYaw ( m_vecEnemyLKP ); ChangeYaw ( pev->yaw_speed ); if ( m_fSequenceFinished ) { TaskComplete(); } break; } case TASK_HOUND_CLOSE_EYE: { if ( pev->skin < HOUNDEYE_EYE_FRAMES - 1 ) { pev->skin++; } break; } case TASK_HOUND_HOP_BACK: { if ( m_fSequenceFinished ) { TaskComplete(); } break; } case TASK_SPECIAL_ATTACK1: { pev->skin = RANDOM_LONG(0, HOUNDEYE_EYE_FRAMES - 1); MakeIdealYaw ( m_vecEnemyLKP ); ChangeYaw ( pev->yaw_speed ); float life; life = ((255 - pev->frame) / (pev->framerate * m_flFrameRate)); if (life < 0.1) life = 0.1; MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); WRITE_BYTE( TE_IMPLOSION); WRITE_COORD( pev->origin.x); WRITE_COORD( pev->origin.y); WRITE_COORD( pev->origin.z + 16); WRITE_BYTE( 50 * life + 100); // radius WRITE_BYTE( pev->frame / 25.0 ); // count WRITE_BYTE( life * 10 ); // life MESSAGE_END(); if ( m_fSequenceFinished ) { SonicAttack(); TaskComplete(); } break; } default: { CSquadMonster :: RunTask(pTask); break; } } }
//========================================================= // RunTask //========================================================= void CController :: RunTask ( Task_t *pTask ) { if (m_flShootEnd > gpGlobals->time) { Vector vecHand, vecAngle; GetAttachment( 2, vecHand, vecAngle ); while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->time) { Vector vecSrc = vecHand + pev->velocity * (m_flShootTime - gpGlobals->time); Vector vecDir; if (m_pCine != NULL || m_hEnemy != NULL) { if (m_pCine != NULL) // LRC- is this a script that's telling it to fire? { if (m_hTargetEnt != NULL && m_pCine->PreciseAttack()) { vecDir = (m_hTargetEnt->pev->origin - pev->origin).Normalize() * gSkillData.controllerSpeedBall; } else { UTIL_MakeVectors(pev->angles); vecDir = gpGlobals->v_forward * gSkillData.controllerSpeedBall; } } else if (m_hEnemy != NULL) { if (HasConditions( bits_COND_SEE_ENEMY )) { m_vecEstVelocity = m_vecEstVelocity * 0.5 + m_hEnemy->pev->velocity * 0.5; } else { m_vecEstVelocity = m_vecEstVelocity * 0.8; } vecDir = Intersect( vecSrc, m_hEnemy->BodyTarget( pev->origin ), m_vecEstVelocity, gSkillData.controllerSpeedBall ); } float delta = 0.03490; // +-2 degree vecDir = vecDir + Vector( RANDOM_FLOAT( -delta, delta ), RANDOM_FLOAT( -delta, delta ), RANDOM_FLOAT( -delta, delta ) ) * gSkillData.controllerSpeedBall; vecSrc = vecSrc + vecDir * (gpGlobals->time - m_flShootTime); CBaseMonster *pBall = (CBaseMonster*)Create( "controller_energy_ball", vecSrc, pev->angles, edict() ); pBall->pev->velocity = vecDir; } m_flShootTime += 0.2; } if (m_flShootTime > m_flShootEnd) { m_iBall[0] = 64; m_iBallTime[0] = m_flShootEnd; m_iBall[1] = 64; m_iBallTime[1] = m_flShootEnd; m_fInCombat = FALSE; } } switch ( pTask->iTask ) { case TASK_WAIT_FOR_MOVEMENT: case TASK_WAIT: case TASK_WAIT_FACE_ENEMY: case TASK_WAIT_PVS: MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); if (m_fSequenceFinished) { m_fInCombat = FALSE; } CSquadMonster :: RunTask ( pTask ); if (!m_fInCombat) { if (HasConditions ( bits_COND_CAN_RANGE_ATTACK1 )) { pev->sequence = LookupActivity( ACT_RANGE_ATTACK1 ); pev->frame = 0; ResetSequenceInfo( ); m_fInCombat = TRUE; } else if (HasConditions ( bits_COND_CAN_RANGE_ATTACK2 )) { pev->sequence = LookupActivity( ACT_RANGE_ATTACK2 ); pev->frame = 0; ResetSequenceInfo( ); m_fInCombat = TRUE; } else { int iFloat = LookupFloat( ); if (m_fSequenceFinished || iFloat != pev->sequence) { pev->sequence = iFloat; pev->frame = 0; ResetSequenceInfo( ); } } } break; default: CSquadMonster :: RunTask ( pTask ); break; } }
//========================================================= // RunTask //========================================================= void CBaseMonster :: RunTask ( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_TURN_RIGHT: case TASK_TURN_LEFT: { ChangeYaw( pev->yaw_speed ); if ( FacingIdeal() ) { TaskComplete(); } break; } case TASK_PLAY_SEQUENCE_FACE_ENEMY: case TASK_PLAY_SEQUENCE_FACE_TARGET: { CBaseEntity *pTarget; if ( pTask->iTask == TASK_PLAY_SEQUENCE_FACE_TARGET ) pTarget = m_hTargetEnt; else pTarget = m_hEnemy; if ( pTarget ) { pev->ideal_yaw = UTIL_VecToYaw( pTarget->pev->origin - pev->origin ); ChangeYaw( pev->yaw_speed ); } if ( m_fSequenceFinished ) TaskComplete(); } break; case TASK_PLAY_SEQUENCE: case TASK_PLAY_ACTIVE_IDLE: { if ( m_fSequenceFinished ) { TaskComplete(); } break; } case TASK_FACE_ENEMY: { MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); if ( FacingIdeal() ) { TaskComplete(); } break; } case TASK_FACE_HINTNODE: case TASK_FACE_LASTPOSITION: case TASK_FACE_TARGET: case TASK_FACE_IDEAL: case TASK_FACE_ROUTE: { ChangeYaw( pev->yaw_speed ); if ( FacingIdeal() ) { TaskComplete(); } break; } case TASK_WAIT_PVS: { if ( !FNullEnt(FIND_CLIENT_IN_PVS(edict())) ) { TaskComplete(); } break; } case TASK_WAIT_INDEFINITE: { // don't do anything. break; } case TASK_WAIT: case TASK_WAIT_RANDOM: { if ( gpGlobals->time >= m_flWaitFinished ) { TaskComplete(); } break; } case TASK_WAIT_FACE_ENEMY: { MakeIdealYaw ( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); if ( gpGlobals->time >= m_flWaitFinished ) { TaskComplete(); } break; } case TASK_MOVE_TO_TARGET_RANGE: { float distance; if ( m_hTargetEnt == NULL ) TaskFail(); else { distance = ( m_vecMoveGoal - pev->origin ).Length2D(); // Re-evaluate when you think your finished, or the target has moved too far if ( (distance < pTask->flData) || (m_vecMoveGoal - m_hTargetEnt->pev->origin).Length() > pTask->flData * 0.5 ) { m_vecMoveGoal = m_hTargetEnt->pev->origin; distance = ( m_vecMoveGoal - pev->origin ).Length2D(); FRefreshRoute(); } // Set the appropriate activity based on an overlapping range // overlap the range to prevent oscillation if ( distance < pTask->flData ) { TaskComplete(); RouteClear(); // Stop moving } else if ( distance < 190 && m_movementActivity != ACT_WALK ) m_movementActivity = ACT_WALK; else if ( distance >= 270 && m_movementActivity != ACT_RUN ) m_movementActivity = ACT_RUN; } break; } case TASK_WAIT_FOR_MOVEMENT: { if (MovementIsComplete()) { TaskComplete(); RouteClear(); // Stop moving } break; } case TASK_DIE: { if ( m_fSequenceFinished && pev->frame >= 255 ) { pev->deadflag = DEAD_DEAD; SetThink ( NULL ); StopAnimation(); if ( !BBoxFlat() ) { // a bit of a hack. If a corpses' bbox is positioned such that being left solid so that it can be attacked will // block the player on a slope or stairs, the corpse is made nonsolid. // pev->solid = SOLID_NOT; UTIL_SetSize ( pev, Vector ( -4, -4, 0 ), Vector ( 4, 4, 1 ) ); } else // !!!HACKHACK - put monster in a thin, wide bounding box until we fix the solid type/bounding volume problem UTIL_SetSize ( pev, Vector ( pev->mins.x, pev->mins.y, pev->mins.z ), Vector ( pev->maxs.x, pev->maxs.y, pev->mins.z + 1 ) ); if ( ShouldFadeOnDeath() ) { // this monster was created by a monstermaker... fade the corpse out. SUB_StartFadeOut(); } else { // body is gonna be around for a while, so have it stink for a bit. CSoundEnt::InsertSound ( bits_SOUND_CARCASS, pev->origin, 384, 30 ); } } break; } case TASK_RANGE_ATTACK1_NOTURN: case TASK_MELEE_ATTACK1_NOTURN: case TASK_MELEE_ATTACK2_NOTURN: case TASK_RANGE_ATTACK2_NOTURN: case TASK_RELOAD_NOTURN: { if ( m_fSequenceFinished ) { m_Activity = ACT_RESET; TaskComplete(); } break; } case TASK_RANGE_ATTACK1: case TASK_MELEE_ATTACK1: case TASK_MELEE_ATTACK2: case TASK_RANGE_ATTACK2: case TASK_SPECIAL_ATTACK1: case TASK_SPECIAL_ATTACK2: case TASK_RELOAD: { MakeIdealYaw ( m_vecEnemyLKP ); ChangeYaw ( pev->yaw_speed ); if ( m_fSequenceFinished ) { m_Activity = ACT_RESET; TaskComplete(); } break; } case TASK_SMALL_FLINCH: { if ( m_fSequenceFinished ) { TaskComplete(); } } break; case TASK_WAIT_FOR_SCRIPT: { if ( m_pCine->m_iDelay <= 0 && gpGlobals->time >= m_pCine->m_startTime ) { TaskComplete(); } break; } case TASK_PLAY_SCRIPT: { // ALERT(at_console, "Play Script\n"); if (m_fSequenceFinished) { // ALERT(at_console, "Anim Finished\n"); if (m_pCine->m_iRepeatsLeft > 0) { // ALERT(at_console, "Frame %f; Repeat %d from %f\n", pev->frame, m_pCine->m_iRepeatsLeft, m_pCine->m_fRepeatFrame); m_pCine->m_iRepeatsLeft--; pev->frame = m_pCine->m_fRepeatFrame; ResetSequenceInfo( ); } else { TaskComplete(); } } break; } } }
//========================================================= // RunTask //========================================================= void CLuciole :: RunTask ( Task_t *pTask ) { // petite loupiote MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, Center() ); WRITE_BYTE(TE_DLIGHT); WRITE_COORD(Center().x); // X WRITE_COORD(Center().y); // Y WRITE_COORD(Center().z); // Z WRITE_BYTE( 7 ); // radius * 0.1 WRITE_BYTE( 150 ); // r WRITE_BYTE( 71 ); // g WRITE_BYTE( 245 ); // b WRITE_BYTE( 3 ); // time * 10 WRITE_BYTE( 0 ); // decay * 0.1 MESSAGE_END( ); // position de tir if ( m_hEnemy != NULL && (Center()-m_hEnemy->Center()).Length() < ATTACK_DIST && gpGlobals->time - m_flLastAttack > ATTACK_DELAY ) { m_flLastAttack = gpGlobals->time; EMIT_SOUND ( edict(), CHAN_ITEM, "debris/beamstart14.wav", 1.0, ATTN_NORM ); for ( int i=0; i<3; i++ ) { CBeam *pBeam = CBeam::BeamCreate( "sprites/laserbeam.spr", 2 ); if ( RANDOM_LONG(0,1) ) pBeam->SetColor( 206,118, 254 ); else pBeam->SetColor( 223,224, 255 ); pBeam->SetBrightness( 192 ); pBeam->PointEntInit( m_hEnemy->Center(), entindex( ) ); pBeam->SetEndAttachment( 0 ); pBeam->RelinkBeam( ); pBeam->SetNoise ( 30 ); pBeam->LiveForTime ( 0.4 ); m_hEnemy->TakeDamage ( pev, pev, gSkillData.LucioleDamage, DMG_SHOCK ); } return; } MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( pev->yaw_speed ); // run task classique switch ( pTask->iTask ) { case TASK_FLYBEE_WAIT_FOR_MOVEMENT: { if (MovementIsComplete()) { TaskComplete(); RouteClear(); // Stop moving } break; } case TASK_LUCIOLE_GET_PATH: { // considère l'objectif atteint à 10 units de distance BOOL bFinDeRoute = FALSE; if ( (pev->origin-m_vecRoute).Length() < 10 ) { bFinDeRoute = TRUE; } // actualise la position ennemie if ( m_hEnemy == NULL ) { TaskComplete (); break; } Vector vecEnemy = m_hEnemy->Center(); // vérifie la visibilité du joueur TraceResult tr; UTIL_TraceLine ( pev->origin, vecEnemy, dont_ignore_monsters, dont_ignore_glass, edict(), &tr ); if ( tr.flFraction == 1.0 || FClassnameIs(tr.pHit, "player") ) { // champ libre jusqu'au joueur m_vecRoute = vecEnemy; m_iMouchard = MOUCHARD_OFF; } // joueur invisible else { // trajectoire non finie - on continue if ( bFinDeRoute == FALSE ) { // active le mouchard if ( m_iMouchard == MOUCHARD_OFF ) { m_iMouchard = MOUCHARD_LANCEMENT; m_vecMouchard1 = m_vecRoute; } } // pas de trajectoire définie else { // tente d'utiliser le mouchard TraceResult trMouchard; UTIL_TraceLine ( pev->origin, m_vecMouchard2, dont_ignore_monsters, dont_ignore_glass, edict(), &trMouchard ); if ( m_iMouchard == MOUCHARD_ON && ( trMouchard.flFraction == 1.0 || FClassnameIs(trMouchard.pHit, "player") ) ) { // c parti m_vecRoute = m_vecMouchard2; // mouchard obsolète, on en relance un nouveau m_iMouchard = MOUCHARD_LANCEMENT; } else { TraceResult trTete; UTIL_TraceLine ( pev->origin, m_hEnemy->pev->view_ofs, dont_ignore_monsters, dont_ignore_glass, edict(), &trTete ); TraceResult trPieds; UTIL_TraceLine ( pev->origin, m_hEnemy->pev->origin, dont_ignore_monsters, dont_ignore_glass, edict(), &trPieds ); if ( trTete.flFraction == 1.0 || FClassnameIs(trTete.pHit, "player") ) { // champ libre jusqu'au joueur m_vecRoute = m_hEnemy->pev->view_ofs; } else if ( trPieds.flFraction == 1.0 || FClassnameIs(trPieds.pHit, "player") ) { // champ libre jusqu'au joueur m_vecRoute = m_hEnemy->pev->origin; } // ennemi totalement invisible else { // bloqué par de petits obstacles - on tente de monter ou descendre un peu TraceResult trEvite [2]; UTIL_MakeVectors ( pev->angles ); int ordre [4]; switch ( RANDOM_LONG(0,3) ) { case 0: ordre[0] = 0; ordre[1] = 1; ordre[2] = 2; ordre[3] = 3; break; case 1: ordre[0] = 0; ordre[1] = 3; ordre[2] = 2; ordre[3] = 1; break; case 2: ordre[0] = 2; ordre[1] = 3; ordre[2] = 0; ordre[3] = 1; break; case 3: ordre[0] = 3; ordre[1] = 1; ordre[2] = 0; ordre[3] = 2; break; } UTIL_TraceLine ( pev->origin, pev->origin + Vector (0,0,RANDOM_FLOAT(40,60)), dont_ignore_monsters, dont_ignore_glass, edict(), &trEvite[ordre[0]] ); UTIL_TraceLine ( pev->origin, pev->origin - Vector (0,0,RANDOM_FLOAT(40,60)), dont_ignore_monsters, dont_ignore_glass, edict(), &trEvite[ordre[1]] ); UTIL_TraceLine ( pev->origin, pev->origin + gpGlobals->v_right * RANDOM_FLOAT(40,60), dont_ignore_monsters, dont_ignore_glass, edict(), &trEvite[ordre[2]] ); UTIL_TraceLine ( pev->origin, pev->origin - gpGlobals->v_right * RANDOM_FLOAT(40,60), dont_ignore_monsters, dont_ignore_glass, edict(), &trEvite[ordre[3]] ); for ( int i=0; i<4; i++ ) { if ( trEvite[i].flFraction >= 0.5 ) m_vecRoute = trEvite[i].vecEndPos - (trEvite[i].vecEndPos-pev->origin).Normalize() * 5; break; } } } } } // actualise le mouchard if ( m_iMouchard != MOUCHARD_OFF ) { if ( m_iMouchard == MOUCHARD_LANCEMENT ) { m_vecMouchard2 = m_vecMouchard1; } // vérifie si le joueur est visible depuis sa dernière position connue TraceResult trMouchard; UTIL_TraceLine ( m_vecMouchard1, vecEnemy, dont_ignore_monsters, dont_ignore_glass, edict(), &trMouchard ); if ( trMouchard.flFraction == 1.0 || FClassnameIs(trMouchard.pHit, "player") ) { m_vecMouchard2 = vecEnemy; m_iMouchard = MOUCHARD_ON; } } // trajectoire établie - application des vitesses float flDot = DotProduct ( pev->velocity.Normalize(), (m_vecRoute-pev->origin).Normalize() ); float flRatio = 0.6 + (flDot+1)*0.6; float speed = pev->velocity.Length() * flRatio; speed = max ( 100, speed ); speed = min ( speed, 250 ); pev->velocity = (m_vecRoute - pev->origin).Normalize() * speed; break; } default: CBaseMonster :: RunTask ( pTask ); break; } }
void CTalkMonster :: RunTask( const Task_t& task ) { switch( task.iTask ) { case TASK_TLK_CLIENT_STARE: case TASK_TLK_LOOK_AT_CLIENT: { edict_t *pPlayer; // track head to the client for a while. if( m_MonsterState == MONSTERSTATE_IDLE && !IsMoving() && !IsTalking() ) { // Get edict for one player pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if( pPlayer ) { IdleHeadTurn( pPlayer->v.origin ); } } else { // started moving or talking TaskFail(); return; } if( pPlayer ) { if( task.iTask == TASK_TLK_CLIENT_STARE ) { // fail out if the player looks away or moves away. if( ( pPlayer->v.origin - GetAbsOrigin() ).Length2D() > TLK_STARE_DIST ) { // player moved away. TaskFail(); } UTIL_MakeVectors( pPlayer->v.angles ); if( UTIL_DotPoints( pPlayer->v.origin, GetAbsOrigin(), gpGlobals->v_forward ) < m_flFieldOfView ) { // player looked away TaskFail(); } } } else { TaskFail(); } if( gpGlobals->time > m_flWaitFinished ) { TaskComplete(); } break; } case TASK_FACE_PLAYER: { // Get edict for one player edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if( pPlayer ) { MakeIdealYaw( pPlayer->v.origin ); ChangeYaw( GetYawSpeed() ); IdleHeadTurn( pPlayer->v.origin ); if( gpGlobals->time > m_flWaitFinished && FlYawDiff() < 10 ) { TaskComplete(); } } else { TaskFail(); } break; } case TASK_TLK_EYECONTACT: { if( !IsMoving() && IsTalking() && m_hTalkTarget != NULL ) { // ALERT( at_console, "waiting %f\n", m_flStopTalkTime - gpGlobals->time ); IdleHeadTurn( m_hTalkTarget->GetAbsOrigin() ); } else { TaskComplete(); } break; } case TASK_WALK_PATH_FOR_UNITS: { float distance; distance = (m_vecLastPosition - GetAbsOrigin()).Length2D(); // Walk path until far enough away if ( distance > task.flData || MovementIsComplete() ) { TaskComplete(); RouteClear(); // Stop moving } break; } case TASK_WAIT_FOR_MOVEMENT: { if( IsTalking() && m_hTalkTarget != NULL ) { // ALERT(at_console, "walking, talking\n"); IdleHeadTurn( m_hTalkTarget->GetAbsOrigin() ); } else { IdleHeadTurn( GetAbsOrigin() ); // override so that during walk, a scientist may talk and greet player FIdleHello(); if( RANDOM_LONG( 0, m_nSpeak * 20 ) == 0 ) { FIdleSpeak(); } } CBaseMonster::RunTask( task ); if( TaskIsComplete() ) IdleHeadTurn( GetAbsOrigin() ); break; } default: { if( IsTalking() && m_hTalkTarget != NULL ) { IdleHeadTurn( m_hTalkTarget->GetAbsOrigin() ); } else { SetBoneController( 0, 0 ); } CBaseMonster::RunTask( task ); break; } } }
void CScientist :: RunTask( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_RUN_PATH_SCARED: if ( MovementIsComplete() ) TaskComplete(); if ( RANDOM_LONG(0,31) < 8 ) Scream(); break; case TASK_MOVE_TO_TARGET_RANGE_SCARED: { if ( RANDOM_LONG(0,63)< 8 ) Scream(); if ( m_hEnemy == NULL ) { TaskFail(); } else { float distance; distance = ( m_vecMoveGoal - pev->origin ).Length2D(); // Re-evaluate when you think your finished, or the target has moved too far if ( (distance < pTask->flData) || (m_vecMoveGoal - m_hTargetEnt->pev->origin).Length() > pTask->flData * 0.5 ) { m_vecMoveGoal = m_hTargetEnt->pev->origin; distance = ( m_vecMoveGoal - pev->origin ).Length2D(); FRefreshRoute(); } // Set the appropriate activity based on an overlapping range // overlap the range to prevent oscillation if ( distance < pTask->flData ) { TaskComplete(); RouteClear(); // Stop moving } else if ( distance < 190 && m_movementActivity != ACT_WALK_SCARED ) m_movementActivity = ACT_WALK_SCARED; else if ( distance >= 270 && m_movementActivity != ACT_RUN_SCARED ) m_movementActivity = ACT_RUN_SCARED; } } break; case TASK_HEAL: if ( m_fSequenceFinished ) { TaskComplete(); } else { if ( TargetDistance() > 90 ) TaskComplete(); pev->ideal_yaw = UTIL_VecToYaw( m_hTargetEnt->pev->origin - pev->origin ); ChangeYaw( pev->yaw_speed ); } break; default: CTalkMonster::RunTask( pTask ); break; } }
void Bot_Think(edict_t *eBot) { // If the bot isn't dead, then add animations. if(eBot->monster.iState != STATE_DEAD) { if(eBot->v.flags & FL_ONGROUND) { if(( (eBot->v.velocity[0] < -4.0f || eBot->v.velocity[0] > 4.0f) || (eBot->v.velocity[1] < -4.0f || eBot->v.velocity[1] > 4.0f)) && (!eBot->local.dAnimationTime || eBot->local.iAnimationEnd == 9)) Entity_Animate(eBot,PlayerAnimation_Walk); else if((eBot->v.velocity[0] == 0 || eBot->v.velocity[1] == 0) && (!eBot->local.dAnimationTime || eBot->local.iAnimationEnd > 9)) { #ifdef GAME_OPENKATANA if(eBot->v.iActiveWeapon == WEAPON_DAIKATANA) Entity_Animate(eBot,PlayerAnimation_KatanaIdle); else #endif Entity_Animate(eBot,PlayerAnimation_Idle); } } } switch(eBot->monster.iThink) { case THINK_IDLE: #if 1 // Add some random movement. ~hogsy if(rand()%120 == 0) { int iResult = rand()%3; if(iResult == 0) eBot->v.velocity[0] += BOT_MIN_SPEED; else if(iResult == 1) eBot->v.velocity[0] -= BOT_MIN_SPEED; iResult = rand()%3; if(iResult == 0) eBot->v.velocity[1] += BOT_MIN_SPEED; else if(iResult == 1) eBot->v.velocity[1] -= BOT_MIN_SPEED; eBot->v.angles[1] = Math_VectorToYaw(eBot->v.velocity); } else if(rand()%150 == 0) { Monster_Jump(eBot,200.0f); Entity_Animate(eBot,PlayerAnimation_Jump); } #endif break; case THINK_WANDERING: { edict_t *eTarget; Waypoint_t *wPoint; // Weapon_t *wMyWeapon; // vec3_t vAngle; eTarget = Monster_GetTarget(eBot); if(eTarget) { if(Monster_GetRelationship(eBot,eTarget) == RELATIONSHIP_HATE) { // [22/3/2013] Begin attacking next frame ~hogsy Monster_SetThink(eBot,THINK_ATTACKING); return; } } if(!eBot->monster.vTarget) { // [28/7/2012] TODO: Find specific waypoint such as an item ~hogsy wPoint = Waypoint_GetByVisibility(eBot->v.origin); if(wPoint) { if(wPoint->bOpen) { // [22/3/2013] TODO: Tell that current entity it's time to move... ~hogsy } Math_VectorCopy(wPoint->position,eBot->monster.vTarget); } } #if 0 wMyWeapon = Weapon_GetCurrentWeapon(eBot); if(MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > 4000) return; else if(wMyWeapon->iPrimaryType == AM_MELEE && MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > MONSTER_RANGE_MELEE) return; else if(Monster_IsVisible(eBot,eBot->v.enemy)) { // [5/8/2012] No ammo and it's not a melee weapon? ~hogsy if(!Weapon_CheckPrimaryAmmo(eBot) && wMyWeapon->iPrimaryType != AM_MELEE) { // [5/8/2012] Should probably flee ~hogsy Monster_SetThink(eBot,THINK_FLEEING); return; } Math_VectorSubtract(eBot->v.enemy->v.origin,eBot->v.origin,vAngle); // ent->v.ideal_yaw = VectorToAngles(vAngle); ChangeYaw(eBot); } #endif } break; } }
void CController :: RunTask ( const Task_t& task ) { if (m_flShootEnd > gpGlobals->time) { Vector vecHand, vecAngle; GetAttachment( 2, vecHand, vecAngle ); while (m_flShootTime < m_flShootEnd && m_flShootTime < gpGlobals->time) { Vector vecSrc = vecHand + GetAbsVelocity() * (m_flShootTime - gpGlobals->time); Vector vecDir; if (m_hEnemy != NULL) { if (HasConditions( bits_COND_SEE_ENEMY )) { m_vecEstVelocity = m_vecEstVelocity * 0.5 + m_hEnemy->GetAbsVelocity() * 0.5; } else { m_vecEstVelocity = m_vecEstVelocity * 0.8; } vecDir = Intersect( vecSrc, m_hEnemy->BodyTarget( GetAbsOrigin() ), m_vecEstVelocity, gSkillData.GetControllerSpeedBall() ); float delta = 0.03490; // +-2 degree vecDir = vecDir + Vector( RANDOM_FLOAT( -delta, delta ), RANDOM_FLOAT( -delta, delta ), RANDOM_FLOAT( -delta, delta ) ) * gSkillData.GetControllerSpeedBall(); vecSrc = vecSrc + vecDir * (gpGlobals->time - m_flShootTime); CBaseMonster *pBall = (CBaseMonster*)Create( "controller_energy_ball", vecSrc, GetAbsAngles(), edict() ); pBall->SetAbsVelocity( vecDir ); } m_flShootTime += 0.2; } if (m_flShootTime > m_flShootEnd) { m_iBall[0] = 64; m_iBallTime[0] = m_flShootEnd; m_iBall[1] = 64; m_iBallTime[1] = m_flShootEnd; m_fInCombat = false; } } switch ( task.iTask ) { case TASK_WAIT_FOR_MOVEMENT: case TASK_WAIT: case TASK_WAIT_FACE_ENEMY: case TASK_WAIT_PVS: MakeIdealYaw( m_vecEnemyLKP ); ChangeYaw( GetYawSpeed() ); if (m_fSequenceFinished) { m_fInCombat = false; } CSquadMonster :: RunTask ( task ); if (!m_fInCombat) { if (HasConditions ( bits_COND_CAN_RANGE_ATTACK1 )) { SetSequence( LookupActivity( ACT_RANGE_ATTACK1 ) ); SetFrame( 0 ); ResetSequenceInfo( ); m_fInCombat = true; } else if (HasConditions ( bits_COND_CAN_RANGE_ATTACK2 )) { SetSequence( LookupActivity( ACT_RANGE_ATTACK2 ) ); SetFrame( 0 ); ResetSequenceInfo( ); m_fInCombat = true; } else { int iFloat = LookupFloat( ); if (m_fSequenceFinished || iFloat != GetSequence() ) { SetSequence( iFloat ); SetFrame( 0 ); ResetSequenceInfo( ); } } } break; default: CSquadMonster :: RunTask ( task ); break; } }