#define D_StdGame_StructureDefine
#define D_Brain_StructureDefine
 
#include "ToolsCPA.h"
 
#include "Options/Options.h"
#include "Macros.h"
 
#include "Structur/input_s.h"
#include "Structur/ErrGame.h"
#include "Structur/EngMode.h"
#include "Actions/AllActs.h"
 
#include "structur/objects.h"
#include "STRUCTUR/StdObjSt.h"
#include "Structur/State.h"
 
#include "GameEng.h"
#include "ia_dnm.h"
#include "PlayAnim/PlayAnim.h"
 
#include "safe.h" /*BART*/
 
#include "PRF.h"
 
/*ANNECY 27/11/97 CT{*/
#include "ia_dnm1.cxx"
/*ENDANNECY CT}*/
 
//XB 05/08/99
#include "AI/AIBase/Specif/AIOption.h"
//End XB
 
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
	extern void GAM_fn_vRasterDumpUpdate(unsigned long,unsigned long,unsigned long,unsigned long,unsigned long);
#endif
 
/*-----------------------------------------------------------------------------
 *  Description :   Inits the array of functions for mechanics.
 *-----------------------------------------------------------------------------
 *  Input :         pointer on the list of PAirOfFunctions
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 05/02/97            Author : Frederic
 *-----------------------------------------------------------------------------
 *  Modification date : 13/06/97                 Modification Author : S Leroy
 *  Modifications :
 *-----------------------------------------------------------------------------
 *  Modification date : 30/06/98                 Modification Author : J Thenoz
 *  Modifications : parsing functions disapear
 *---------------------------------------------------------------------------*/
void InitArrayOfDynamicFunction(struct DNM_stDynamics* (**p_fnDynamicFunction)(struct DNM_stDynamics*,HIE_tdxHandleToSuperObject,struct DNM_stParsingDatas *,DNM_tdxHandleToMecIdentityCard,MTH_tdxReal) )
{
	p_fnDynamicFunction[DNM_eCamera] = DNM_p_stDynamicsCameraMechanics;
	p_fnDynamicFunction[DNM_eBase] = MEC_p_stDynamicsBaseMechanics;
}
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Gets the handle on Identity Card from a perso
 *-----------------------------------------------------------------------------
 *  Input :         Handle on the SuperObject
 *  Output :        Handle
 *-----------------------------------------------------------------------------
 *  Creation date : 07/04/97            Author :Frederic
 *-----------------------------------------------------------------------------
 *  Modification date :                 Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
 
 
 DNM_tdxHandleToMecIdentityCard  fn_h_GetCurrentDNMIdCard(HIE_tdxHandleToSuperObject p_SuperObjPerso)
 {
 
	 tdxHandleToState hCurrentState;
 
	 hCurrentState = fn_h3dDataGetCurrentState(M_GetMSHandle(p_SuperObjPerso,3dData));
	 if( hCurrentState==NULL)
		 return NULL;
	 return fn_hGetStateMechanicsIdCard(hCurrentState);
 }
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Transfers the speed information from the Anim-Player
 *					to the Mechanics Structure
 *-----------------------------------------------------------------------------
 *  Input :         Handle on the SuperObject
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 10/03/97            Author :Frederic
 *-----------------------------------------------------------------------------
 *  Modification date :                 Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
/* MR0605*/
void fn_vTransferSpeedInformationPLA_DNM(HIE_tdxHandleToSuperObject p_SuperObjPerso,short sLastFrame)
{
 MS_tdxHandleToDynam h_Dynam;
 DNM_tdstDynamics *p_stDynamics;
 MTH3D_tdstVector  *p_MthVector;
 MTH3D_tdstMatrix *p_MthRotationMatrix;
 
 
  if((h_Dynam = M_GetMSHandle(p_SuperObjPerso,Dynam)) == NULL )
	  return;
  if((p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam)) == NULL)
  	return;
 
  /* MR0605*/
  p_MthVector = PLA_fn_stGetLinearSpeedVector(p_SuperObjPerso,sLastFrame);
  p_MthRotationMatrix =  PLA_fn_stGetAngularSpeedMatrix(p_SuperObjPerso,sLastFrame);
 
  if(p_MthVector)
  {
		/* JT 211298*/
	 /*if (!MTH3D_M_bIsNullVector(p_MthVector))*/ DNM_M_vDynamicsSetSpeedAnim ( p_stDynamics, p_MthVector );
  }
 
  if(p_MthRotationMatrix)
		MEC_vImposeRelativeRotation ( p_stDynamics, p_MthRotationMatrix );
}
 
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Makes a character react: Intelligence / Reflex
 *-----------------------------------------------------------------------------
 *  Input :         a pointer on the SO
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : ../10/96            Author :Frédéric
 *-----------------------------------------------------------------------------
 *  Modification date : 21/10/97        Modification Author : Olivier Didelot
 *  Modifications :
 *---------------------------------------------------------------------------*/
void fn_vMakeCharacterThink(HIE_tdxHandleToSuperObject p_stSuperObj)
{
	AI_tdstMind *p_stMind;
	MS_tdxHandleToBrain h_Brain;
//XB 05/08/99
#ifndef D_THROW_CFAST_AI
//End XB
	static char cFastC = 1;
//XB 05/08/99
#endif /* D_THROW_CFAST_AI */
//End XB
    struct AI_tdstAIModel_ *p_stAIModel;
	/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
	long lDuration;
#endif
	/* END ANNECY MT }*/
	
	fn_v3dDataUpdateBrainCounter(p_stSuperObj);
	
	if(!fn_b3dDataCanComputeBrain(p_stSuperObj))
		return;
	if((h_Brain = M_GetMSHandle(p_stSuperObj,Brain)) == NULL )
		return;
	if((p_stMind = M_pstGetMindOfBrain(h_Brain)) == NULL)
		return;
	
	p_stAIModel = p_stMind->p_stAIModel;
	
	/* A global value depending on aleat number of instance and current trame counter */
	fn_v3dDataUpdateMainBrainCounter(M_GetMSHandle(p_stSuperObj,3dData));
	gcGlobAleat = (char) fn_uw3dDataGetMainBrainCounter(M_GetMSHandle(p_stSuperObj,3dData));
	
	/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
  #pragma warning (disable : 4146)
	lDuration = -TMR_fn_ulFastGetInternalCounter();		
  #pragma warning (default : 4146)
#endif
	/* END ANNECY MT }*/
    PRF_fn_vStartChrono( PRF_C_ulFctAI, p_stSuperObj );
	
//XB 05/08/99
#ifndef D_THROW_CFAST_AI
//End XB
	/* CFast. Don't do reflex and intelligence, but only call big C function */
	if ( cFastC && p_stAIModel && (p_stAIModel->CFast_bIsC) && (p_stAIModel->CFast_lFunction) )
	{
		CFast_gast_ArrayFunctions[p_stAIModel->CFast_lFunction].mfnv_Function(p_stSuperObj);
	}
	else
//XB 05/08/99
#endif /* D_THROW_CFAST_AI */
//End XB
	{
		if (!fn_bDoReflexPerso(p_stSuperObj))
		{
			/* because of killperso*/
			if((h_Brain = M_GetMSHandle(p_stSuperObj,Brain)) != NULL )
				if((p_stMind = M_pstGetMindOfBrain(h_Brain)) != NULL)
					fn_bDoIntelligencePerso(p_stSuperObj);
		}
	}
	
	PRF_fn_vStopChrono( PRF_C_ulFctAI, p_stSuperObj );
	
	/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
	lDuration += TMR_fn_ulFastGetInternalCounter();		
	if(M_GetMSHandle(p_stSuperObj,StandardGame))
	{
		GAM_fn_vRasterDumpUpdate((unsigned long)fn_otStandardGameGetModelType(M_GetMSHandle(p_stSuperObj,StandardGame)),lDuration,0,0,0);
	}
#endif
	/* END ANNECY MT }*/
	return;
}
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Makes a character mechanically react
 *-----------------------------------------------------------------------------
 *  Input :         a pointer on the SO
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : ../10/96            Author :Frédéric
 *-----------------------------------------------------------------------------
 *  Modification date : 30-05-97        Modification Author : JMS
 *  Modifications : take into account the father
 *-----------------------------------------------------------------------------
 *  Modification date : 30-06-98        Modification Author : J Thenoz
 *  Modifications : delete requests treatment
 *---------------------------------------------------------------------------*/
void fn_vMakeCharacterMechanicallyReact(HIE_tdxHandleToSuperObject p_stSuperObj)
{
	MS_tdxHandleToDynam h_Dynam;
	DNM_tdstDynamics *p_stDynamics;
	DNM_tdxHandleToMecIdentityCard  h_IdentityCard;
/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
	long lDuration;
#endif
/* END ANNECY MT }*/
 
	if((h_Dynam = M_GetMSHandle(p_stSuperObj,Dynam)) == NULL )
		return;
	if((p_stDynamics = fn_p_stDynamGetDynamics(h_Dynam)) == NULL)
		return;
 
/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
  #pragma warning (disable : 4146)
	lDuration = -TMR_fn_ulFastGetInternalCounter();		
  #pragma warning (default : 4146)
#endif
/* END ANNECY MT }*/
 
	PRF_fn_vStartChrono( PRF_C_ulFctDNM, p_stSuperObj );
 
	h_IdentityCard = fn_h_GetCurrentDNMIdCard(p_stSuperObj);
 
	/* dynamic change */
	if (DNM_M_pDynamicsGetCurrentIdCard(p_stDynamics)!=h_IdentityCard)
		DNM_fn_vChangeIdCard (p_stDynamics, h_IdentityCard);
 
	/* dynamic function call */
	if(h_IdentityCard != NULL)
	{
		g_a_pfnDynamicFunction[DNM_fn_eIdentityCardGetType(h_IdentityCard)]
		(
			p_stDynamics,
			p_stSuperObj,
			fn_p_stDynamGetParsingDatas(M_GetMSHandle(p_stSuperObj,Dynam)),
			h_IdentityCard,
			M_xGetUsefulDeltaTimeInSeconds(g_stEngineStructure.stEngineTimer)
		);
 
		/* Translate state datas*/
		if (DNM_M_bDynamicsIsCollisionReport(p_stDynamics)) DNM_M_ReportStateTranslate(DNM_M_p_stDynamicsGetReport(p_stDynamics));
		fn_vDynamSetUsedMechanics(h_Dynam,DNM_fn_eIdentityCardGetType(h_IdentityCard));
	}
 
    PRF_fn_vStopChrono( PRF_C_ulFctDNM, p_stSuperObj );
 
/* ANNECY MT - 19/10/98 {*/
#if (defined(USE_PROFILER) && !defined(PRESS_DEMO) && !defined(U64))
	lDuration += TMR_fn_ulFastGetInternalCounter();		
	if(M_GetMSHandle(p_stSuperObj,StandardGame))
	{
		GAM_fn_vRasterDumpUpdate((unsigned long)fn_otStandardGameGetModelType(M_GetMSHandle(p_stSuperObj,StandardGame)),0,0,lDuration,0);
	}
#endif
/* END ANNECY MT }*/
}
 
 
/*-----------------------------------------------------------------------------
 *  Description :   Makes a character react: Intelligence / Reflex + Mechanics
 *-----------------------------------------------------------------------------
 *  Input :         a pointer on the SO
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : ../10/96            Author :Frederic
 *-----------------------------------------------------------------------------
 *  Modifications : CT 18/02/98 delete update using report
 *---------------------------------------------------------------------------*/
char gcGlobAleat = 0;
void fn_vMakeCharacterReact(HIE_tdxHandleToSuperObject p_stSuperObj)
{
	unsigned long ulCurrentBits;
	MS_tdxHandleToStandardGame hStdGame = M_GetMSHandle(p_stSuperObj,StandardGame);
	
#ifdef ACTIVE_EDITOR
	char* pMsg;
	char MyMsg[1024]="";
	char MyTitle[256];
	char* pMyComport;
	char szMyFamily[256];
	char* pMyModel;
	char* pMyPersoName;
	struct AI_tdstMind_ *p_stMind;
	ACP_tdxBool bAIPlayed = FALSE ;
#endif
 
	SAF_M_Try /*BART*/
		
		ulCurrentBits = fn_ulStandardGameGetCustomBits(hStdGame);
	
	/* if both bits are set, we are not displayed, and passivity is required.*/
	/* in all other cases, either we are visible and we act, or no passivity is required, whether we are visible or not!*/
	if ( (ulCurrentBits & (GAM_C_CustBitUnseenFrozen | GAM_C_CustBitOutOfVisibility)) != (GAM_C_CustBitUnseenFrozen | GAM_C_CustBitOutOfVisibility) )
	{
		/* if no AI is required, or if we are too far to take AI into account, skip AI!*/
		if
		(
			!(
				(ulCurrentBits & GAM_C_CustBitNoAI)
				||
				((ulCurrentBits & GAM_C_CustBitNoAIWhenTooFar) && fn_bStandardGameIsTooFar(hStdGame))
			)
		)
		{
#ifdef ACTIVE_EDITOR
			bAIPlayed = TRUE ;
			sprintf (MyTitle,"Erreur dans une IA !");
#endif
			fn_vMakeCharacterThink(p_stSuperObj);
 
			/* the AI might have destroyed the instance, so check that it is still valid!*/
			if ( (hStdGame = M_GetMSHandle(p_stSuperObj,StandardGame)) != NULL ) /*VOLUNTARY ASSIGNMENT*/
			{
				/*the AI might have changed some bits, so read them again!*/
				ulCurrentBits = fn_ulStandardGameGetCustomBits(hStdGame);
			}
		}
 
		/* if no meca is required or we are too far to take it into account, skip it		*/
		if
		(
			hStdGame /* the object still exists (hence it is not a destroyed always)*/
			&&
			!(
				(ulCurrentBits & GAM_C_CustBitNoMechanic)
				||
				(
					(ulCurrentBits & GAM_C_CustBitNoMecaWhenTooFar)
					&& fn_bStandardGameIsTooFar(hStdGame)
				)
			)
		)
		{
#ifdef ACTIVE_EDITOR
			sprintf (MyTitle,"Erreur dans la mécanique !");
#endif		
			fn_vMakeCharacterMechanicallyReact(p_stSuperObj);
		}
/* jt 010499 commenté car les designers utilisent systématiquement des plateformes sans méca avant qu'un acteur devienne fils
#if defined(ACTIVE_EDITOR) && defined(__DEBUG_AI__)
		else if ( hStdGame )
		{
			if ( fn_bStandardGameIsAPlatform(p_stSuperObj) && M_GetMSHandle((p_stSuperObj), Brain) && bAIPlayed )
			{
				char szMsg[512], *pszPersoName;
				int i, iNbActorChildren = 0;
				HIE_tdxHandleToSuperObject hChild;
 
				sprintf (MyTitle,"Erreur dans la mécanique !");
				strcpy(szMsg, "une plateforme qui a des fils et une IA doit impérativement traiter sa mécanique!\n     Les fils sont:");
				HIE_M_ForEachChildOf(p_stSuperObj,hChild,i)
				{
					if ( HIE_fn_ulGetSuperObjectType(hChild) == HIE_C_ulActor )
					{
						tdstEngineObject *hChildActor = (tdstEngineObject *) HIE_fn_hGetSuperObjectObject(hChild);
						strcat(szMsg, "\n\t- ");
						
						if (hChildActor->h_Brain && hChildActor->h_Brain->p_stMind)
						{
							pszPersoName = hChildActor->h_Brain->p_stMind->szPersoName;
						}
						else
						{
							pszPersoName = "**unknown**";
						}
						strcat(szMsg, pszPersoName);
						iNbActorChildren ++;
					}
				}
				SAF_M_AssertWithMsg((iNbActorChildren == 0), szMsg);
			}
		}
#endif
*/
	}
	
	SAF_M_CatchWithMsg(pMsg) /* BART*/
#ifdef ACTIVE_EDITOR
	if ( M_GetMSHandle((p_stSuperObj), Brain) )
	{
		p_stMind = AI_M_stGetMindOfSuperObj(p_stSuperObj);
		strcpy(szMyFamily, M_GetNameComport(M_GetCurrentComport(M_GetIntellOrReflex(p_stMind))) );

		pMyComport = strrchr(szMyFamily, ':')+1;
		pMyModel = strchr(szMyFamily, '\\');
		*(pMyModel++) = 0;
		*(strchr(pMyModel, '\\')) = 0;
		
		/*if ( strlen(pMyPersoName) == 0)*/
		if (fn_ucIsAnAlwaysObject(M_GetEngineObject(p_stSuperObj)))
		{
			sprintf(MyMsg,"sur un ALWAYS\nFamille : %s\nModel : %s\nComportement : %s\nDescription : \n  ->%s\n",
				szMyFamily,
				pMyModel,
				pMyComport,
				pMsg);
		}
		else
		{
			pMyPersoName = AI_M_szGetPersoName(p_stMind);
			sprintf(MyMsg,"sur l'instance \"%s\"\nFamille : %s\nModel : %s\nComportement : %s\nDescription : \n  ->%s\n",
				pMyPersoName,
				szMyFamily,
				pMyModel,
				pMyComport,
				pMsg);
		}
	}
	else
	{
		sprintf(
			MyMsg, "sur un acteur sans IA, dans l'état %s\nDescription : \n  ->%s\n",
			fn_p_szGetStateName(fn_h3dDataGetCurrentState(M_GetMSHandle((p_stSuperObj), 3dData))),
			pMsg
		) ;
		p_stMind = NULL ;
	}
	/*pMyPersoName = AI_M_szGetPersoName(p_stMind);*/

	
	Erm_fn_iMessageBox(MyMsg, MyTitle, MB_TOPMOST| MB_ICONEXCLAMATION | MB_OK);
	fn_vForceEditor();
#endif
	
	SAF_M_EndCatch /*BART*/
}
 
 
#ifndef _DEBUG
#pragma optimize( "t", off )
#endif
 
 
#ifndef _DEBUG
#pragma optimize( "", on )
#endif
