doom3-bfg/base/script/ai_character_prone.script
2022-08-27 13:19:00 +02:00

303 lines
6.5 KiB
Text

/***********************************************************************
ai_character_prone.script
editor keys:
"die_after_speaking" character dies after being talked to twice.
***********************************************************************/
object ai_character_prone : ai {
float talkMode;
float talk_secondary_index;
//
// States
//
void state_Idle();
void state_Pain();
void state_Dead();
void state_Killed();
//
// actions
//
void idle_talk();
void init();
// torso anim states
void Torso_TalkPrimary();
void Torso_TalkTrigger();
void Torso_TalkSecondary();
void Torso_Idle();
void Torso_Dead();
void Torso_PlayDead();
void Torso_Pain();
};
/***********************************************************************
Torso animation control
***********************************************************************/
void ai_character_prone::Torso_Dead() {
stopAnim( ANIMCHANNEL_TORSO, 4 );
playAnim( ANIMCHANNEL_HEAD, "dead" );
waitFrame();
finishAction( "dead" );
}
void ai_character_prone::Torso_PlayDead() {
setBoneMod( false );
if ( hasAnim( ANIMCHANNEL_HEAD, "dead" ) ) {
playAnim( ANIMCHANNEL_HEAD, "dead" );
}
if ( hasAnim( ANIMCHANNEL_TORSO, "dead" ) ) {
playAnim( ANIMCHANNEL_TORSO, "dead" );
}
waitFrame();
finishAction( "dead" );
}
void ai_character_prone::Torso_Idle() {
idleAnim( ANIMCHANNEL_TORSO, "idle" );
while( 1 ) {
waitFrame();
}
}
void ai_character_prone::Torso_TalkPrimary() {
playAnim( ANIMCHANNEL_TORSO, "talk_primary" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
waitFrame();
}
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
}
void ai_character_prone::Torso_TalkTrigger() {
playAnim( ANIMCHANNEL_TORSO, "talk_trigger" );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
waitFrame();
}
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
}
void ai_character_prone::Torso_TalkSecondary() {
playAnim( ANIMCHANNEL_TORSO, "talk_secondary" + talk_secondary_index );
talk_secondary_index = talk_secondary_index + 1;
if ( !hasAnim( ANIMCHANNEL_TORSO, "talk_secondary" + talk_secondary_index ) ) {
talk_secondary_index = 1;
}
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
waitFrame();
}
if ( getIntKey( "die_after_speaking" ) ) {
playAnim( ANIMCHANNEL_HEAD, "dead" );
animState( ANIMCHANNEL_TORSO, "Torso_PlayDead", 0 );
} else {
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
}
}
void ai_character_prone::Torso_Pain() {
string animname;
float nextpain;
float currenttime;
stopSound( SND_CHANNEL_VOICE, false );
animname = getPainAnim();
playAnim( ANIMCHANNEL_TORSO, animname );
while( !animDone( ANIMCHANNEL_TORSO, 0 ) ) {
waitFrame();
}
finishAction( "pain" );
setState( "state_Dead" );
animState( ANIMCHANNEL_TORSO, "Torso_PlayDead", 0 );
}
/***********************************************************************
AI
***********************************************************************/
/*
=====================
ai_character_prone::init
=====================
*/
void ai_character_prone::init() {
talkMode = getIntKey( "talk_mode" );
talk_secondary_index = 1;
setBoneMod( true );
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
setState( "state_Idle" );
}
/*
=====================
ai_character_prone::state_Idle
=====================
*/
void ai_character_prone::state_Idle() {
AI_ACTIVATED = false;
while( !AI_ACTIVATED ) {
if ( AI_PAIN ) {
setState( "state_Pain" );
}
waitFrame();
}
setTalkTarget( $player1 );
idle_talk();
while( 1 ) {
while( !AI_TALK ) {
if ( AI_PAIN ) {
setState( "state_Pain" );
}
waitFrame();
}
idle_talk();
}
}
/*
=====================
ai_character_prone::state_Pain
=====================
*/
void ai_character_prone::state_Pain() {
setTalkState( TALK_BUSY );
stopMove();
animState( ANIMCHANNEL_TORSO, "Torso_Pain", 2 );
waitAction( "pain" );
setState( "state_Dead" );
}
/*
=====================
ai_character_prone::state_Dead
=====================
*/
void ai_character_prone::state_Dead() {
setTalkState( TALK_DEAD );
setBoneMod( false );
animState( ANIMCHANNEL_TORSO, "Torso_PlayDead", 0 );
stopThinking();
}
/*
=====================
ai_character_prone::state_Killed
=====================
*/
void ai_character_prone::state_Killed() {
animState( ANIMCHANNEL_TORSO, "Torso_Dead", 0 );
waitAction( "dead" );
stopThinking();
}
/*
=====================
ai_character_prone::idle_talk
=====================
*/
void ai_character_prone::idle_talk() {
float talktime;
float endtime;
float talkradius;
float currentTime;
entity talkTo;
talkTo = getTalkTarget();
lookAt( talkTo, 5 );
// wait at least half a second
wait( 0.5 );
talkradius = getFloatKey( "talkradius" );
if ( talkMode == 0 ) {
animState( ANIMCHANNEL_TORSO, "Torso_TalkTrigger", 4 );
talkMode = 1;
setTalkState( TALK_BUSY );
while( inAnimState( ANIMCHANNEL_TORSO, "Torso_TalkTrigger" ) ) {
if ( AI_PAIN ) {
setState( "state_Pain" );
}
if ( distanceTo( talkTo ) > talkradius ) {
break;
}
lookAt( talkTo, 2 );
waitFrame();
}
setTalkState( TALK_OK );
} else if ( talkMode == 1 ) {
animState( ANIMCHANNEL_TORSO, "Torso_TalkPrimary", 4 );
talkMode = 2;
setTalkState( TALK_BUSY );
while( inAnimState( ANIMCHANNEL_TORSO, "Torso_TalkPrimary" ) ) {
if ( AI_PAIN ) {
setState( "state_Pain" );
}
if ( distanceTo( talkTo ) > talkradius ) {
break;
}
lookAt( talkTo, 2 );
waitFrame();
}
setTalkState( TALK_OK );
} else if ( getFloatKey( "die_after_speaking" ) ) {
setTalkState( TALK_BUSY );
animState( ANIMCHANNEL_TORSO, "Torso_TalkSecondary", 4 );
while( !inAnimState( ANIMCHANNEL_TORSO, "Torso_PlayDead" ) ) {
lookAt( talkTo, 0.1 );
waitFrame();
}
setState( "state_Dead" );
} else {
setTalkState( TALK_BUSY );
animState( ANIMCHANNEL_TORSO, "Torso_TalkSecondary", 4 );
while( inAnimState( ANIMCHANNEL_TORSO, "Torso_TalkSecondary" ) ) {
if ( AI_PAIN ) {
setState( "state_Pain" );
}
if ( distanceTo( talkTo ) > talkradius ) {
break;
}
lookAt( talkTo, 2 );
waitFrame();
}
setTalkState( TALK_OK );
}
animState( ANIMCHANNEL_TORSO, "Torso_Idle", 0 );
setTalkTarget( $null_entity );
talktime = getFloatKey( "talktime" );
currentTime = sys.getTime();
endtime = currentTime + talktime;
while( ( currentTime < endtime ) && ( distanceTo( talkTo ) <= talkradius ) ) {
lookAt( talkTo, 2 );
if ( AI_PAIN ) {
setState( "state_Pain" );
}
if ( AI_TALK ) {
return;
}
waitFrame();
currentTime = sys.getTime();
}
lookAt( self, 0 );
stopSound( SND_CHANNEL_VOICE, false );
}