home *** CD-ROM | disk | FTP | other *** search
Text File | 2004-08-04 | 29.9 KB | 1,416 lines |
- /***********************************************************************
-
- ai_character_sentry.script
-
- ***********************************************************************/
-
- #define SENTRY_WAIT_GETCLOSER 3
- #define SENTRY_LEAD_TIMEOUT 1
- #define SENTRY_FIRERATE 0.1
- #define SENTRY_MIN_SHOTS 8
- #define SENTRY_MIN_LOOK_DELAY 4
- #define SENTRY_MAX_LOOK_DELAY 8
- #define SENTRY_LOOK_TIME 1.5
- #define SENTRY_LEAD_DIST 140
- #define SENTRY_LOST_DIST 280
- #define SENTRY_WALKTURN 65
- #define SENTRY_WALKTURN2 30
- #define SENTRY_ATTACK_MAX_LENGTH 4
- #define SENTRY_ATTACK_MIN_LENGTH 1.2
- #define SENTRY_WAIT_MAX_LENGTH 1
- #define SENTRY_WAIT_MIN_LENGTH 0.3
- #define SENTRY_MIN_TURN 10
-
- //rektek
- #define SENTRY_MAXDIST 190
- #define SENTRY_MINDIST 150
- #define SENTRY_RUNDIST 200
-
- #define RETREATING -1
- #define NOT_MOVING 0
- #define APPROACHING 1
-
- #define RETREATING_DEST -1
- #define APPROACHING_DEST 1
-
- #define PLAYER_LOST 0
- #define PLAYER_BEHIND_ME 1
- #define PLAYER_OK 2
- #define PLAYER_AHEAD_OF_ME 3
-
- object char_sentry : character {
- boolean lead_player;
- float hanging;
- boolean awake;
- boolean fire;
- float playerMoveState;
- entity light;
- boolean light_on;
- float nextPositionSearch;
- entity ignore_enemy;
- float ignore_enemy_time;
- vector lastValidPlayerPosition;
- float playerPositionThread;
-
- //rektek
- boolean run;
-
- //
- // States
- //
- void state_WaitForTrigger();
- void state_Idle();
- void state_Killed();
- void state_FollowPath();
- void state_Wait();
- void state_GetCloser();
- void state_CantReachPlayer();
- void state_Lead();
- void state_FindPlayer();
- void state_Combat();
- void combat_chase();
- boolean find_attack_position();
-
- // attack checks
- float check_attacks();
- void do_attack( float attack_flags );
- void combat_range();
-
- void state_Begin();
- void init();
- void destroy();
-
- void spawn_flashlight();
- void flashlight_off();
- void flashlight_on();
- void ignore( entity ignore_ent );
- boolean checkForEnemy( float use_fov );
-
- float checkDestinationDistance();
- void updatePlayerPositionThread();
-
- // path commands
- void path_sentry_light_on();
- void path_sentry_light_off();
- void path_sentry_shutdown();
- void path_sentry_unlock_door();
- void path_corner();
- void path_sentry_lead_player();
- void path_sentry_ignore_player();
-
- // torso anim states
- void Torso_Death();
- void Torso_Idle();
- void Torso_Pain();
- void Torso_RangeAttack();
-
- // legs anim states
- void Legs_Fold();
- void Legs_Folded();
- void Legs_Unfold();
- void Legs_Hanging();
- void Legs_Death();
- void Legs_Idle();
- void Legs_Walk();
- void Legs_TurnLeft();
- void Legs_TurnRight();
- };
-
- /***********************************************************************
-
- Torso animation control
-
- ***********************************************************************/
-
- void char_sentry::Torso_Death() {
- finishAction( "dead" );
-
- // never exit
- waitUntil( 0 );
- }
-
- void char_sentry::Torso_Idle() {
- idleAnim( ANIMCHANNEL_TORSO, "stand" );
-
- eachFrame {
- if ( AI_PAIN ) {
- Torso_Pain();
- idleAnim( ANIMCHANNEL_TORSO, "stand" );
- }
- if ( fire ) {
- animState( ANIMCHANNEL_TORSO, "Torso_RangeAttack", 4 );
- }
- }
- }
-
- void char_sentry::Torso_Pain() {
- string animname;
-
- animname = getPainAnim();
- setBlendFrames( ANIMCHANNEL_TORSO, 2 );
- playAnim( ANIMCHANNEL_TORSO, animname );
-
- while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
- waitFrame();
- }
-
- // no pain for 2 seconds
- preventPain( 2 );
-
- finishAction( "pain" );
- setBlendFrames( ANIMCHANNEL_TORSO, 4 );
- }
-
- void char_sentry::Torso_RangeAttack() {
- float endtime;
- float firetime;
- float numshots;
-
- setAnimPrefix( "" );
-
- playAnim( ANIMCHANNEL_TORSO, "range_attack" );
- while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
- if ( AI_PAIN ) {
- Torso_Pain();
- }
- waitFrame();
- }
-
- numshots = 0;
- while( fire || ( numshots < SENTRY_MIN_SHOTS ) ) {
- endtime = RandomDelay( SENTRY_ATTACK_MIN_LENGTH, SENTRY_ATTACK_MAX_LENGTH );
- setBlendFrames( ANIMCHANNEL_TORSO, 2 );
- playCycle( ANIMCHANNEL_TORSO, "range_attack_loop" );
- firetime = sys.getTime();
- while( ( fire || ( numshots < SENTRY_MIN_SHOTS ) ) && ( sys.getTime() < endtime ) ) {
- if ( sys.getTime() >= firetime ) {
- startSound( "snd_fire", SND_CHANNEL_WEAPON, false );
- attackMissile( "Barrel" );
- numshots++;
- firetime = sys.getTime() + SENTRY_FIRERATE;
- }
- if ( AI_PAIN ) {
- Torso_Pain();
- playCycle( ANIMCHANNEL_TORSO, "range_attack_loop" );
- }
- waitFrame();
- }
-
- if ( !fire && ( numshots >= SENTRY_MIN_SHOTS ) ) {
- break;
- }
-
- setBlendFrames( ANIMCHANNEL_TORSO, 2 );
- playCycle( ANIMCHANNEL_TORSO, "range_attack_aim" );
- endtime = RandomDelay( SENTRY_WAIT_MIN_LENGTH, SENTRY_WAIT_MAX_LENGTH );
- while( ( fire || ( numshots < SENTRY_MIN_SHOTS ) ) && ( sys.getTime() < endtime ) ) {
- if ( AI_PAIN ) {
- Torso_Pain();
- }
- waitFrame();
- }
- }
-
- playAnim( ANIMCHANNEL_TORSO, "range_attack_end" );
- while( !animDone( ANIMCHANNEL_TORSO, 4 ) ) {
- if ( AI_PAIN ) {
- Torso_Pain();
- }
- waitFrame();
- }
-
- finishAction( "range_attack" );
- animState( ANIMCHANNEL_TORSO, "Torso_Idle", 4 );
- }
-
- /***********************************************************************
-
- Legs animation control
-
- ***********************************************************************/
-
- void char_sentry::Legs_Death() {
- while( AI_DEAD ) {
- waitFrame();
- }
-
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 4 );
- }
-
- void char_sentry::Legs_Idle() {
- float delta;
-
- if ( !AI_FORWARD && !facingIdeal() ) {
- if ( getTurnDelta() > SENTRY_MIN_TURN ) {
- animState( ANIMCHANNEL_LEGS, "Legs_TurnLeft", 4 );
- }
-
- if ( getTurnDelta() < -SENTRY_MIN_TURN ) {
- animState( ANIMCHANNEL_LEGS, "Legs_TurnRight", 4 );
- }
- }
-
- idleAnim( ANIMCHANNEL_LEGS, "stand" );
-
- eachFrame {
- //rektek
- // if ( !awake ) {
- // animState( ANIMCHANNEL_LEGS, "Legs_Fold", 4 );
- // }
- if ( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta <= SENTRY_WALKTURN ) && ( delta >= -SENTRY_WALKTURN ) ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Walk", 12 );
- }
- }
- if ( !facingIdeal() ) {
- if ( getTurnDelta() > SENTRY_MIN_TURN ) {
- animState( ANIMCHANNEL_LEGS, "Legs_TurnLeft", 4 );
- }
- if ( getTurnDelta() < -SENTRY_MIN_TURN ) {
- animState( ANIMCHANNEL_LEGS, "Legs_TurnRight", 4 );
- }
- }
- }
- }
-
- void char_sentry::Legs_Walk() {
- float delta;
-
- playCycle( ANIMCHANNEL_LEGS, "walk" );
-
- while( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta > SENTRY_WALKTURN ) || ( delta < -SENTRY_WALKTURN ) ) {
- break;
- }
-
- waitFrame();
- }
-
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 12 );
- }
-
- void char_sentry::Legs_Fold() {
- startSound( "snd_shutdown", SND_CHANNEL_VOICE, false );
- playAnim( ANIMCHANNEL_LEGS, "fold" );
- while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
- waitFrame();
- }
- flashlight_off();
- finishAction( "fold" );
- animState( ANIMCHANNEL_LEGS, "Legs_Folded", 0 );
- }
-
- void char_sentry::Legs_Folded() {
- playCycle( ANIMCHANNEL_LEGS, "folded" );
- while( !awake ) {
- waitFrame();
- }
-
- animState( ANIMCHANNEL_LEGS, "Legs_Unfold", 4 );
- }
-
- void char_sentry::Legs_Unfold() {
- playAnim( ANIMCHANNEL_LEGS, "unfold" );
- while( !animDone( ANIMCHANNEL_LEGS, 8 ) ) {
- waitFrame();
- }
-
- finishAction( "unfold" );
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 8 );
- }
-
- void char_sentry::Legs_Hanging() {
- playCycle( ANIMCHANNEL_LEGS, "releaseidle" );
- while( hanging ) {
- waitFrame();
- }
-
- playAnim( ANIMCHANNEL_LEGS, "load" );
- while( !animDone( ANIMCHANNEL_LEGS, 8 ) ) {
- waitFrame();
- }
-
- finishAction( "unload" );
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 8 );
- }
-
- void char_sentry::Legs_TurnLeft() {
- float turnAmount;
- float delta;
-
- turnAmount = getTurnDelta();
- if ( turnAmount > 110 ) {
- // do it in two turns
- turnAmount *= 0.5;
- }
-
- playAnim( ANIMCHANNEL_LEGS, "turn_left" );
- while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
- if ( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta <= SENTRY_WALKTURN2 ) && ( delta >= -SENTRY_WALKTURN2 ) ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Walk", 12 );
- }
- }
- waitFrame();
- }
-
- playAnim( ANIMCHANNEL_LEGS, "turn_right" );
- while( !animDone( ANIMCHANNEL_LEGS, 8 ) ) {
- if ( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta <= SENTRY_WALKTURN2 ) && ( delta >= -SENTRY_WALKTURN2 ) ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Walk", 8 );
- }
- }
- waitFrame();
- }
-
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 8 );
- }
-
- void char_sentry::Legs_TurnRight() {
- float turnAmount;
- float delta;
-
- turnAmount = getTurnDelta();
- if ( turnAmount < -110 ) {
- // do it in two turns
- turnAmount *= 0.5;
- }
-
- playAnim( ANIMCHANNEL_LEGS, "turn_right" );
- while( !animDone( ANIMCHANNEL_LEGS, 0 ) ) {
- if ( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta <= SENTRY_WALKTURN2 ) && ( delta >= -SENTRY_WALKTURN2 ) ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Walk", 12 );
- }
- }
- waitFrame();
- }
-
- playAnim( ANIMCHANNEL_LEGS, "turn_left" );
- while( !animDone( ANIMCHANNEL_LEGS, 8 ) ) {
- if ( AI_FORWARD ) {
- delta = getTurnDelta();
- if ( ( delta <= SENTRY_WALKTURN2 ) && ( delta >= -SENTRY_WALKTURN2 ) ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Walk", 8 );
- }
- }
- waitFrame();
- }
-
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 8 );
- }
-
- /***********************************************************************
-
- AI
-
- ***********************************************************************/
-
- /*
- =====================
- char_sentry::state_Begin
- =====================
- */
- void char_sentry::state_Begin() {
- fire = false;
- setBoneMod( true );
-
- light_on = false;
- if ( getIntKey( "flashlight" ) ) {
- spawn_flashlight();
- }
-
- hanging = getIntKey( "hanging" );
- awake = getIntKey( "unfolded" );
-
- waitFrame();
- if ( hanging ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Hanging", 0 );
- } else if ( !awake ) {
- animState( ANIMCHANNEL_LEGS, "Legs_Folded", 0 );
- } else {
- animState( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
- }
- animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
- setState( "state_WaitForTrigger" );
- }
-
- /*
- =====================
- char_sentry::init
- =====================
- */
- void char_sentry::init() {
-
- lead_player = getIntKey( "lead_player" );
- can_talk = false;
- no_cower_saved = true;
- no_cower = true;
- }
-
- /*
- =====================
- char_sentry::destroy
- =====================
- */
- void char_sentry::destroy() {
- light.remove();
- if ( playerPositionThread ) {
- sys.terminate( playerPositionThread );
- playerPositionThread = 0;
- }
- }
-
- /*
- =====================
- char_sentry::spawn_flashlight
- =====================
- */
- void char_sentry::spawn_flashlight() {
- string texture;
- float distance;
-
- distance = getFloatKey( "flashlight_distance" );
- if ( !distance ) {
- distance = 640;
- }
-
- // use ik_pose to bind light
- playAnim( ANIMCHANNEL_TORSO, "ik_pose" );
- if ( getIntKey( "flashlight" ) == 2 ) {
- // spot light
- sys.setSpawnArg( "light_target", "1 0 0" );
- sys.setSpawnArg( "light_up", "0 0 .5" );
- sys.setSpawnArg( "light_right", "0 -.5 0" );
- sys.setSpawnArg( "light_end", distance + " 0 0" );
-
- texture = getKey( "mtr_flashlight" );
- sys.setSpawnArg( "texture", texture );
-
- sys.setSpawnArg( "name", getName() + "_light" );
- light = sys.spawn( "light" );
- light.setAngles( getAngles() );
- light.bindToJoint( self, "light", true );
- light.setOrigin( '0 0 0' );
- } else {
- // radial light
- sys.setSpawnArg( "name", getName() + "_light" );
- light = sys.spawn( "light" );
- light.setRadius( 256 );
- light.setAngles( getAngles() + '0 90 0' );
- light.bindToJoint( self, "light", true );
- texture = getKey( "mtr_flashlight" );
- light.setShader( texture );
- light.setOrigin( '0 0 0' );
- }
- stopAnim( ANIMCHANNEL_TORSO, 0 );
-
- flashlight_off();
- }
-
- /*
- =====================
- char_sentry::flashlight_off
- =====================
- */
- void char_sentry::flashlight_off() {
- string skin;
-
- if ( light ) {
- light.Off();
- skin = getKey( "skin_flashlight_off" );
- setSkin( skin );
- light_on = false;
- }
- }
-
- /*
- =====================
- char_sentry::flashlight_on
- =====================
- */
- void char_sentry::flashlight_on() {
- string skin;
-
- if ( light ) {
- light.On();
- skin = getKey( "skin_flashlight_on" );
- setSkin( skin );
- light_on = true;
- }
- }
-
- /*
- =====================
- char_sentry::ignore
- =====================
- */
- void char_sentry::ignore( entity ignore_ent ) {
- ignore_enemy = ignore_ent;
- ignore_enemy_time = sys.getTime() + 2;
- }
-
- /*
- =====================
- char_sentry::checkForEnemy
- =====================
- */
- boolean char_sentry::checkForEnemy( float use_fov ) {
- entity enemy;
- entity ent;
-
- enemy = $null_entity;
- if ( lead_player && $player1.hasEnemies() ) {
- enemy = closestReachableEnemyOfEntity( $player1 );
- if ( ( ignore_enemy_time > sys.getTime() ) && ( ignore_enemy == enemy ) ) {
- enemy = $null_entity;
- }
- if ( !enemy ) {
- enemy = $player1.closestEnemyToPoint( getOrigin() );
- if ( ( ignore_enemy_time > sys.getTime() ) && ( ignore_enemy == enemy ) ) {
- enemy = $null_entity;
- }
- }
- }
-
- if ( !enemy ) {
- enemy = findEnemyAI( false );
- if ( ( ignore_enemy_time > sys.getTime() ) && ( ignore_enemy == enemy ) ) {
- enemy = $null_entity;
- }
- }
-
- if ( enemy ) {
- startSound( "snd_sight_enemy", SND_CHANNEL_VOICE, false );
- setEnemy( enemy );
- return true;
- } else {
- clearEnemy();
- }
-
- return false;
- }
-
- /*
- =====================
- char_sentry::checkDestinationDistance()
- =====================
- */
- float char_sentry::checkDestinationDistance() {
- float playerDist;
- float currentDist;
- float leadDistance;
- float relativeMoveDir;
- vector delta;
-
- // determine if the player is moving toward us
- delta = getOrigin() - lastValidPlayerPosition;
- relativeMoveDir = delta * $player1.getLinearVelocity();
- if ( relativeMoveDir > 1 ) {
- // Player is approaching
- playerMoveState = APPROACHING;
- } else if ( relativeMoveDir < -1 ) {
- // Player is moving away from us
- playerMoveState = RETREATING;
- } else {
- // Player is standing still
- playerMoveState = NOT_MOVING;
- }
-
- if ( !current_path ) {
- return PLAYER_OK;
- }
-
- playerDist = distanceToPoint( lastValidPlayerPosition );
- if ( playerDist < SENTRY_LEAD_DIST ) {
- return PLAYER_OK;
- }
-
- if ( !canSee( $player1 ) ) {
- currentDist = travelDistanceToEntity( current_path );
- leadDistance = travelDistanceBetweenPoints( lastValidPlayerPosition, current_path.getOrigin() );
- if ( currentDist > leadDistance ) {
- return PLAYER_AHEAD_OF_ME;
- } else {
- return PLAYER_LOST;
- }
- }
-
- if ( playerDist > SENTRY_LOST_DIST ) {
- currentDist = travelDistanceToEntity( current_path );
- leadDistance = travelDistanceBetweenPoints( lastValidPlayerPosition, current_path.getOrigin() );
- if ( currentDist > leadDistance ) {
- return PLAYER_AHEAD_OF_ME;
- } else {
- return PLAYER_BEHIND_ME;
- }
- }
-
- return PLAYER_OK;
- }
-
- /*
- =====================
- char_sentry::updatePlayerPositionThread()
- =====================
- */
- void char_sentry::updatePlayerPositionThread() {
- vector pos;
-
- while( 1 ) {
- if ( canReachEntity( $player1 ) ) {
- lastValidPlayerPosition = getReachableEntityPosition( $player1 );
- }
- //sys.debugBounds( '1 0 0', lastValidPlayerPosition + $player1.getMins(), lastValidPlayerPosition + $player1.getMaxs(), 0 );
- waitFrame();
- }
- }
-
- /***********************************************************************
-
- Path commands
-
- ***********************************************************************/
-
- /*
- =====================
- char_sentry::path_sentry_light_on
- =====================
- */
- void char_sentry::path_sentry_light_on() {
- flashlight_on();
- }
-
- /*
- =====================
- char_sentry::path_sentry_light_off
- =====================
- */
- void char_sentry::path_sentry_light_off() {
- flashlight_off();
- }
-
- /*
- =====================
- char_sentry::path_sentry_shutdown
- =====================
- */
- void char_sentry::path_sentry_shutdown() {
- vector ang;
-
- stopMove();
-
- ang = current_path.getAngles();
- turnTo( ang_y );
- waitUntil( facingIdeal() );
-
- awake = false;
- AI_ACTIVATED = false;
-
- if ( playerPositionThread ) {
- sys.terminate( playerPositionThread );
- playerPositionThread = 0;
- }
-
- waitAction( "fold" );
- while( !AI_ACTIVATED ) {
- waitFrame();
- }
-
- if ( getIntKey( "flashlight_on" ) ) {
- flashlight_on();
- }
- awake = true;
- waitAction( "unfold" );
- }
-
- /*
- =====================
- char_sentry::path_sentry_unlock_door
- =====================
- */
- void char_sentry::path_sentry_unlock_door() {
- vector ang;
- string triggername;
- entity triggerent;
-
- if ( current_path.getKey( "trigger" ) == "" ) {
- // already unlocked the door
- return;
- }
-
- ang = current_path.getAngles();
- turnTo( ang_y );
- waitUntil( facingIdeal() );
-
- startSound( "snd_open_door", SND_CHANNEL_VOICE, false );
- playCustomAnim( "unlock_door", 4, 4 );
- waitAction( "customAnim" );
-
- // trigger any entities the path had targeted
- triggername = current_path.getKey( "trigger" );
- if ( triggername != "" ) {
- triggerent = sys.getEntity( triggername );
- if ( triggerent ) {
- triggerent.activate( self );
- }
- }
-
- current_path.setKey( "trigger", "" );
- }
-
- /*
- =====================
- char_sentry::path_corner
- =====================
- */
- void char_sentry::path_corner() {
- if ( !lead_player ) {
- setState( "state_FollowPath" );
- }
-
- setNeverDormant( true );
- if ( !canSee( $player1 ) ) {
- setState( "state_FindPlayer" );
- }
-
- if ( checkDestinationDistance() == PLAYER_BEHIND_ME ) {
- setState( "state_Wait" );
- } else {
- setState( "state_Lead" );
- }
- }
-
- /*
- =====================
- char_sentry::path_sentry_lead_player
- =====================
- */
- void char_sentry::path_sentry_lead_player() {
- lead_player = true;
- if ( !playerPositionThread ) {
- playerPositionThread = thread updatePlayerPositionThread();
- }
- }
-
- /*
- =====================
- char_sentry::path_sentry_ignore_player
- =====================
- */
- void char_sentry::path_sentry_ignore_player() {
- lead_player = false;
- if ( playerPositionThread ) {
- sys.terminate( playerPositionThread );
- playerPositionThread = 0;
- }
- }
-
- /***********************************************************************
-
- States
-
- ***********************************************************************/
-
- /*
- =====================
- char_sentry::state_Killed
- =====================
- */
- void char_sentry::state_Killed() {
- stopMove();
-
- if ( playerPositionThread ) {
- sys.terminate( playerPositionThread );
- playerPositionThread = 0;
- }
-
- flashlight_off();
-
- animState( ANIMCHANNEL_TORSO, "Torso_Death", 0 );
- animState( ANIMCHANNEL_LEGS, "Legs_Death", 0 );
-
- waitAction( "dead" );
-
- float burnDelay = getFloatKey( "burnaway" );
- if ( burnDelay != 0 ) {
- preBurn();
- sys.wait( burnDelay );
- burn();
- startSound( "snd_burn", SND_CHANNEL_BODY, false );
- sys.wait( 3 );
- remove();
- }
-
- stopThinking();
- }
-
- /*
- =====================
- char_sentry::state_WaitForTrigger
- =====================
- */
- void char_sentry::state_WaitForTrigger() {
-
- //rektek -- Preprogram Bot AI "FOLLOW PLAYER"
-
- // UNLOAD SENTRY
- Legs_Hanging();
-
- while (1)
- {
- // Always Flashlight?
- flashlight_on();
- lookAt( $player1, 0.1 );
- allowDamage();
-
- // FIND PLAYER
- if ( !canSee( $player1 ) )
- {
- setState( "state_FindPlayer" );
- }
-
- // DEFEND PLAYER
- if ( checkForEnemy( true ) )
- {
- setState( "state_Combat" );
- }
-
- // DON'T BLOCK PLAYER PATH
- if ( AI_PUSHED )
- {
- getOutOfWay();
- }
-
- // RUN TO PLAYER
- run = false;
- moveToEntity( $player1 );
-
- while( !AI_DEST_UNREACHABLE && !AI_MOVE_DONE && ( distanceTo( $player1 ) > SENTRY_MINDIST ) )
- {
- lookAt( $player1, 0.1 );
- if ( distanceTo( $player1 ) > SENTRY_RUNDIST )
- {
- run = true;
- startSound( "snd_waiting_for_player", SND_CHANNEL_VOICE, false );
- }
- if ( distanceTo( $player1 ) < SENTRY_MAXDIST )
- {
- run = false;
- }
-
- waitFrame();
- }
- stopMove();
-
- waitFrame();
- }
-
- // OLD CODE "LEAD PLAYER"
- /*
- if ( hanging != 2 ) {
- AI_ACTIVATED = false;
- while( !AI_ACTIVATED ) {
- waitFrame();
- }
- }
-
- if ( getIntKey( "flashlight_on" ) ) {
- flashlight_on();
- }
-
- if ( hanging ) {
- hanging = false;
- awake = true;
- waitAction( "unload" );
- } else if ( !awake ) {
- awake = true;
- waitAction( "unfold" );
- }
-
- // hanging guys turn off damage untill they're out. make sure we get damage turned back on.
- allowDamage();
- lookAt( $player1, 3 );
-
- current_path = randomPath();
- //next_path = current_path.randomPath();
- lookAt( $player1, 3 );
-
- setState( "state_Idle" );
- */
- // END OF OLD CODE
- }
-
- /*
- =====================
- char_sentry::state_Idle
- =====================
- */
- void char_sentry::state_Idle()
- {
-
- //rektek -- Preprogram Bot AI "FOLLOW PLAYER"
-
- while (1)
- {
- // Always Flashlight?
- flashlight_on();
- lookAt( $player1, 0.1 );
-
- // FIND PLAYER
- if ( !canSee( $player1 ) )
- {
- setState( "state_FindPlayer" );
- }
-
- // DEFEND PLAYER
- if ( checkForEnemy( true ) )
- {
- setState( "state_Combat" );
- }
-
- // DON'T BLOCK PLAYER PATH
- if ( AI_PUSHED )
- {
- getOutOfWay();
- }
-
- // RUN TO PLAYER
- run = false;
- moveToEntity( $player1 );
-
- while( !AI_DEST_UNREACHABLE && !AI_MOVE_DONE && ( distanceTo( $player1 ) > SENTRY_MINDIST ) )
- {
- lookAt( $player1, 0.1 );
- if ( distanceTo( $player1 ) > SENTRY_RUNDIST )
- {
- run = true;
- startSound( "snd_waiting_for_player", SND_CHANNEL_VOICE, false );
- }
- if ( distanceTo( $player1 ) < SENTRY_MAXDIST )
- {
- run = false;
- }
-
- waitFrame();
- }
- stopMove();
-
- waitFrame();
-
- }
-
- // OLD CODE "LEAD PLAYER"
- /*
- stopMove();
-
- if ( lead_player && !playerPositionThread ) {
- playerPositionThread = thread updatePlayerPositionThread();
- }
-
- if ( current_path ) {
- executePathCommand( current_path );
- }
-
- while( 1 ) {
- if ( lead_player ) {
- if ( !canSee( $player1 ) ) {
- setState( "state_FindPlayer" );
- }
- }
-
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
- if ( AI_PUSHED ) {
- getOutOfWay();
- }
- if ( current_path ) {
- executePathCommand( current_path );
- }
- waitFrame();
- }
- */
- // END OF OLD CODE
- }
-
- /*
- =====================
- char_sentry::state_FollowPath
- =====================
- */
- void char_sentry::state_FollowPath() {
- if ( !current_path ) {
- setState( "state_Idle" );
- }
-
- moveToEntity( current_path );
-
- while( 1 ) {
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
-
- checkBlocked();
-
- if ( AI_MOVE_DONE ) {
- if ( AI_DEST_UNREACHABLE ) {
- waitFrame();
- setState( "state_FindPlayer" );
- }
- setNeverDormant( getFloatKey( "neverdormant" ) );
- finishPathCommand();
- setState( "state_Idle" );
- }
-
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_Wait
- =====================
- */
- void char_sentry::state_Wait() {
- float getCloserTime;
-
- float result = checkDestinationDistance();
- if ( result == PLAYER_LOST ) {
- setState( "state_FindPlayer" );
- } else if ( result == PLAYER_AHEAD_OF_ME ) {
- setState( "state_Lead" );
- } else if ( ( result == PLAYER_OK ) && ( playerMoveState == APPROACHING ) ) {
- setState( "state_Lead" );
- }
-
- stopMove();
- startSound( "snd_waiting_for_player", SND_CHANNEL_VOICE, false );
-
- getCloserTime = sys.getTime() + SENTRY_WAIT_GETCLOSER;
- while( 1 ) {
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
-
- lookAt( $player1, 0.1 );
-
- if ( AI_PUSHED ) {
- getOutOfWay();
- }
-
- result = checkDestinationDistance();
- if ( result == PLAYER_LOST ) {
- setState( "state_FindPlayer" );
- } else if ( result == PLAYER_AHEAD_OF_ME ) {
- setState( "state_Lead" );
- } else if ( ( result == PLAYER_OK ) && ( playerMoveState == APPROACHING ) ) {
- setState( "state_Lead" );
- } else if ( ( sys.getTime() > getCloserTime ) && ( result == PLAYER_BEHIND_ME ) ) {
- setState( "state_GetCloser" );
- }
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_GetCloser
- =====================
- */
- void char_sentry::state_GetCloser() {
- while( 1 ) {
- moveToPosition( lastValidPlayerPosition );
- if ( AI_MOVE_DONE ) {
- if ( !canReachEntity( $player1 ) ) {
- setState( "state_CantReachPlayer" );
- }
- }
-
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
-
- checkBlocked();
-
- float result = checkDestinationDistance();
-
- if ( result == PLAYER_LOST ) {
- setState( "state_FindPlayer" );
- }
- if ( result == PLAYER_OK ) {
- setState( "state_Wait" );
- }
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_CantReachPlayer
- =====================
- */
- void char_sentry::state_CantReachPlayer() {
- startSound( "snd_cant_reach_player", SND_CHANNEL_VOICE, false );
- stopMove();
- while( 1 ) {
- if ( canReachEntity( $player1 ) ) {
- setState( "state_Wait" );
- }
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_Lead
- =====================
- */
- void char_sentry::state_Lead() {
- float nextLookTime;
- float leadTimeOut;
-
- if ( !current_path ) {
- setState( "state_Idle" );
- }
-
- nextLookTime = RandomDelay( SENTRY_MIN_LOOK_DELAY, SENTRY_MAX_LOOK_DELAY );
- moveToEntity( current_path );
-
- leadTimeOut = sys.getTime() + SENTRY_LEAD_TIMEOUT;
-
- while( 1 ) {
- if ( checkForEnemy( true ) ) {
- setState( "state_Combat" );
- }
-
- if ( !light_on && ( sys.getTime() > nextLookTime ) ) {
- lookAt( $player1, SENTRY_LOOK_TIME );
- nextLookTime = RandomDelay( SENTRY_MIN_LOOK_DELAY, SENTRY_MAX_LOOK_DELAY );
- }
-
- checkBlocked();
-
- float result = checkDestinationDistance();
- if ( ( result != PLAYER_BEHIND_ME ) && ( result != PLAYER_LOST ) ) {
- leadTimeOut = sys.getTime() + SENTRY_LEAD_TIMEOUT;
- } else if ( sys.getTime() > leadTimeOut ) {
- setState( "state_Wait" );
- } else if ( !light_on ) {
- // look back at player to see what he's up to
- lookAt( $player1, 0.1 );
- nextLookTime += 0.1;
- }
-
- if ( AI_MOVE_DONE ) {
- if ( AI_DEST_UNREACHABLE ) {
- waitFrame();
- setState( "state_FindPlayer" );
- }
- setNeverDormant( getFloatKey( "neverdormant" ) );
- finishPathCommand();
- setState( "state_Idle" );
- }
-
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_FindPlayer
- =====================
- */
- void char_sentry::state_FindPlayer() {
- while( 1 ) {
- moveToPosition( lastValidPlayerPosition );
- if ( AI_MOVE_DONE || AI_DEST_UNREACHABLE ) {
- if ( !canReachEntity( $player1 ) ) {
- setState( "state_CantReachPlayer" );
- }
- }
-
- if ( checkForEnemy( true ) ) {
- waitFrame();
- setState( "state_Combat" );
- }
-
- checkBlocked();
-
- float result = checkDestinationDistance();
- if ( canSee( $player1 ) && ( ( result == PLAYER_BEHIND_ME ) || ( result == PLAYER_OK ) ) ) {
- setState( "state_Wait" );
- } else if ( result == PLAYER_AHEAD_OF_ME ) {
- setState( "state_Lead" );
- }
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::state_Combat
- =====================
- */
- void char_sentry::state_Combat() {
- float attack_flags;
-
- eachFrame {
- faceEnemy();
- lookAtEnemy( 1 );
-
- if ( AI_ENEMY_DEAD || !getEnemy() ) {
- startSound( "snd_target_lost", SND_CHANNEL_VOICE, false );
- AI_ENEMY_DEAD = false;
- clearEnemy();
- setState( "state_Idle" );
-
- }
-
- attack_flags = check_attacks();
- if ( attack_flags ) {
- do_attack( attack_flags );
- continue;
- }
-
- if ( canReachEnemy() ) {
- combat_chase();
- } else if ( !find_attack_position() ) {
- ignore( getEnemy() );
- checkForEnemy( false );
- }
-
- waitFrame();
- }
- }
-
- /*
- =====================
- char_sentry::combat_chase
- =====================
- */
- void char_sentry::combat_chase() {
- float attack_flags;
-
- moveToEnemy();
- while( !AI_DEST_UNREACHABLE ) {
- if ( AI_ENEMY_DEAD ) {
- startSound( "snd_target_lost", SND_CHANNEL_VOICE, false );
- AI_ENEMY_DEAD = false;
- clearEnemy();
- setState( "state_Idle" );
- }
-
- if ( AI_MOVE_DONE ) {
- if ( !enemyPositionValid() ) {
- clearEnemy();
- setState( "state_Idle" );
- }
- moveToEnemy();
- }
-
- lookAtEnemy( 1 );
-
- attack_flags = check_attacks();
- if ( attack_flags ) {
- do_attack( attack_flags );
- return;
- }
-
- waitFrame();
- }
- stopMove();
- }
-
- /*
- =====================
- char_sentry::find_attack_position
- =====================
- */
- boolean char_sentry::find_attack_position() {
- float attack_flags;
-
- if ( sys.getTime() < nextPositionSearch ) {
- return false;
- }
- nextPositionSearch = sys.getTime() + 1;
- locateEnemy();
- moveToAttackPosition( getEnemy(), "range_attack_loop" );
- if ( AI_DEST_UNREACHABLE ) {
- return false;
- }
-
- while( !AI_MOVE_DONE ) {
- if ( AI_ENEMY_DEAD ) {
- startSound( "snd_target_lost", SND_CHANNEL_VOICE, false );
- AI_ENEMY_DEAD = false;
- clearEnemy();
- setState( "state_Idle" );
- }
-
- lookAtEnemy( 1 );
-
- attack_flags = check_attacks();
- if ( attack_flags ) {
- do_attack( attack_flags );
- return true;
- }
-
- waitFrame();
- }
- stopMove();
-
- return true;
- }
-
-
- /*
- =====================
- char_sentry::do_attack
- =====================
- */
- void char_sentry::do_attack( float attack_flags ) {
- if ( attack_flags & ATTACK_MISSILE ) {
- combat_range();
- }
- }
-
- /*
- =====================
- char_sentry::check_attacks
- =====================
- */
- float char_sentry::check_attacks() {
- float attack_flags = 0;
-
- if ( canHitEnemyFromAnim( "range_attack_loop" ) ) {
- attack_flags |= ATTACK_MISSILE;
- }
-
- return attack_flags;
- }
-
- /*
- =====================
- char_sentry::combat_range
- =====================
- */
- void char_sentry::combat_range() {
- faceEnemy();
- fire = true;
- while( canHitEnemyFromAnim( "range_attack_loop" ) ) {
- waitFrame();
- }
- fire = false;
- waitUntil( !inAnimState( ANIMCHANNEL_TORSO, "Torso_RangeAttack" ) );
- }
-