Files
FC1/CryGame/AIHandler.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1008 lines
28 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Game Source Code
//
// File: AIHAndler.cpp
// Description: handeling AI signals, changing behaviors
//
// History:
// - Dec, 12, 2002: Created by Kirill Bulatsev
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "aihandler.h"
#include <ISound.h>
#include <IAISystem.h>
#include <ILipSync.h>
//
//------------------------------------------------------------------------------
CAIHandler::CAIHandler(void):
m_pEntity(NULL),
m_pCharacter(NULL),
m_pDefaultCharacter(NULL),
m_pBehavior(NULL),
m_pPreviousBehavior(NULL),
m_pDefaultBehavior(NULL),
m_pDEFAULTDefaultBehavior(NULL),
m_pBehaviorTable(NULL),
m_pBehaviorTableAVAILABLE(NULL),
m_pBehaviorTableINTERNAL(NULL),
m_DamageGrenadeType(-1)
{
m_pLog=NULL;
}
//
//------------------------------------------------------------------------------
CAIHandler::~CAIHandler(void)
{
if (m_pPreviousBehavior == m_pBehavior)
m_pPreviousBehavior = 0;
SAFE_RELEASE(m_pCharacter);
SAFE_RELEASE(m_pDefaultCharacter);
SAFE_RELEASE(m_pBehavior);
SAFE_RELEASE(m_pPreviousBehavior);
SAFE_RELEASE(m_pDefaultBehavior);
SAFE_RELEASE(m_pDEFAULTDefaultBehavior);
SAFE_RELEASE(m_pBehaviorTable);
SAFE_RELEASE(m_pBehaviorTableAVAILABLE);
SAFE_RELEASE(m_pBehaviorTableINTERNAL);
}
//
//------------------------------------------------------------------------------
void CAIHandler::Init(CXGame *pGame, IEntity *pEntity, ILog *pLog)
{
m_pLog=pLog;
m_pGame = pGame;
m_pScriptSystem = m_pGame->GetSystem()->GetIScriptSystem();
m_pScriptObject = pEntity->GetScriptObject();
m_pEntity = pEntity;
ILipSync *pLipSync= m_pEntity->GetCharInterface()->GetLipSyncInterface();
if (pLipSync)
pLipSync->SetCallbackSink(this);
_SmartScriptObject pCharacterTable(m_pScriptSystem, true);
//character ----------------------------------------------------------
// -- load the character only if it is used
m_pScriptSystem->GetGlobalValue("AICharacter",pCharacterTable);
_SmartScriptObject pAvailableCharacter(m_pScriptSystem, true);
pCharacterTable->GetValue("AVAILABLE",pAvailableCharacter);
const char *aiCharacterFileName=NULL;
const char *aiCharacterName=NULL;
_SmartScriptObject pEntityProperties(m_pScriptSystem, true);
_SmartScriptObject pEntityPropertiesInstance(m_pScriptSystem, true);
if(!m_pScriptObject->GetValue("Properties",pEntityProperties))
{
pLog->Log("\002 ERROR CAIHandler: can't find Properties. Entity %s", pEntity->GetName());
goto BEHAVIOR_LOADING;
}
if(!m_pScriptObject->GetValue("PropertiesInstance",pEntityPropertiesInstance))
{
pLog->Log("\002 ERROR CAIHandler: can't find PropertiesInstance. Entity %s", pEntity->GetName());
goto BEHAVIOR_LOADING;
}
if(!pEntityProperties->GetValue("aicharacter_character",aiCharacterName))
{
pLog->Log("\002 ERROR CAIHandler: can't find aicharacter_character. Entity %s", pEntity->GetName());
goto BEHAVIOR_LOADING;
}
if(!pAvailableCharacter->GetValue(aiCharacterName,aiCharacterFileName))
{
pLog->Log("\002 ERROR CAIHandler: can't find [%s] in AICharacter.AVAILABLE. Entity %s", aiCharacterName, pEntity->GetName());
goto BEHAVIOR_LOADING;
}
m_pCharacter = m_pScriptSystem->CreateEmptyObject();
if(!pCharacterTable->GetValue(aiCharacterName, m_pCharacter)) //[petar] if character script preloaded do not load
{
if(m_pScriptSystem->ExecuteFile(aiCharacterFileName,true,true)) // [petar] if not preloaded force load
{
if(!pCharacterTable->GetValue(aiCharacterName, m_pCharacter))
{
// did not find script for character
pLog->Log("\002 ERROR CAIHandler: can't find script for character [%s]. Entity %s", aiCharacterFileName, pEntity->GetName());
Release( &m_pCharacter );
}
}
else
{
// could not load script for character
pLog->Log("\002 ERROR CAIHandler: can't load script for character [%s]. Entity %s", aiCharacterFileName, pEntity->GetName());
Release( &m_pCharacter );
}
}
// default character initialization
m_pDefaultCharacter = m_pScriptSystem->CreateEmptyObject();
if(!pCharacterTable->GetValue("DEFAULT", m_pDefaultCharacter))
{
pLog->Log("\002 ERROR CAIHandler: can't find DEFAULT character. Entity %s", pEntity->GetName());
Release( &m_pDefaultCharacter );
}
BEHAVIOR_LOADING:
//behaviour ----------------------------------------------------------
m_pBehaviorTable = m_pScriptSystem->CreateEmptyObject();
if(!m_pScriptSystem->GetGlobalValue("AIBehaviour",m_pBehaviorTable))
{
Release(&m_pBehaviorTable);
pLog->Log("\002 ERROR CAIHandler: can't find AIBehaviour table ");
return;
}
m_pBehaviorTableAVAILABLE = m_pScriptSystem->CreateEmptyObject();
if(!m_pBehaviorTable->GetValue("AVAILABLE",m_pBehaviorTableAVAILABLE))
{
pLog->Log("\002 ERROR CAIHandler: can't find AVAILABLE TABLE");
Release( &m_pBehaviorTableAVAILABLE );
return;
}
m_pBehaviorTableINTERNAL = m_pScriptSystem->CreateEmptyObject();
if(!m_pBehaviorTable->GetValue("INTERNAL",m_pBehaviorTableINTERNAL))
{
pLog->Log("\002 ERROR CAIHandler: can't find AIBehavior.INTERNAL table.");
Release( &m_pBehaviorTableINTERNAL );
}
const char *aiBehaviorFileName=NULL;
const char *aiBehaviorName=NULL;
if(!pEntityPropertiesInstance->GetValue("aibehavior_behaviour",aiBehaviorName))
{
goto BEHAVIOR_DEFAULT;
}
m_FirstBehaviorName = string(aiBehaviorName);
if(!m_pBehaviorTableAVAILABLE->GetValue(aiBehaviorName,aiBehaviorFileName))
{
if (!m_pBehaviorTableINTERNAL)
{
CryError("Internal behaviour table not found. Cannot continue...");
return;
}
if(!m_pBehaviorTableINTERNAL->GetValue(aiBehaviorName,aiBehaviorFileName))
goto BEHAVIOR_DEFAULT;
}
m_pBehavior = m_pScriptSystem->CreateEmptyObject();
if(!m_pBehaviorTable->GetValue(aiBehaviorName, m_pBehavior)) //[petar] if behaviour not preloaded
{
if(m_pScriptSystem->ExecuteFile(aiBehaviorFileName,true,true)) // [petar] force that it be loaded
{
if(!m_pBehaviorTable->GetValue(aiBehaviorName, m_pBehavior))
{
// did not find script for character
// use default behavior
pLog->Log("\002 ERROR CAIHandler: can't find script for behavior [%s]. Using DEFAULT. Entity %s", aiBehaviorName, pEntity->GetName());
if(!m_pBehaviorTable->GetValue("DEFAULT", m_pBehavior))
{
pLog->Log("\002 ERROR CAIHandler: can't find DEFAULT. Entity %s", aiBehaviorName, pEntity->GetName());
Release( &m_pBehavior );
}
}
}
else
{
// could not load script for behavior
pLog->Log("\002 ERROR CAIHandler: can't load script for behavior [%s]. Entity %s", aiBehaviorFileName, pEntity->GetName());
}
}
m_CurrentBehaviorName = aiBehaviorName;
BEHAVIOR_DEFAULT:
m_pDEFAULTDefaultBehavior = m_pScriptSystem->CreateEmptyObject();
if(!m_pBehaviorTable->GetValue("DEFAULT", m_pDEFAULTDefaultBehavior))
{
pLog->Log("\002 ERROR CAIHandler: can't find DEFAULT. Entity %s", aiBehaviorName, pEntity->GetName());
Release( &m_pDEFAULTDefaultBehavior );
}
if(aiCharacterName)
{
m_DefaultBehaviorName = string(aiCharacterName) + string("Idle");
int jobFlag=0;
if( m_pBehavior && m_pBehavior->GetValue("JOB", jobFlag) )
{
// m_pBehavior->SetValue("Name", m_DefaultBehaviorName.c_str());
m_CurrentBehaviorName = m_DefaultBehaviorName;
}
m_pDefaultBehavior = m_pScriptSystem->CreateEmptyObject();
{
if (!(m_pDefaultBehavior = FindOrLoadTable(m_pBehaviorTable,m_DefaultBehaviorName.c_str())))
{
pLog->Log("\004 WARNING can't find default behaviour %s. Entity %s", m_DefaultBehaviorName.c_str(), pEntity->GetName());
Release( &m_pDefaultBehavior );
}
}
}
if(m_pBehavior)
m_pScriptObject->SetValue("Behaviour", m_pBehavior);
// if(m_pDefaultBehavior)
m_pScriptObject->SetValue("DefaultBehaviour", m_DefaultBehaviorName.c_str());
//
_SmartScriptObject pAIAnchorTable(m_pScriptSystem, true);
if(m_pScriptSystem->GetGlobalValue("AIAnchor",pAIAnchorTable))
pAIAnchorTable->GetValue("AIOBJECT_DAMAGEGRENADE", m_DamageGrenadeType);
//SoundPacks ----------------------------------------------------------
//
_SmartScriptObject pSoundPacksTable(m_pScriptSystem, true);
if(m_pScriptSystem->GetGlobalValue("SOUNDPACK",pSoundPacksTable)) // SOUNDPACK table
{
const char *aiSoundPackName=NULL;
if(pEntityProperties->GetValue("SoundPack",aiSoundPackName))
{
m_pSoundPackTable = FindOrLoadTable( pSoundPacksTable, aiSoundPackName );
}
}
//AniPacks ----------------------------------------------------------
//
_SmartScriptObject pAnimPacksTable(m_pScriptSystem, true);
if(m_pScriptSystem->GetGlobalValue("ANIMATIONPACK",pAnimPacksTable)) // SOUNDPACK table
{
const char *aiAnimPackName=NULL;
if(pEntityProperties->GetValue("AnimPack",aiAnimPackName))
{
m_pAnimationPackTable = FindOrLoadTable( pAnimPacksTable, aiAnimPackName );
}
}
}
//
//------------------------------------------------------------------------------
void CAIHandler::AIMind( SOBJECTSTATE *state )
{
int expression=1;
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
HSCRIPTFUNCTION handlerFunc=NULL;
string event_string;
if( state->bHaveTarget )
{
if( state->bSound )
{
expression = 2;
if( state->fThreat > state->fInterest )
{
FRAME_PROFILER( "AI_OnThreateningSoundHeard",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnThreateningSoundHeard", &state->fDistanceFromTarget );
event_string = "OnThreateningSoundHeard";
}
else
{
FRAME_PROFILER( "AI_OnInterestingSoundHeard",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnInterestingSoundHeard", &state->fDistanceFromTarget );
event_string = "OnInterestingSoundHeard";
}
}
else if( state->nTargetType == AIOBJECT_PLAYER ) //-- player seen
{
expression = 2;
if( state->bMemory )
CallBehaviorOrDefault( "OnPlayerMemory" );
else
{
FRAME_PROFILER( "AI_OnPlayerSeen",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnPlayerSeen", &state->fDistanceFromTarget );
expression = 3;
event_string = "OnPlayerSeen";
}
}
else if( state->nTargetType == m_DamageGrenadeType ) //-- grenade seen
{
FRAME_PROFILER( "AI_OnGrenadeSeen",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnGrenadeSeen", &state->fDistanceFromTarget , false);
event_string = "OnGrenadeSeen";
}
// else if(state->nTargetType == AIOBJECT_PLAYER ) //-- Grenade seen
else
{
if( state->fThreat > state->fInterest )
{
if( state->bMemory )
{
FRAME_PROFILER( "AI_OnEnemyMemory",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnEnemyMemory", &state->fDistanceFromTarget );
expression = 2;
event_string = "OnEnemyMemory";
}
else
{
FRAME_PROFILER( "AI_OnPlayerSeen2",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnPlayerSeen",&state->fDistanceFromTarget);
int gunout;
if (!m_pEntity->GetScriptObject()->GetValue("AI_GunOut",gunout))
{
IPipeUser *pPuppet;
if (m_pEntity->GetAI()->GetType()== AIOBJECT_PUPPET)
if (m_pEntity->GetAI()->CanBeConvertedTo(AIOBJECT_PIPEUSER,(void**)&pPuppet))
pPuppet->InsertSubPipe(0,"DRAW_GUN");
}
expression = 3;
event_string = "OnPlayerSeen";
}
}
else
if( state->fInterest > 0 ) //
{
FRAME_PROFILER( "AI_OnSomethingSeen",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnSomethingSeen" );
expression = 2;
event_string = "OnSomethingSeen";
}
}
}
else //-- do not have a target
{
FRAME_PROFILER( "AI_OnNoTarget",m_pGame->GetSystem(),PROFILE_AI );
CallBehaviorOrDefault( "OnNoTarget" );
event_string = "OnNoTarget";
}
{
FRAME_PROFILER( "AIExpressionScriptEvent",m_pGame->GetSystem(),PROFILE_AI );
m_pEntity->SendScriptEvent(ScriptEvent_Expression, expression );
}
if(CheckCharacter( event_string.c_str() ))
DoChangeBehavior( );
}
//
//------------------------------------------------------------------------------
void CAIHandler::AISignal( int signalID, const char * signalText, IEntity *pSender )
{
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
if(signalID == -2)
signalText = "OnNoHidingPlace";
else if(signalID == -50)
signalText = "OnNoFormationPoint";
if( !signalText )
return;
HSCRIPTFUNCTION singnalHandler=NULL;
//m_pLog->Log("\002 >> %s", signalText);
if( !CallScript(m_pBehavior, signalText, NULL, pSender) )
// try default in behavior
if( !CallScript(m_pDefaultBehavior, signalText, NULL, pSender) )
// try global defaul
CallScript(m_pDEFAULTDefaultBehavior, signalText, NULL, pSender);
if(CheckCharacter( signalText ))
DoChangeBehavior( );
}
//
//------------------------------------------------------------------------------
bool CAIHandler::CheckCharacter( const char* signalText )
{
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
if( strlen(signalText)<2 )
return false;
_SmartScriptObject pCharacterTable(m_pScriptSystem, true);
_SmartScriptObject pNextBehavior(m_pScriptSystem, true);
const char *behaviorName=NULL;
const char *nextBehaviorName=NULL;
if( m_pBehavior && m_pCharacter )
{
behaviorName = m_CurrentBehaviorName.c_str();//m_pBehavior->GetValue("Name", behaviorName);
if(m_pCharacter->GetValue(behaviorName, pCharacterTable))
{
if(pCharacterTable->GetValue(signalText, nextBehaviorName))
{
m_NextBehaviorName = nextBehaviorName;
{
if (m_pLog->GetVerbosityLevel())
{
FRAME_PROFILER( "Logging of the character change",m_pGame->GetSystem(),PROFILE_AI );
if(m_pEntity && m_pEntity->GetName() && behaviorName && nextBehaviorName && signalText)
m_pLog->LogToConsole("\004 entity %s changin behavior from %s to %s on signal %s",
m_pEntity->GetName(), behaviorName, nextBehaviorName, signalText );
}
}
return true;
}
}
}
if(!m_pDefaultCharacter)
return false;
bool tableIsValid = false;
if(m_pBehavior /*&& m_pBehavior->GetValue("Name", behaviorName)*/)
{
behaviorName = m_CurrentBehaviorName.c_str();
if(!(tableIsValid = m_pDefaultCharacter->GetValue(behaviorName, pCharacterTable)))
tableIsValid = m_pDefaultCharacter->GetValue("NoBehaviorFound", pCharacterTable);
}
else
tableIsValid = m_pDefaultCharacter->GetValue("NoBehaviorFound", pCharacterTable);
if( tableIsValid )
if(pCharacterTable->GetValue(signalText, nextBehaviorName))
{
m_NextBehaviorName = nextBehaviorName;
{
if (m_pLog->GetVerbosityLevel())
{
FRAME_PROFILER( "Logging of DEFAULT character change",m_pGame->GetSystem(),PROFILE_AI );
if(m_pEntity && m_pEntity->GetName() && behaviorName && nextBehaviorName && signalText)
m_pLog->Log("\004 entity %s changin behavior from %s to %s on signal %s [DEFAULT character]",
m_pEntity->GetName(), behaviorName, nextBehaviorName, signalText );
}
}
return true;
}
return false;
}
//
//------------------------------------------------------------------------------
void CAIHandler::DoChangeBehavior( )
{
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
// if (m_NextBehaviorName == m_CurrentBehaviorName)
// return;
IScriptObject *pNextBehavior=NULL;
if( m_NextBehaviorName == "PREVIOUS")
// !strcmp(nextBehaviorName, "PREVIOUS") )
{
pNextBehavior = m_pPreviousBehavior;
if (pNextBehavior)
{
const char* nextBehaviorName;
pNextBehavior->GetValue("Name",nextBehaviorName);
if (m_CurrentBehaviorName == nextBehaviorName)
return;
m_CurrentBehaviorName = nextBehaviorName;
}
}
else
{
if( m_NextBehaviorName == "FIRST" )
{
m_NextBehaviorName = m_FirstBehaviorName;
}
const char* nextBehaviorName = m_NextBehaviorName.c_str();
m_CurrentBehaviorName = m_NextBehaviorName;
pNextBehavior = m_pScriptSystem->CreateEmptyObject();
if( !m_pBehaviorTable->GetValue(nextBehaviorName,pNextBehavior) )
{
//[petar] if behaviour not preloaded then force loading of it
FRAME_PROFILER( "On-DemandBehaviourLoading",m_pGame->GetSystem(),PROFILE_AI );
const char *aiBehaviorFileName;
if(m_pBehaviorTableAVAILABLE->GetValue(nextBehaviorName,aiBehaviorFileName))
{
//fixme - problem with reloading!!!!
m_pScriptSystem->ExecuteFile(aiBehaviorFileName,true,true);
}
else if(m_pBehaviorTableINTERNAL->GetValue(nextBehaviorName,aiBehaviorFileName))
{
//fixme - problem with reloading!!!!
m_pScriptSystem->ExecuteFile(aiBehaviorFileName,true,true);
}
}
if( !m_pBehaviorTable->GetValue(nextBehaviorName,pNextBehavior) )
{
Release( &pNextBehavior );
if(m_pEntity && m_pEntity->GetName() && m_NextBehaviorName.c_str())
{
m_pLog->LogToFile("\004 entity %s faild to change behavior to %s.",
m_pEntity->GetName(), m_NextBehaviorName.c_str());
// m_pGame->GetSystem()->GetILog()->Log("\004 entity %s faild to change behavior.",
// m_pEntity->GetName());
}
}
}
if (pNextBehavior == m_pBehavior)
{
if (pNextBehavior!=m_pPreviousBehavior)
Release(&pNextBehavior);
return;
}
int job=0;
if (m_pBehavior && m_pBehavior->GetValue( "JOB", job ))
{
ICryCharInstance *pCharacter = m_pEntity->GetCharInterface()->GetCharacter(0);
if (pCharacter)
{
pCharacter->StopAnimation(3);
pCharacter->StopAnimation(4);
}
CallBehaviorOrDefault("OnJobExit",NULL,false);
if (pNextBehavior && !pNextBehavior->GetValue("JOB",job))
{
// stop any ongoing conversations
HSCRIPTFUNCTION stopConvFunction=NULL;
if( m_pScriptObject->GetValue("StopConversation", stopConvFunction) )
{
m_pScriptSystem->BeginCall(stopConvFunction);
m_pScriptSystem->PushFuncParam(m_pScriptObject);
m_pScriptSystem->EndCall();
}
}
}
if(pNextBehavior)
{
if (m_pBehavior)
{
int remember_previous;
if (!m_pBehavior->GetValue("NOPREVIOUS",remember_previous))
{
if((m_pPreviousBehavior != pNextBehavior) && (m_pPreviousBehavior!=m_pBehavior))
Release( &m_pPreviousBehavior );
m_pPreviousBehavior = m_pBehavior;
}
}
else
{
m_pLog->Log("\001 [AIERROR] entity %s had 0 behaviour but behaviour name %s",
m_pEntity->GetName(),m_CurrentBehaviorName.c_str() );
}
m_pBehavior = pNextBehavior;
m_pScriptObject->SetValue("Behaviour", m_pBehavior);
int jobFlag=0;
if( m_pBehavior->GetValue("JOB", jobFlag) )
{
m_CurrentBehaviorName = m_DefaultBehaviorName;
// m_pBehavior->SetValue("Name", m_DefaultBehaviorName.c_str());
}
const char *eventToCallName=NULL;
if(m_pScriptObject->GetValue("EventToCall", eventToCallName))
{
HSCRIPTFUNCTION functionToCall=NULL;
CallScript( m_pBehavior, eventToCallName);
m_pScriptObject->SetValue("EventToCall", "");
}
}
}
//
//------------------------------------------------------------------------------
void CAIHandler::CallBehaviorOrDefault( const char* signalText, float *value, bool bJob )
{
HSCRIPTFUNCTION handlerFunc=NULL;
int job;
if( m_pBehavior )
{
if(!CallScript( m_pBehavior, signalText, value ))
{
if (bJob)
{
if (m_pBehavior->GetValue( "JOB", job ))
CallScript( m_pDefaultBehavior, signalText, value );
}
else
CallScript( m_pDefaultBehavior, signalText, value );
}
}
}
//
//------------------------------------------------------------------------------
bool CAIHandler::CallScript( IScriptObject *scriptTable, const char* funcName, float *value, IEntity *pSender )
{
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
HSCRIPTFUNCTION functionToCall=NULL;
if( scriptTable )
if( scriptTable->GetValue(funcName, functionToCall) )
{
// string str="Calling behavior >> ";
// str+= funcName;
// FRAME_PROFILER( "Calling behavior signal",m_pGame->GetSystem(),PROFILE_AI );
// FRAME_PROFILER( str.c_str(),m_pGame->GetSystem(),PROFILE_AI );
// only use strings which are known at compile time...
// not doing so causes a stack corruption in the frame profiler -- CW
// FRAME_PROFILER( funcName,m_pGame->GetSystem(),PROFILE_AI );
//sprintf(m_szSignalName,"AISIGNAL: %s",funcName);
FRAME_PROFILER( "AISIGNAL" , m_pGame->GetSystem(), PROFILE_AI );
m_pScriptSystem->BeginCall( functionToCall );
m_pScriptSystem->PushFuncParam(scriptTable); // self
m_pScriptSystem->PushFuncParam(m_pScriptObject);
if(pSender)
m_pScriptSystem->PushFuncParam(pSender->GetScriptObject());
else if( value )
m_pScriptSystem->PushFuncParam( *value );
m_pScriptSystem->EndCall();
return true;
}
return false;
}
//
//------------------------------------------------------------------------------
void CAIHandler::Release( )
{
}
//
//------------------------------------------------------------------------------
void CAIHandler::Release( IScriptObject **obj )
{
if((*obj) == NULL)
return;
(*obj)->Release();
(*obj) = NULL;
}
//
//------------------------------------------------------------------------------
IScriptObject *CAIHandler::GetMostLikelyTable( IScriptObject *table )
{
int readcount = table->Count();
if (!readcount)
return 0;
IScriptObject *pSelectedTable = m_pScriptSystem->CreateEmptyObject();
int probability = rand()%999;
int randValue;
int curValue;
int i;
int sum = 0;
for (i=1;i<table->Count()+1;i++)
{
table->GetAt(i,pSelectedTable);
float fProb=0;
pSelectedTable->GetValue("PROBABILITY",fProb);
sum+=(int)(fProb);
if (sum>probability)
break;
}
if (i==table->Count()+1)
{
pSelectedTable->Release();
return 0 ;
}
else
randValue = i;
table->GetAt(randValue,pSelectedTable);
if (pSelectedTable->GetValue("USED",curValue))
{
int cnt = 0;
while (pSelectedTable->GetValue("USED",curValue) && cnt<readcount)
{
randValue++;
if (randValue>readcount)
randValue = 1;
table->GetAt(randValue,pSelectedTable);
cnt++;
}
if (cnt<readcount)
{
pSelectedTable->SetValue("USED",1);
return pSelectedTable;
}
else
{
for (int i=1;i<= readcount;i++)
table->SetToNull("USED");
pSelectedTable->SetValue("USED",1);
return pSelectedTable;
}
}
else
{
pSelectedTable->SetValue("USED",1);
return pSelectedTable;
}
return 0;
}
//
//------------------------------------------------------------------------------
void CAIHandler::DoReadibilityPack( const char* text )
{
FUNCTION_PROFILER( m_pGame->GetSystem(),PROFILE_AI );
if( m_pAnimationPackTable)
{
_SmartScriptObject pAnimationDirective(m_pScriptSystem, true);
if( m_pAnimationPackTable->GetValue( text, pAnimationDirective ) )
{
IScriptObject *pMostLikelyTable = 0;
if(pMostLikelyTable = GetMostLikelyTable( pAnimationDirective ))
{
const char* aniName;
int layer;
float blendTime;
pMostLikelyTable->GetValue( "animationName", aniName );
pMostLikelyTable->GetValue( "layer", layer );
pMostLikelyTable->GetValue( "blend_time", blendTime );
IPipeUser *puppet;
if(m_pEntity->GetAI()->CanBeConvertedTo(AIOBJECT_PIPEUSER, (void**)&puppet))
{
IGoalPipe *pipe=m_pGame->GetSystem()->GetAISystem()->CreateGoalPipe( "special_pipe_anipack_wait" );
GoalParameters par;
par.fValue = m_pEntity->GetAnimationLength(aniName);
pipe->PushGoal( "timeout", 1, par );
SAIEVENT sev;
sev.fInterest = par.fValue;
m_pEntity->GetAI()->Event(AIEVENT_ONBODYSENSOR,&sev);
puppet->InsertSubPipe(0,"special_pipe_anipack_wait");
}
m_pEntity->StartAnimation( 0, aniName, layer, blendTime );
}
if (pMostLikelyTable)
pMostLikelyTable->Release();
}
}
//_SmartScriptObject pSoundPack(m_pScriptSystem, true);
if( m_pSoundPackTable )
{
ISoundSystem *pSoundSystem=m_pGame->GetSystem()->GetISoundSystem();
if (!pSoundSystem) // || !m_pGame->m_p3DEngine)
return; // no sound can be played anyway
/*
IVisArea *pListenerArea=pSoundSystem->GetListenerArea();
// check if the sound is occluded or listener inside / outside etc.
Vec3d vPos=m_pEntity->GetPos();
IVisArea *pArea=m_pGame->m_p3DEngine->GetVisAreaFromPos(vPos);
if (pArea)
{
if (!pListenerArea)
return; // from outside to inside
if (!m_pGame->m_p3DEngine->IsVisAreasConnected(pArea,pListenerArea,1,true))
return;
}
else
{
if (pListenerArea)
return; // from inside to outside
}
*/
_SmartScriptObject pSoundDirective(m_pScriptSystem, true);
if( m_pSoundPackTable->GetValue( text, pSoundDirective ) )
{
IScriptObject *pMostLikelyTable=0;
if(pMostLikelyTable = GetMostLikelyTable( pSoundDirective ))
{
const char* sndName;
int volume;
float min;
float max;
const char *snd2DName;
int snd2Dvolume;
int temp;
bool bSkipSound=false;
_smart_ptr<ISound> pSound;
pMostLikelyTable->GetValue( "soundFile", sndName );
pMostLikelyTable->GetValue( "Volume", volume );
pMostLikelyTable->GetValue( "min", min );
pMostLikelyTable->GetValue( "max", max );
if (pMostLikelyTable->GetValue("NOMUTANT",temp))
{
IAIObject *pAIObject = m_pEntity->GetAI();
if (pAIObject)
{
IPipeUser *pPipeUser;
if (pAIObject->CanBeConvertedTo(AIOBJECT_PIPEUSER,(void**)&pPipeUser))
{
IAIObject *pAttTarget = pPipeUser->GetAttentionTarget();
if (pAttTarget)
{
if (pAttTarget->GetType()==AIOBJECT_PUPPET && pAttTarget->GetAssociation())
{
IEntity *pTargetEntity = (IEntity*)pAttTarget->GetAssociation();
if (pTargetEntity)
{
int ismutant;
if (pTargetEntity->GetScriptObject())
{
if (pTargetEntity->GetScriptObject()->GetValue("MUTANT",ismutant))
bSkipSound = true;
}
}
}
}
}
}
}
if (!bSkipSound)
{
FRAME_PROFILER( "Lipsych AI Sound",m_pGame->GetSystem(),PROFILE_AI );
//m_pGame->GetSystem()->GetILog()->Log("\004 playin readibility sound %s",sndName);
if(m_pEntity && m_pEntity->GetCharInterface())
{
ILipSync *pLipSync=m_pEntity->GetCharInterface()->GetLipSyncInterface();
if (!pLipSync)
{
GameWarning("Could not create lip-sync interface ! Is this entity a character ?");
return;
}
//if (!pLipSync->LoadDialog(sndName, volume, min, max, 30.f, FLAG_SOUND_UNSCALABLE))
if (!pLipSync->LoadDialog(sndName, volume, min, max, 30.f, 0))
{
GameWarning("CLipSync::LoadDialog failed !");
return;
}
}
if (pMostLikelyTable->GetValue( "radiosoundFile", snd2DName ))
{
if (pMostLikelyTable->GetValue( "radioVolume", snd2Dvolume ))
{
pSound=pSoundSystem->LoadSound(snd2DName,FLAG_SOUND_2D|FLAG_SOUND_STEREO);
pSound->SetVolume(snd2Dvolume);
pSound->Play();
}
}
}
/*if (pSound)
{
pSound->SetVolume((int)volume);
pSound->SetMinMaxDistance(min,max/2.0f);
// pSound->SetMaxSoundDistance(max/2.0f); // :)
pSound->SetSoundPriority(0);
pSound->SetLoopMode( false );
pSound->SetPosition( m_pEntity->GetPos() );
pSound->Play();
//m_pGame->GetSystem()->GetILog()->Log("\002 CAIHandler: Readability sound [%s]. Entity %s", sndName, m_pEntity->GetName());
}
*/ }
if (pMostLikelyTable)
pMostLikelyTable->Release();
}
}
}
//
//------------------------------------------------------------------------------
IScriptObject *CAIHandler::FindOrLoadTable( IScriptObject * globalTable, const char* nameToGet )
{
IScriptObject *resTable = m_pScriptSystem->CreateEmptyObject();;
if(globalTable->GetValue(nameToGet, resTable))
return resTable;
_SmartScriptObject pAvailableTable(m_pScriptSystem, true);
globalTable->GetValue("AVAILABLE",pAvailableTable);
const char *fileName=NULL;
if(!pAvailableTable->GetValue(nameToGet,fileName))
{
// pLog->Log("\002 ERROR CAIHandler: can't find [%s] in AICharacter.AVAILABLE. Entity %s", aiCharacterName, pEntity->GetName());
_SmartScriptObject pInternalTable(m_pScriptSystem, true);
globalTable->GetValue("INTERNAL",pInternalTable);
if(!pInternalTable->GetValue(nameToGet,fileName))
{
Release( &resTable );
return resTable;
}
}
if(m_pScriptSystem->ExecuteFile(fileName,true,false))
{
if(!globalTable->GetValue(nameToGet, resTable))
{
// did not find script for character
// pLog->Log("\002 ERROR CAIHandler: can't find script for character [%s]. Entity %s", aiCharacterFileName, pEntity->GetName());
Release( &resTable );
}
}
else
{
// could not load script for character
// pLog->Log("\002 ERROR CAIHandler: can't load script for character [%s]. Entity %s", aiCharacterFileName, pEntity->GetName());
Release( &resTable );
}
return resTable;
}
//
//------------------------------------------------------------------------------
void CAIHandler::SetCurrentBehaviourVariable(const char * szVariableName, float fValue)
{
if (m_pBehavior)
m_pBehavior->SetValue(szVariableName,fValue);
}
void CAIHandler::OnDialogLoaded(struct ILipSync *pLipSync)
{
if (!pLipSync->PlayDialog())
{
GameWarning("CLipSync::PlayDialog failed !");
return ;
}
}
void CAIHandler::OnDialogFailed(struct ILipSync *pLipSync)
{
}