/*** * * Copyright (c) 1999, Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * This source code contains proprietary and confidential information of * Valve LLC and its suppliers. Access to this code is restricted to * persons who have executed a written SDK license with Valve. Any access, * use or distribution of this code by or to any unlicensed person is illegal. * ****/ //========================================================= // Default behaviors. //========================================================= #include "extdll.h" #include "util.h" #include "cbase.h" #include "monsters.h" #include "schedule.h" #include "defaultai.h" #include "soundent.h" #include "nodes.h" #include "scripted.h" //========================================================= // Fail //========================================================= Task_t tlFail[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT, (float)2 }, { TASK_WAIT_PVS, (float)0 }, }; Schedule_t slFail[] = { { tlFail, ARRAYSIZE ( tlFail ), bits_COND_CAN_ATTACK, 0, "Fail" }, }; //========================================================= // Idle Schedules //========================================================= Task_t tlIdleStand1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT, (float)5 },// repick IDLESTAND every five seconds. gives us a chance to pick an active idle, fidget, etc. }; Schedule_t slIdleStand[] = { { tlIdleStand1, ARRAYSIZE ( tlIdleStand1 ), bits_COND_NEW_ENEMY | bits_COND_SEE_FEAR | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_HEAR_SOUND | bits_COND_SMELL_FOOD | bits_COND_SMELL | bits_COND_PROVOKED, bits_SOUND_COMBAT |// sound flags bits_SOUND_WORLD | bits_SOUND_PLAYER | bits_SOUND_DANGER | bits_SOUND_MEAT |// scents bits_SOUND_CARCASS | bits_SOUND_GARBAGE, "IdleStand" }, }; Schedule_t slIdleTrigger[] = { { tlIdleStand1, ARRAYSIZE ( tlIdleStand1 ), bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE, 0, "Idle Trigger" }, }; Task_t tlIdleWalk1[] = { { TASK_WALK_PATH, (float)9999 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, }; Schedule_t slIdleWalk[] = { { tlIdleWalk1, ARRAYSIZE ( tlIdleWalk1 ), bits_COND_NEW_ENEMY | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_HEAR_SOUND | bits_COND_SMELL_FOOD | bits_COND_SMELL | bits_COND_PROVOKED, bits_SOUND_COMBAT |// sound flags bits_SOUND_MEAT |// scents bits_SOUND_CARCASS | bits_SOUND_GARBAGE, "Idle Walk" }, }; //========================================================= // Ambush - monster stands in place and waits for a new // enemy, or chance to attack an existing enemy. //========================================================= Task_t tlAmbush[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT_INDEFINITE, (float)0 }, }; Schedule_t slAmbush[] = { { tlAmbush, ARRAYSIZE ( tlAmbush ), bits_COND_NEW_ENEMY | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_PROVOKED, 0, "Ambush" }, }; //========================================================= // ActiveIdle schedule - !!!BUGBUG - if this schedule doesn't // complete on its own, the monster's HintNode will not be // cleared, and the rest of the monster's group will avoid // that node because they think the group member that was // previously interrupted is still using that node to active // idle. ///========================================================= Task_t tlActiveIdle[] = { { TASK_FIND_HINTNODE, (float)0 }, { TASK_GET_PATH_TO_HINTNODE, (float)0 }, { TASK_STORE_LASTPOSITION, (float)0 }, { TASK_WALK_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_FACE_HINTNODE, (float)0 }, { TASK_PLAY_ACTIVE_IDLE, (float)0 }, { TASK_GET_PATH_TO_LASTPOSITION,(float)0 }, { TASK_WALK_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_CLEAR_LASTPOSITION, (float)0 }, { TASK_CLEAR_HINTNODE, (float)0 }, }; Schedule_t slActiveIdle[] = { { tlActiveIdle, ARRAYSIZE( tlActiveIdle ), bits_COND_NEW_ENEMY | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_PROVOKED | bits_COND_HEAR_SOUND, bits_SOUND_COMBAT | bits_SOUND_WORLD | bits_SOUND_PLAYER | bits_SOUND_DANGER, "Active Idle" } }; //========================================================= // Wake Schedules //========================================================= Task_t tlWakeAngry1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_SOUND_WAKE, (float)0 }, { TASK_FACE_IDEAL, (float)0 }, }; Schedule_t slWakeAngry[] = { { tlWakeAngry1, ARRAYSIZE ( tlWakeAngry1 ), 0, 0, "Wake Angry" } }; //========================================================= // AlertFace Schedules //========================================================= Task_t tlAlertFace1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_FACE_IDEAL, (float)0 }, }; Schedule_t slAlertFace[] = { { tlAlertFace1, ARRAYSIZE ( tlAlertFace1 ), bits_COND_NEW_ENEMY | bits_COND_SEE_FEAR | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_PROVOKED, 0, "Alert Face" }, }; //========================================================= // AlertSmallFlinch Schedule - shot, but didn't see attacker, // flinch then face //========================================================= Task_t tlAlertSmallFlinch[] = { { TASK_STOP_MOVING, 0 }, { TASK_REMEMBER, (float)bits_MEMORY_FLINCHED }, { TASK_SMALL_FLINCH, (float)0 }, { TASK_SET_SCHEDULE, (float)SCHED_ALERT_FACE }, }; Schedule_t slAlertSmallFlinch[] = { { tlAlertSmallFlinch, ARRAYSIZE ( tlAlertSmallFlinch ), 0, 0, "Alert Small Flinch" }, }; //========================================================= // AlertIdle Schedules //========================================================= Task_t tlAlertStand1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT, (float)20 }, { TASK_SUGGEST_STATE, (float)MONSTERSTATE_IDLE }, }; Schedule_t slAlertStand[] = { { tlAlertStand1, ARRAYSIZE ( tlAlertStand1 ), bits_COND_NEW_ENEMY | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_PROVOKED | bits_COND_SMELL | bits_COND_SMELL_FOOD | bits_COND_HEAR_SOUND, bits_SOUND_COMBAT |// sound flags bits_SOUND_WORLD | bits_SOUND_PLAYER | bits_SOUND_DANGER | bits_SOUND_MEAT |// scent flags bits_SOUND_CARCASS | bits_SOUND_GARBAGE, "Alert Stand" }, }; //========================================================= // InvestigateSound - sends a monster to the location of the // sound that was just heard, to check things out. //========================================================= Task_t tlInvestigateSound[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_STORE_LASTPOSITION, (float)0 }, { TASK_GET_PATH_TO_BESTSOUND, (float)0 }, { TASK_FACE_IDEAL, (float)0 }, { TASK_WALK_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_PLAY_SEQUENCE, (float)ACT_IDLE }, { TASK_WAIT, (float)10 }, { TASK_GET_PATH_TO_LASTPOSITION,(float)0 }, { TASK_WALK_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_CLEAR_LASTPOSITION, (float)0 }, }; Schedule_t slInvestigateSound[] = { { tlInvestigateSound, ARRAYSIZE ( tlInvestigateSound ), bits_COND_NEW_ENEMY | bits_COND_SEE_FEAR | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "InvestigateSound" }, }; //========================================================= // CombatIdle Schedule //========================================================= Task_t tlCombatStand1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT_INDEFINITE, (float)0 }, }; Schedule_t slCombatStand[] = { { tlCombatStand1, ARRAYSIZE ( tlCombatStand1 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_CAN_ATTACK, 0, "Combat Stand" }, }; //========================================================= // CombatFace Schedule //========================================================= Task_t tlCombatFace1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_FACE_ENEMY, (float)0 }, }; Schedule_t slCombatFace[] = { { tlCombatFace1, ARRAYSIZE ( tlCombatFace1 ), bits_COND_CAN_ATTACK | bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD, 0, "Combat Face" }, }; //========================================================= // Standoff schedule. Used in combat when a monster is // hiding in cover or the enemy has moved out of sight. // Should we look around in this schedule? //========================================================= Task_t tlStandoff[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_SET_ACTIVITY, (float)ACT_IDLE }, { TASK_WAIT_FACE_ENEMY, (float)2 }, }; Schedule_t slStandoff[] = { { tlStandoff, ARRAYSIZE ( tlStandoff ), bits_COND_CAN_RANGE_ATTACK1 | bits_COND_CAN_RANGE_ATTACK2 | bits_COND_ENEMY_DEAD | bits_COND_NEW_ENEMY | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Standoff" } }; //========================================================= // Arm weapon (draw gun) //========================================================= Task_t tlArmWeapon[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, (float) ACT_ARM } }; Schedule_t slArmWeapon[] = { { tlArmWeapon, ARRAYSIZE ( tlArmWeapon ), 0, 0, "Arm Weapon" } }; //========================================================= // reload schedule //========================================================= Task_t tlReload[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, float(ACT_RELOAD) }, }; Schedule_t slReload[] = { { tlReload, ARRAYSIZE ( tlReload ), bits_COND_HEAVY_DAMAGE, 0, "Reload" } }; //========================================================= // Attack Schedules //========================================================= // primary range attack Task_t tlRangeAttack1[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_RANGE_ATTACK1, (float)0 }, }; Schedule_t slRangeAttack1[] = { { tlRangeAttack1, ARRAYSIZE ( tlRangeAttack1 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED | bits_COND_NO_AMMO_LOADED | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Range Attack1" }, }; // secondary range attack Task_t tlRangeAttack2[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_RANGE_ATTACK2, (float)0 }, }; Schedule_t slRangeAttack2[] = { { tlRangeAttack2, ARRAYSIZE ( tlRangeAttack2 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Range Attack2" }, }; // primary melee attack Task_t tlPrimaryMeleeAttack1[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_MELEE_ATTACK1, (float)0 }, }; Schedule_t slPrimaryMeleeAttack[] = { { tlPrimaryMeleeAttack1, ARRAYSIZE ( tlPrimaryMeleeAttack1 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED, 0, "Primary Melee Attack" }, }; // secondary melee attack Task_t tlSecondaryMeleeAttack1[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_MELEE_ATTACK2, (float)0 }, }; Schedule_t slSecondaryMeleeAttack[] = { { tlSecondaryMeleeAttack1, ARRAYSIZE ( tlSecondaryMeleeAttack1 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED, 0, "Secondary Melee Attack" }, }; // special attack1 Task_t tlSpecialAttack1[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_SPECIAL_ATTACK1, (float)0 }, }; Schedule_t slSpecialAttack1[] = { { tlSpecialAttack1, ARRAYSIZE ( tlSpecialAttack1 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED | bits_COND_NO_AMMO_LOADED | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Special Attack1" }, }; // special attack2 Task_t tlSpecialAttack2[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_SPECIAL_ATTACK2, (float)0 }, }; Schedule_t slSpecialAttack2[] = { { tlSpecialAttack2, ARRAYSIZE ( tlSpecialAttack2 ), bits_COND_NEW_ENEMY | bits_COND_ENEMY_DEAD | bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE | bits_COND_ENEMY_OCCLUDED | bits_COND_NO_AMMO_LOADED | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Special Attack2" }, }; // Chase enemy schedule Task_t tlChaseEnemy1[] = { { TASK_SET_FAIL_SCHEDULE, (float)SCHED_CHASE_ENEMY_FAILED }, { TASK_GET_PATH_TO_ENEMY, (float)0 }, { TASK_RUN_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, }; Schedule_t slChaseEnemy[] = { { tlChaseEnemy1, ARRAYSIZE ( tlChaseEnemy1 ), bits_COND_NEW_ENEMY | bits_COND_CAN_RANGE_ATTACK1 | bits_COND_CAN_MELEE_ATTACK1 | bits_COND_CAN_RANGE_ATTACK2 | bits_COND_CAN_MELEE_ATTACK2 | bits_COND_TASK_FAILED | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "Chase Enemy" }, }; // Chase enemy failure schedule Task_t tlChaseEnemyFailed[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_WAIT, (float)0.2 }, { TASK_FIND_COVER_FROM_ENEMY, (float)0 }, { TASK_RUN_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_REMEMBER, (float)bits_MEMORY_INCOVER }, // { TASK_TURN_LEFT, (float)179 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_WAIT, (float)1 }, }; Schedule_t slChaseEnemyFailed[] = { { tlChaseEnemyFailed, ARRAYSIZE ( tlChaseEnemyFailed ), bits_COND_NEW_ENEMY | bits_COND_CAN_RANGE_ATTACK1 | bits_COND_CAN_MELEE_ATTACK1 | bits_COND_CAN_RANGE_ATTACK2 | bits_COND_CAN_MELEE_ATTACK2 | bits_COND_HEAR_SOUND, bits_SOUND_DANGER, "tlChaseEnemyFailed" }, }; //========================================================= // small flinch, played when minor damage is taken. //========================================================= Task_t tlSmallFlinch[] = { { TASK_REMEMBER, (float)bits_MEMORY_FLINCHED }, { TASK_STOP_MOVING, 0 }, { TASK_SMALL_FLINCH, 0 }, }; Schedule_t slSmallFlinch[] = { { tlSmallFlinch, ARRAYSIZE ( tlSmallFlinch ), 0, 0, "Small Flinch" }, }; //========================================================= // Die! //========================================================= Task_t tlDie1[] = { { TASK_STOP_MOVING, 0 }, { TASK_SOUND_DIE, (float)0 }, { TASK_DIE, (float)0 }, }; Schedule_t slDie[] = { { tlDie1, ARRAYSIZE( tlDie1 ), 0, 0, "Die" }, }; //========================================================= // Victory Dance //========================================================= Task_t tlVictoryDance[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }, { TASK_WAIT, (float)0 }, }; Schedule_t slVictoryDance[] = { { tlVictoryDance, ARRAYSIZE( tlVictoryDance ), 0, 0, "Victory Dance" }, }; //========================================================= // BarnacleVictimGrab - barnacle tongue just hit the monster, // so play a hit animation, then play a cycling pull animation // as the creature is hoisting the monster. //========================================================= Task_t tlBarnacleVictimGrab[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, (float)ACT_BARNACLE_HIT }, { TASK_SET_ACTIVITY, (float)ACT_BARNACLE_PULL }, { TASK_WAIT_INDEFINITE, (float)0 },// just cycle barnacle pull anim while barnacle hoists. }; Schedule_t slBarnacleVictimGrab[] = { { tlBarnacleVictimGrab, ARRAYSIZE ( tlBarnacleVictimGrab ), 0, 0, "Barnacle Victim" } }; //========================================================= // BarnacleVictimChomp - barnacle has pulled the prey to its // mouth. Victim should play the BARNCLE_CHOMP animation // once, then loop the BARNACLE_CHEW animation indefinitely //========================================================= Task_t tlBarnacleVictimChomp[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, (float)ACT_BARNACLE_CHOMP }, { TASK_SET_ACTIVITY, (float)ACT_BARNACLE_CHEW }, { TASK_WAIT_INDEFINITE, (float)0 },// just cycle barnacle pull anim while barnacle hoists. }; Schedule_t slBarnacleVictimChomp[] = { { tlBarnacleVictimChomp, ARRAYSIZE ( tlBarnacleVictimChomp ), 0, 0, "Barnacle Chomp" } }; // Universal Error Schedule Task_t tlError[] = { { TASK_STOP_MOVING, 0 }, { TASK_WAIT_INDEFINITE, (float)0 }, }; Schedule_t slError[] = { { tlError, ARRAYSIZE ( tlError ), 0, 0, "Error" }, }; Task_t tlScriptedWalk[] = { { TASK_WALK_TO_TARGET, (float)TARGET_MOVE_SCRIPTED }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_PLANT_ON_SCRIPT, (float)0 }, { TASK_FACE_SCRIPT, (float)0 }, { TASK_FACE_IDEAL, (float)0 }, { TASK_ENABLE_SCRIPT, (float)0 }, { TASK_WAIT_FOR_SCRIPT, (float)0 }, { TASK_PLAY_SCRIPT, (float)0 }, }; Schedule_t slWalkToScript[] = { { tlScriptedWalk, ARRAYSIZE ( tlScriptedWalk ), SCRIPT_BREAK_CONDITIONS, 0, "WalkToScript" }, }; Task_t tlScriptedRun[] = { { TASK_RUN_TO_TARGET, (float)TARGET_MOVE_SCRIPTED }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_PLANT_ON_SCRIPT, (float)0 }, { TASK_FACE_SCRIPT, (float)0 }, { TASK_FACE_IDEAL, (float)0 }, { TASK_ENABLE_SCRIPT, (float)0 }, { TASK_WAIT_FOR_SCRIPT, (float)0 }, { TASK_PLAY_SCRIPT, (float)0 }, }; Schedule_t slRunToScript[] = { { tlScriptedRun, ARRAYSIZE ( tlScriptedRun ), SCRIPT_BREAK_CONDITIONS, 0, "RunToScript" }, }; Task_t tlScriptedWait[] = { { TASK_STOP_MOVING, 0 }, { TASK_WAIT_FOR_SCRIPT, (float)0 }, { TASK_PLAY_SCRIPT, (float)0 }, }; Schedule_t slWaitScript[] = { { tlScriptedWait, ARRAYSIZE ( tlScriptedWait ), SCRIPT_BREAK_CONDITIONS, 0, "WaitForScript" }, }; Task_t tlScriptedFace[] = { { TASK_STOP_MOVING, 0 }, { TASK_FACE_SCRIPT, (float)0 }, { TASK_FACE_IDEAL, (float)0 }, { TASK_WAIT_FOR_SCRIPT, (float)0 }, { TASK_PLAY_SCRIPT, (float)0 }, }; Schedule_t slFaceScript[] = { { tlScriptedFace, ARRAYSIZE ( tlScriptedFace ), SCRIPT_BREAK_CONDITIONS, 0, "FaceScript" }, }; //========================================================= // Cower - this is what is usually done when attempts // to escape danger fail. //========================================================= Task_t tlCower[] = { { TASK_STOP_MOVING, 0 }, { TASK_PLAY_SEQUENCE, (float)ACT_COWER }, }; Schedule_t slCower[] = { { tlCower, ARRAYSIZE ( tlCower ), 0, 0, "Cower" }, }; //========================================================= // move away from where you're currently standing. //========================================================= Task_t tlTakeCoverFromOrigin[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_FIND_COVER_FROM_ORIGIN, (float)0 }, { TASK_RUN_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_REMEMBER, (float)bits_MEMORY_INCOVER }, { TASK_TURN_LEFT, (float)179 }, }; Schedule_t slTakeCoverFromOrigin[] = { { tlTakeCoverFromOrigin, ARRAYSIZE ( tlTakeCoverFromOrigin ), bits_COND_NEW_ENEMY, 0, "TakeCoverFromOrigin" }, }; //========================================================= // hide from the loudest sound source //========================================================= Task_t tlTakeCoverFromBestSound[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_FIND_COVER_FROM_BEST_SOUND, (float)0 }, { TASK_RUN_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_REMEMBER, (float)bits_MEMORY_INCOVER }, { TASK_TURN_LEFT, (float)179 }, }; Schedule_t slTakeCoverFromBestSound[] = { { tlTakeCoverFromBestSound, ARRAYSIZE ( tlTakeCoverFromBestSound ), bits_COND_NEW_ENEMY, 0, "TakeCoverFromBestSound" }, }; //========================================================= // Take cover from enemy! Tries lateral cover before node // cover! //========================================================= Task_t tlTakeCoverFromEnemy[] = { { TASK_STOP_MOVING, (float)0 }, { TASK_WAIT, (float)0.2 }, { TASK_FIND_COVER_FROM_ENEMY, (float)0 }, { TASK_RUN_PATH, (float)0 }, { TASK_WAIT_FOR_MOVEMENT, (float)0 }, { TASK_REMEMBER, (float)bits_MEMORY_INCOVER }, // { TASK_TURN_LEFT, (float)179 }, { TASK_FACE_ENEMY, (float)0 }, { TASK_WAIT, (float)1 }, }; Schedule_t slTakeCoverFromEnemy[] = { { tlTakeCoverFromEnemy, ARRAYSIZE ( tlTakeCoverFromEnemy ), bits_COND_NEW_ENEMY, 0, "tlTakeCoverFromEnemy" }, }; Schedule_t *CBaseMonster::m_scheduleList[] = { slIdleStand, slIdleTrigger, slIdleWalk, slAmbush, slActiveIdle, slWakeAngry, slAlertFace, slAlertSmallFlinch, slAlertStand, slInvestigateSound, slCombatStand, slCombatFace, slStandoff, slArmWeapon, slReload, slRangeAttack1, slRangeAttack2, slPrimaryMeleeAttack, slSecondaryMeleeAttack, slSpecialAttack1, slSpecialAttack2, slChaseEnemy, slChaseEnemyFailed, slSmallFlinch, slDie, slVictoryDance, slBarnacleVictimGrab, slBarnacleVictimChomp, slError, slWalkToScript, slRunToScript, slWaitScript, slFaceScript, slCower, slTakeCoverFromOrigin, slTakeCoverFromBestSound, slTakeCoverFromEnemy, slFail }; Schedule_t *CBaseMonster::ScheduleFromName( const char *pName ) { return ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) ); } Schedule_t *CBaseMonster :: ScheduleInList( const char *pName, Schedule_t **pList, int listCount ) { int i; if ( !pName ) { ALERT( at_console, "%s set to unnamed schedule!\n", STRING(pev->classname) ); return NULL; } for ( i = 0; i < listCount; i++ ) { if ( !pList[i]->pName ) { ALERT( at_console, "Unnamed schedule!\n" ); continue; } if ( stricmp( pName, pList[i]->pName ) == 0 ) return pList[i]; } return NULL; } //========================================================= // GetScheduleOfType - returns a pointer to one of the // monster's available schedules of the indicated type. //========================================================= Schedule_t* CBaseMonster :: GetScheduleOfType ( int Type ) { // ALERT ( at_console, "Sched Type:%d\n", Type ); switch ( Type ) { // This is the schedule for scripted sequences AND scripted AI case SCHED_AISCRIPT: { ASSERT( m_pCine != NULL ); if ( !m_pCine ) { ALERT( at_aiconsole, "Script failed for %s\n", STRING(pev->classname) ); CineCleanup(); return GetScheduleOfType( SCHED_IDLE_STAND ); } // else // ALERT( at_aiconsole, "Starting script %s for %s\n", STRING( m_pCine->m_iszPlay ), STRING(pev->classname) ); switch ( m_pCine->m_fMoveTo ) { case 0: case 4: return slWaitScript; case 1: return slWalkToScript; case 2: return slRunToScript; case 5: return slFaceScript; } break; } case SCHED_IDLE_STAND: { if ( RANDOM_LONG(0,14) == 0 && FCanActiveIdle() ) { return &slActiveIdle[ 0 ]; } return &slIdleStand[ 0 ]; } case SCHED_IDLE_WALK: { return &slIdleWalk[ 0 ]; } case SCHED_WAIT_TRIGGER: { return &slIdleTrigger[ 0 ]; } case SCHED_WAKE_ANGRY: { return &slWakeAngry[ 0 ]; } case SCHED_ALERT_FACE: { return &slAlertFace[ 0 ]; } case SCHED_ALERT_STAND: { return &slAlertStand[ 0 ]; } case SCHED_COMBAT_STAND: { return &slCombatStand[ 0 ]; } case SCHED_COMBAT_FACE: { return &slCombatFace[ 0 ]; } case SCHED_CHASE_ENEMY: { return &slChaseEnemy[ 0 ]; } case SCHED_CHASE_ENEMY_FAILED: { return &slFail[ 0 ]; } case SCHED_SMALL_FLINCH: { return &slSmallFlinch[ 0 ]; } case SCHED_ALERT_SMALL_FLINCH: { return &slAlertSmallFlinch[ 0 ]; } case SCHED_RELOAD: { return &slReload[ 0 ]; } case SCHED_ARM_WEAPON: { return &slArmWeapon[ 0 ]; } case SCHED_STANDOFF: { return &slStandoff[ 0 ]; } case SCHED_RANGE_ATTACK1: { return &slRangeAttack1[ 0 ]; } case SCHED_RANGE_ATTACK2: { return &slRangeAttack2[ 0 ]; } case SCHED_MELEE_ATTACK1: { return &slPrimaryMeleeAttack[ 0 ]; } case SCHED_MELEE_ATTACK2: { return &slSecondaryMeleeAttack[ 0 ]; } case SCHED_SPECIAL_ATTACK1: { return &slSpecialAttack1[ 0 ]; } case SCHED_SPECIAL_ATTACK2: { return &slSpecialAttack2[ 0 ]; } case SCHED_TAKE_COVER_FROM_BEST_SOUND: { return &slTakeCoverFromBestSound[ 0 ]; } case SCHED_TAKE_COVER_FROM_ENEMY: { return &slTakeCoverFromEnemy[ 0 ]; } case SCHED_COWER: { return &slCower[ 0 ]; } case SCHED_AMBUSH: { return &slAmbush[ 0 ]; } case SCHED_BARNACLE_VICTIM_GRAB: { return &slBarnacleVictimGrab[ 0 ]; } case SCHED_BARNACLE_VICTIM_CHOMP: { return &slBarnacleVictimChomp[ 0 ]; } case SCHED_INVESTIGATE_SOUND: { return &slInvestigateSound[ 0 ]; } case SCHED_DIE: { return &slDie[ 0 ]; } case SCHED_TAKE_COVER_FROM_ORIGIN: { return &slTakeCoverFromOrigin[ 0 ]; } case SCHED_VICTORY_DANCE: { return &slVictoryDance[ 0 ]; } case SCHED_FAIL: { return slFail; } default: { ALERT ( at_console, "GetScheduleOfType()\nNo CASE for Schedule Type %d!\n", Type ); return &slIdleStand[ 0 ]; break; } } return NULL; }