/*=========================================================================
* MS_Micro.cpp : MS_Micro's functions
*
*
*
*         MS_Micro MUST BE REPLACE BY THE C FILENAME
*
*
* Version              1.0
* Creation date        01/10/96
* Revision date
*
* That file needs to be compatible for all platforms.
*
* (c) Ubi Studios 1996
*=======================================================================*/
 
/*******************************************************/
/**** For the structures and variables declarations ****/
/*******************************************************/
#define D_Micro_StructureDefine
#define D_Micro_VariableDefine
 
#include "ToolsCPA.h"
 
#include "SND.h"
 
#include "Options/Options.h"
#include "Macros.h"
 
#include "Actions/AllActs.h"
 
#include "Structur/MemGame.h"
#include "Structur/ErrGame.h"
#include "Structur/Objects.h"
#include "Structur/GameScpt.h"
#include "Structur/StdObjSt.h"
#include "Structur/EngMode.h"
 
#include "Basic.h"
#include "ObjInit.h"
#include "ZeMem.h"
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's object action script callback
*-----------------------------------------------------------------------------
*  Input :         Object pointer
*  Output :        None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96            Author : Francois
*-----------------------------------------------------------------------------
*  Modification date :                 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
#if defined(GAM_USE_SCRIPT)
SCR_tde_Anl_ReturnValue fn_eMicroScriptCallback(SCR_tdst_File_Description *_p_stFile,char *_p_szName,char *_ap_szParams[],SCR_tde_Anl_Action	_eAction)
{
   SCR_tde_Anl_ReturnValue eReturnValue = SCR_ERV_Anl_NormalReturn;
   MS_tdxHandleToMicro h_MS_Micro;
   struct tdstEngineObject_ *p_stEngineObject;
   MTH3D_tdstVector stX,stY,stZ;
 
 _p_stFile=_p_stFile;
 
   SCR_M_RdL0_GetSectionLong(C_ParentSection,0,struct tdstEngineObject_ *, p_stEngineObject);
 
   if (M_IsTitle)
   {
      MMG_fn_vBeginMemoryInfo (MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMicro , p_stEngineObject);
      h_MS_Micro = fn_h_MicroRealAlloc();
      MMG_fn_vEndMemoryInfo ();
      p_stEngineObject->h_Micro = h_MS_Micro;
      SCR_M_RdL0_SetSectionLong(C_ThisSection,0,h_MS_Micro);
      /*h_MS_Micro->hMicroMatrix = GEO_fn_hCreateMatrix();*/
      h_MS_Micro->bIsActive = 0;
      POS_fn_vSetIdentityMatrix( h_MS_Micro->hMicroMatrix );
      /*fn_vAddMicro(p_stEngineObject);*/
   }
   else if (M_IsEntry)
   {
      if( M_ActionIs( C_EntryMicroRotationMatrix ) )
      {
         SCR_M_RdL0_GetSectionLong(C_ThisSection,0,MS_tdxHandleToMicro,h_MS_Micro);
         M_CheckScriptParamNumber(9);
         MTH3D_M_vSetVectorElements(&stX,fn_fAToF(_ap_szParams[0]),
            fn_fAToF(_ap_szParams[1]),fn_fAToF(_ap_szParams[2]));
         MTH3D_M_vSetVectorElements(&stY,fn_fAToF(_ap_szParams[3]),
            fn_fAToF(_ap_szParams[4]),fn_fAToF(_ap_szParams[5]));
         MTH3D_M_vSetVectorElements(&stZ,fn_fAToF(_ap_szParams[6]),
            fn_fAToF(_ap_szParams[7]),fn_fAToF(_ap_szParams[8]));
         POS_fn_vSetRotationMatrix(h_MS_Micro->hMicroMatrix,&stX,&stY,&stZ);
      }
      else if( M_ActionIs( C_EntryMicroTranslationMatrix ) )
      {
         SCR_M_RdL0_GetSectionLong(C_ThisSection,0,MS_tdxHandleToMicro,h_MS_Micro);
         M_CheckScriptParamNumber(3);
         MTH3D_M_vSetVectorElements(&stX,fn_fAToF(_ap_szParams[0]),
            fn_fAToF(_ap_szParams[1]),fn_fAToF(_ap_szParams[2]));
         POS_fn_vSetTranslationVector(h_MS_Micro->hMicroMatrix,&stX);
      }
      else if( M_ActionIs( C_EntryMicroActivation ) )
      {
         SCR_M_RdL0_GetSectionLong(C_ThisSection,0,MS_tdxHandleToMicro,h_MS_Micro);
         h_MS_Micro->bIsActive = 1;
 
/*         fn_vAddMicro( p_stEngineObject );*/
      }
      else if( M_ActionIs( C_EntryMicroUnactivation ) )
      {/* Default option*/
         SCR_M_RdL0_GetSectionLong(C_ThisSection,0,MS_tdxHandleToMicro,h_MS_Micro);
         h_MS_Micro->bIsActive = 0;
      }
   }
   return(eReturnValue);
}
#endif /* GAM_USE_SCRIPT */
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's save structure
*-----------------------------------------------------------------------------
*  Input : 		  SCR_tdst_File_Description *, struct tdstEngineObject_ *
*  Output :		  Void
*-----------------------------------------------------------------------------
*  Creation date : 28/02/97				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
/*
void fn_vMicroSaveMiniStructure(SCR_tdst_File_Description *p_stFile,struct tdstEngineObject_ *p_stObject)
{
   char szSection[SCR_CV_ui_Cfg_MaxLenName];
   MS_tdxHandleToMicro h_MS_Micro = p_stObject->h_Micro;
   MTH3D_tdstVector stX,stY,stZ;
 
   SCR_M_SvL0_SaveBlankLine(p_stFile);
   SCR_M_SvL0_SaveComment(p_stFile, "**** MS_Micro mini-structure definition ****");
 
   sprintf(szSection,"%s:",C_SectionMicroDescription);
   SCR_M_SvL0_SaveBeginSection(p_stFile,szSection,SCR_CC_C_Cfg_EOL);
 
   // ** Put here the saving script functions **
   POS_fn_vGetRotationMatrix( h_MS_Micro->hMicroMatrix,&stX,&stY,&stZ );
   SCR_M_SvL0_SaveEntry(p_stFile,C_EntryMicroRotationMatrix,SCR_CC_C_Cfg_NoChar);
   SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf,9,
      "%f,%f,%f,%f,%f,%f,%f,%f,%f",
      stX.xX,stX.xY,stX.xZ,
      stY.xX,stY.xY,stY.xZ,
      stZ.xX,stZ.xY,stZ.xZ);
   POS_fn_vGetTranslationVector( h_MS_Micro->hMicroMatrix,&stX );
   SCR_M_SvL0_SaveEntry(p_stFile,C_EntryMicroTranslationMatrix,SCR_CC_C_Cfg_NoChar);
   SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf,3,"%f,%f,%f",stX.xX,stX.xY,stX.xZ);
 
   SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL)
}
*/
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's mini-structure sizeof
*-----------------------------------------------------------------------------
*  Input : 		  None
*  Output :		  Size of
*-----------------------------------------------------------------------------
*  Creation date : 14/10/96				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
unsigned long fn_ulMicroSizeOf()
{
   return(sizeof(struct tdstMicro_));
}
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's object action allocation
*-----------------------------------------------------------------------------
*  Input : 		  Object pointer
*  Output :		  None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMicroAlloc(struct tdstEngineObject_ *p_stObject)
{
	MTH3D_tdstVector stI, stJ, stK;
	
	if (p_stObject==NULL)
		M_GameFatalError(E_uwGameMiniStructObjectNull);
	
	if (p_stObject->h_Micro!=NULL)
		M_GameFatalError(E_uwGameMiniStructAllocAlreadyAlloc);
	
	MMG_fn_vBeginMemoryInfo (MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMicro , p_stObject);
	p_stObject->h_Micro = fn_h_MicroRealAlloc();
	MMG_fn_vEndMemoryInfo ();
	
/* ANNECY MT - 15/03/99 { */
	/* init matrix */
	MTH3D_M_vSetVectorElements(&stJ, MTH_C_MinusONE, MTH_C_ZERO, MTH_C_ZERO);
	MTH3D_M_vSetBaseKVector(&stK);
	if (p_stObject -> h_Cineinfo != NULL)
	{
		/* actor is a camera */
		MTH3D_M_vSetVectorElements(&stI, MTH_C_ZERO, MTH_C_MinusONE, MTH_C_ZERO);
	}
	else
	{
		/* actor isn't a camera */
		MTH3D_M_vSetVectorElements(&stI, MTH_C_ZERO, MTH_C_ONE, MTH_C_ZERO);
	}
	POS_fn_vSetRotationMatrix(p_stObject->h_Micro->hMicroMatrix, &stI, &stJ, &stK);
/* END ANNECY MT } */
}
 
MS_tdxHandleToMicro fn_h_MicroRealAlloc()
{
   MS_tdxHandleToMicro h_MS_Micro;
 
   h_MS_Micro = (MS_tdxHandleToMicro)M_p_GameMallocInHLM(fn_ulMicroSizeOf());
   h_MS_Micro->hMicroMatrix = GEO_fn_hCreateMatrix();
   return(h_MS_Micro);
}
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's object action free
*-----------------------------------------------------------------------------
*  Input : 		  Object pointer
*  Output :		  None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMicroFree(struct tdstEngineObject_ *p_stObject)
{
   if (p_stObject==NULL)
      M_GameFatalError(E_uwGameMiniStructObjectNull);
 
   if (p_stObject->h_Micro==NULL)
      M_GameFatalError(E_uwGameMiniStructNull);
 
   MMG_fn_vAddMemoryInfo( MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMicro , p_stObject );
   M_GameFreeInHLM(p_stObject->h_Micro);
}
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's object action initialisation
*-----------------------------------------------------------------------------
*  Input : 		  When this function's called (see ObjInit.h)
*  Output :		  None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMicroInit(struct tdstEngineObject_ *p_stObject,enum tdeObjectTreeInit_ eObjectInit)
{
   if (p_stObject==NULL)
      M_GameFatalError(E_uwGameMiniStructObjectNull);
 
   if (p_stObject->h_Micro==NULL)
      M_GameFatalError(E_uwGameMiniStructNull);
 
   switch(eObjectInit)
   {
    case OTI_WhenGameStart:
     break;
    case OTI_MapLoaded:
     if (fn_bMicroGetActivationFlag(p_stObject->h_Micro))
      fn_vAddMicro(p_stObject);
     break;
    case OTI_ReinitTheMap:
	  	case OTI_AlwaysCreated:
    case OTI_PlayerDead:
    case OTI_LoadSavedGame:
     break;
   }
}
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro's object action desinitialisation
*-----------------------------------------------------------------------------
*  Input : 		  When this function's called (see ObjInit.h)
*  Output :		  None
*-----------------------------------------------------------------------------
*  Creation date : 01/10/96				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
void fn_vMicroDesinit(struct tdstEngineObject_ *p_stObject,enum tdeObjectTreeInit_ eObjectInit)
{
   if (p_stObject==NULL)
      M_GameFatalError(E_uwGameMiniStructObjectNull);
 
   if (p_stObject->h_Micro==NULL)
      M_GameFatalError(E_uwGameMiniStructNull);
 
   switch(eObjectInit)
   {
    case OTI_ReinitTheMap:
     break;
    case OTI_MapLoaded:
     break;
  		case OTI_AlwaysCreated:
    case OTI_PlayerDead:
     break;
	default:
     break;
   }
}
 
/*-----------------------------------------------------------------------------
 *  Description : Micro's object copy clone action
 *-----------------------------------------------------------------------------
 *  Input :         Handle to destination, handle to source
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 30/06/97            Author : Olivier Jourdan
 *-----------------------------------------------------------------------------
 *  Modification date :                 Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
void fn_vMicroCopyClone(struct tdstEngineObject_ * _p_stObjectDest,struct tdstEngineObject_ * _p_stObjectSrc)
{
   /* If Micro doesn't contains pointers to structure that may be*/
   /* changed during the game, this function must only be a :*/
   /* Should be changed*/
   memcpy(_p_stObjectDest->h_Micro,_p_stObjectSrc->h_Micro,fn_ulMicroSizeOf());
}
 
/*-----------------------------------------------------------------------------
*  Description : MS_Micro access functions
*-----------------------------------------------------------------------------
*  Input : 		  MS_tdxHandleToMicro + (value)
*  Output :		  (value or pointer)
*-----------------------------------------------------------------------------
*  Creation date : 29/01/97				 Author : Francois
*-----------------------------------------------------------------------------
*  Modification date : 					 Modification Author :
*  Modifications :
*---------------------------------------------------------------------------*/
/*------------------------------------------------------------------
* Accessors to matrix
*-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
GEO_tdxHandleToMatrix fn_xMicroGetMatrix(MS_tdxHandleToMicro h_MS_Micro)
{
   return( h_MS_Micro->hMicroMatrix );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vMicroSetMatrix(MS_tdxHandleToMicro h_MS_Micro,GEO_tdxHandleToMatrix hMatrix)
{
   h_MS_Micro->hMicroMatrix = hMatrix;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
* Accessors to activation flag
*-----------------------------------------------------------------*/
ACP_tdxBool fn_bMicroGetActivationFlag(MS_tdxHandleToMicro h_MS_Micro)
{
   return( h_MS_Micro->bIsActive );
}
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vMicroSetActivationFlag(MS_tdxHandleToMicro h_MS_Micro,ACP_tdxBool bFlag)
{
   h_MS_Micro->bIsActive = bFlag;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
* Management of micros/characters list
*-----------------------------------------------------------------*/
struct tdstEngineObject_ * fn_hReturnHandleMicroFromIndex(long lIndex)
{
   MIC_tdxHandleToMicro hMicro;
   int i;
 
   LST2_M_DynamicForEachElementOf(&(g_stIndexMicrosList.hMicrosList),hMicro,i)
   {
      if( ((tdstIndexMicros*)hMicro)->lIndex == lIndex )
         return( ((tdstIndexMicros*)hMicro)->hMicroObj );
   }
   return NULL;
}
 
/*------------------------------------------------------------------
 * Get the X component of micro position
 *-----------------------------------------------------------------*/
long RetMicroSonoreX(long indice)
{
 MTH3D_tdstVector stVertex;
 HIE_tdxHandleToSuperObject hSuperObj;
 
 hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
 POS_fn_vGetTranslationVector( HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),&stVertex );
 /*POS_fn_vMulMatrixVertex( &stVertex,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stVertex );*/
 return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stVertex.xX));
}
 
/*------------------------------------------------------------------
 * Get the Y component of micro position
 *-----------------------------------------------------------------*/
long RetMicroSonoreY(long indice)
{
   MTH3D_tdstVector stVertex;
   HIE_tdxHandleToSuperObject hSuperObj;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vGetTranslationVector( HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),&stVertex );
   /*POS_fn_vMulMatrixVertex( &stVertex,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stVertex );*/
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stVertex.xY));
}
 
/*------------------------------------------------------------------
 * Get the Z component of micro position
 *-----------------------------------------------------------------*/
long RetMicroSonoreZ(long indice)
{
   MTH3D_tdstVector stVertex;
   HIE_tdxHandleToSuperObject hSuperObj;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vGetTranslationVector( HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),&stVertex );
   /*POS_fn_vMulMatrixVertex( &stVertex,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stVertex );*/
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stVertex.xZ));
}
 
/*------------------------------------------------------------------
 * Get the X component of micro speed
 *-----------------------------------------------------------------*/
long RetMicroSonoreVX(long indice)
{
	struct tdstEngineObject_	*p_Object;
	HIE_tdxHandleToSuperObject	hSuperObj;
	DNM_tdstDynamics			*p_stDynamics;
	MTH_tdxReal					xResult = MTH_C_ZERO;

	p_Object  = fn_hReturnHandleMicroFromIndex(indice);
	if (p_Object)
	{
		hSuperObj = M_GetSuperObject( p_Object );
		if( !M_GetMSHandle(hSuperObj,Dynam) )
			return 0;
		if( (p_stDynamics = fn_p_stDynamGetDynamics(M_GetMSHandle(hSuperObj,Dynam))) == NULL )
			return 0;
	
		/* camera object special case */
		if (DNM_M_lDynamicsGetObjectType(p_stDynamics)==DNM_eCamera)
		{
			MTH_tdxReal xInvDTInSecond;

			xInvDTInSecond = MTH_M_xDiv(MTH_M_xFloatToReal(1000.f),MTH_M_xLongToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));

			xResult = MTH_M_xMul(MTH3D_M_xGetXofVector(DNM_M_p_stReportGetLastMove(DNM_M_p_stDynamicsGetReport(p_stDynamics))),xInvDTInSecond);
		}
		else
		{
			xResult = MTH3D_M_xGetXofVector(DNM_M_pDynamicsGetPreviousSpeed(p_stDynamics));
		}
	}

	if(xResult>32000.0f)
		xResult=32000.0f; //AR9908 Against overflow...
	if(xResult<-32000.0f)
		xResult=-32000.0f; //AR9908 Against overflow...


	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xResult));
}
 
/*------------------------------------------------------------------
 * Get the Y component of micro speed
 *-----------------------------------------------------------------*/
long RetMicroSonoreVY(long indice)
{
	struct tdstEngineObject_	*p_Object;
	HIE_tdxHandleToSuperObject	hSuperObj;
	DNM_tdstDynamics			*p_stDynamics;
	MTH_tdxReal					xResult = MTH_C_ZERO;

	p_Object  = fn_hReturnHandleMicroFromIndex(indice);
	if (p_Object)
	{
		hSuperObj = M_GetSuperObject( p_Object );
		if( !M_GetMSHandle(hSuperObj,Dynam) )
			return 0;
		if( (p_stDynamics = fn_p_stDynamGetDynamics(M_GetMSHandle(hSuperObj,Dynam))) == NULL )
			return 0;
	
		/* camera object special case */
		if (DNM_M_lDynamicsGetObjectType(p_stDynamics)==DNM_eCamera)
		{
			MTH_tdxReal xInvDTInSecond;

			xInvDTInSecond = MTH_M_xDiv(MTH_M_xFloatToReal(1000.f),MTH_M_xLongToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));

			xResult = MTH_M_xMul(MTH3D_M_xGetYofVector(DNM_M_p_stReportGetLastMove(DNM_M_p_stDynamicsGetReport(p_stDynamics))),xInvDTInSecond);
		}
		else
		{
			xResult = MTH3D_M_xGetYofVector(DNM_M_pDynamicsGetPreviousSpeed(p_stDynamics));
		}
	}

	if(xResult>32000.0f)
		xResult=32000.0f; //AR9908 Against overflow...
	if(xResult<-32000.0f)
		xResult=-32000.0f; //AR9908 Against overflow...

	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xResult));
}
 
/*------------------------------------------------------------------
 * Get the Z component of micro speed
 *-----------------------------------------------------------------*/
long RetMicroSonoreVZ(long indice)
{
	struct tdstEngineObject_	*p_Object;
	HIE_tdxHandleToSuperObject	hSuperObj;
	DNM_tdstDynamics			*p_stDynamics;
	MTH_tdxReal					xResult = MTH_C_ZERO;

	p_Object  = fn_hReturnHandleMicroFromIndex(indice);
	if (p_Object)
	{
		hSuperObj = M_GetSuperObject( p_Object );
		if( !M_GetMSHandle(hSuperObj,Dynam) )
			return 0;
		if( (p_stDynamics = fn_p_stDynamGetDynamics(M_GetMSHandle(hSuperObj,Dynam))) == NULL )
			return 0;
	
		/* camera object special case */
		if (DNM_M_lDynamicsGetObjectType(p_stDynamics)==DNM_eCamera)
		{
			MTH_tdxReal xInvDTInSecond;

			xInvDTInSecond = MTH_M_xDiv(MTH_M_xFloatToReal(1000.f),MTH_M_xLongToReal(g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime));

			xResult = MTH_M_xMul(MTH3D_M_xGetZofVector(DNM_M_p_stReportGetLastMove(DNM_M_p_stDynamicsGetReport(p_stDynamics))),xInvDTInSecond);
		}
		else
		{
			xResult = MTH3D_M_xGetZofVector(DNM_M_pDynamicsGetPreviousSpeed(p_stDynamics));
		}
	}

	if(xResult>32000.0f)
		xResult=32000.0f; //AR9908 Against overflow...
	if(xResult<-32000.0f)
		xResult=-32000.0f; //AR9908 Against overflow...

	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xResult));
}
 
/*------------------------------------------------------------------
 * Get the X component of micro normal
 *-----------------------------------------------------------------*/
long RetMicroSonoreDNX(long indice)
{
	/*
	//This the exact code, but needs 27 multiplication
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix );
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stI.xX));
   */
	/*need only 3 multiplications*/
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xX,stW1.xX),MTH_M_xMul(stV2.xX,stW1.xY)),
		MTH_M_xMul(stV3.xX,stW1.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Get the Y component of micro normal
 *-----------------------------------------------------------------*/
long RetMicroSonoreDNY(long indice)
{
	/*
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix );
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stI.xY));
   */
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xY,stW1.xX),MTH_M_xMul(stV2.xY,stW1.xY)),
		MTH_M_xMul(stV3.xY,stW1.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Get the Z component of micro normal
 *-----------------------------------------------------------------*/
long RetMicroSonoreDNZ(long indice)
{
	/*
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix );
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stI.xZ));
   */
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xZ,stW1.xX),MTH_M_xMul(stV2.xZ,stW1.xY)),
		MTH_M_xMul(stV3.xZ,stW1.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Get the X component of micro tangent
 *-----------------------------------------------------------------*/
long RetMicroSonoreDTX(long indice)
{
	/*
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix );
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stJ.xX));
   */
	/*need only 3 multiplications*/
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xX,stW2.xX),MTH_M_xMul(stV2.xX,stW2.xY)),
		MTH_M_xMul(stV3.xX,stW2.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Get the Y component of micro tangent
 *-----------------------------------------------------------------*/
long RetMicroSonoreDTY(long indice)
{
	/*
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj),M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix );
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stJ.xY));
   */
	/*need only 3 multiplications*/
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xY,stW2.xX),MTH_M_xMul(stV2.xY,stW2.xY)),
		MTH_M_xMul(stV3.xY,stW2.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Get the Z component of micro tangent
 *-----------------------------------------------------------------*/
long RetMicroSonoreDTZ(long indice)
{
	/*
   MTH3D_tdstVector stI,stJ,stK;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition stMatrix;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   POS_fn_vSetIdentityMatrix(&stMatrix);
   POS_fn_vMulMatrixMatrix( &stMatrix,HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj) ,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix);
   POS_fn_vGetRotationMatrix(&stMatrix,&stI,&stJ,&stK);
   //POS_fn_vMulMatrixVertex( &stI,M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix,&stI );
   return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(stJ.xZ));
   */
	/*need only 3 multiplications*/
   MTH3D_tdstVector stV1,stV2,stV3,stW1,stW2,stW3;
   HIE_tdxHandleToSuperObject hSuperObj;
   POS_tdstCompletePosition *pMatrix1,*pMatrix2;
	MTH_tdxReal xN;
 
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(indice) );
   pMatrix1=HIE_fn_hGetSuperObjectGlobalMatrix(hSuperObj);
	pMatrix2=M_GetMSHandle(hSuperObj,Micro)->hMicroMatrix;
   POS_fn_vGetRotationMatrix(pMatrix1,&stV1,&stV2,&stV3);
   POS_fn_vGetRotationMatrix(pMatrix2,&stW1,&stW2,&stW3);
	xN=MTH_M_xAdd(
		MTH_M_xAdd(
			MTH_M_xMul(stV1.xZ,stW2.xX),MTH_M_xMul(stV2.xZ,stW2.xY)),
		MTH_M_xMul(stV3.xZ,stW2.xZ));
	return (long)M_Fixed1616ToRealSnd(MTH_M_xRealToFixed16_16(xN));
}
 
/*------------------------------------------------------------------
 * Return value of micro filter
 *-----------------------------------------------------------------*/
long RetMicroSonoreFILTRE(long indice)
{
   return 0;
}
 
/*------------------------------------------------------------------
 * Activate the Micro attached to character
 * Caution: hEngObj must have a Micro MiniStructure
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vActivateMicroForObject(struct tdstEngineObject_ * hEngObj)
{
   hEngObj->h_Micro->bIsActive = TRUE;
   fn_vAddMicro( hEngObj );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
/*------------------------------------------------------------------
 * Add an active micro in sound engine
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vUnactivateMicroForObject(struct tdstEngineObject_ * hEngObj)
{
   hEngObj->h_Micro->bIsActive = FALSE;
   fn_vRemoveMicro( hEngObj );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
/*------------------------------------------------------------------
 * Add an active micro in sound engine
 *-----------------------------------------------------------------*/
void fn_vAddMicro(struct tdstEngineObject_ * hEngObj)
{
   MIC_tdxHandleToMicro hMicro;
 
   MMG_fn_vAddMemoryInfo( MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMicro , hEngObj );
   hMicro = (MIC_tdxHandleToMicro)M_p_GameMallocInHLM(sizeof(tdstIndexMicros));
   LST2_M_DynamicInitElement(hMicro);
   ((tdstIndexMicros *)hMicro)->lIndex = SND_fn_lCreateMicroSound();
   ((tdstIndexMicros *)hMicro)->hMicroObj = hEngObj;
   LST2_M_DynamicAddTail(&g_stIndexMicrosList.hMicrosList,hMicro);
   hEngObj->h_Micro->bIsActive = TRUE;
}
 
/*------------------------------------------------------------------
 * Remove an active micro from the sound engine
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vRemoveMicro(struct tdstEngineObject_ * hEngObj)
{
   MIC_tdxHandleToMicro hMicro,hNextElement;
   long lI;
 
   LST2_M_DynamicForEachMovingElementOf( &g_stIndexMicrosList.hMicrosList,hMicro,hNextElement,lI )
   {
      if( ((tdstIndexMicros *)hMicro)->hMicroObj == hEngObj )
      {
         SND_fn_vDestroyMicroSound( hMicro->lIndex );
         LST2_M_DynamicIsolate( hMicro );
         MMG_fn_vAddMemoryInfo( MMG_C_lTypeMiniStructure , MMG_C_lSubTypeMicro , hEngObj );
         M_GameFreeInHLM( hMicro );
      }
   }
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
 * Remove all active micros in sound engine (not in 3DOS)
 *-----------------------------------------------------------------*/
void fn_vRemoveAllMicros()
{
   MIC_tdxHandleToMicro hMicro,hNextElement;
   long lI;
 
   LST2_M_DynamicForEachMovingElementOf( &g_stIndexMicrosList.hMicrosList,hMicro,hNextElement,lI )
   {
      SND_fn_vDestroyMicroSound( hMicro->lIndex );
      LST2_M_DynamicIsolate( hMicro );
/*      M_GameFreeInHLM( hMicro );*/
   }
   LST2_M_DynamicInitAnchor( &g_stIndexMicrosList.hMicrosList );
}
/*------------------------------------------------------------------
 * Return TRUE if objet is audible from micro position
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
BOOL td_fn_bRetObjetSoundLinkWithMicro(long objet,long micro)
{
   HIE_tdxHandleToSuperObject hObjectSector,hMicroSector,hSuperObj;
   unsigned long ulI;
   SECT_tdxHandleOfElementLstSoundInteraction hSoundList;
 
   hObjectSector=fn_h_SectInfoGetCurrentSector( M_GetMSHandle(((HIE_tdxHandleToSuperObject)objet),SectInfo) );
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(micro) );
   hMicroSector=fn_h_SectInfoGetCurrentSector( M_GetMSHandle(hSuperObj,SectInfo) );
   if( hObjectSector==hMicroSector )
      return TRUE;
   SECT_M_ForEachSoundNodeInSoundInteractionList(hMicroSector,hSoundList,ulI)
   {
      if( SECT_GetSectorInSoundList(hSoundList)==hObjectSector )
         return FALSE;
   }
   return TRUE;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
 * Return Value of audibility of object from micro position
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
long fn_lRetObjectSoundLinkVolumeWithMicro(long objet,long micro)
{
   HIE_tdxHandleToSuperObject hObjectSector,hMicroSector,hSuperObj;
   unsigned long ulI;
   SECT_tdxHandleOfElementLstSoundInteraction hSoundList;
 
   hObjectSector=fn_h_SectInfoGetCurrentSector( M_GetMSHandle(((HIE_tdxHandleToSuperObject)objet),SectInfo) );
   hSuperObj = M_GetSuperObject( fn_hReturnHandleMicroFromIndex(micro) );
   hMicroSector=fn_h_SectInfoGetCurrentSector( M_GetMSHandle(hSuperObj,SectInfo) );
   if( hObjectSector==hMicroSector )
      return C_MSMicro_MaxVolume;
   SECT_M_ForEachSoundNodeInSoundInteractionList(hMicroSector,hSoundList,ulI)
   {
      if( SECT_GetSectorInSoundList(hSoundList)==hObjectSector )
         return SCT_fn_lGetVolumeInSoundList(hSoundList);
   }
   return C_MSMicro_MinVolume;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
 * Init pointers of functions for sound engine
 *-----------------------------------------------------------------*/
void fn_vInitMicrosFunction()
{
   tdstAllRetMicroSound st_pfnRetMicroSound;
 
   memset(&st_pfnRetMicroSound,0,sizeof(st_pfnRetMicroSound));
   st_pfnRetMicroSound.X=RetMicroSonoreX;
   st_pfnRetMicroSound.Y=RetMicroSonoreY;
   st_pfnRetMicroSound.Z=RetMicroSonoreZ;
   st_pfnRetMicroSound.VX=RetMicroSonoreVX;
   st_pfnRetMicroSound.VY=RetMicroSonoreVY;
   st_pfnRetMicroSound.VZ=RetMicroSonoreVZ;
   st_pfnRetMicroSound.DNX=RetMicroSonoreDNX;
   st_pfnRetMicroSound.DNY=RetMicroSonoreDNY;
   st_pfnRetMicroSound.DNZ=RetMicroSonoreDNZ;
   st_pfnRetMicroSound.DTX=RetMicroSonoreDTX;
   st_pfnRetMicroSound.DTY=RetMicroSonoreDTY;
   st_pfnRetMicroSound.DTZ=RetMicroSonoreDTZ;
   st_pfnRetMicroSound.Filtre=RetMicroSonoreFILTRE;
 
   SND_fn_vSetRetMicroSound(&st_pfnRetMicroSound);
   LST2_M_DynamicInitAnchor(&g_stIndexMicrosList.hMicrosList);
}
 
/*------------------------------------------------------------------
 * Access functions to Micro List Element fields
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
long fn_lGetMicroIndiceInMicroListElement(MIC_tdxHandleToMicro _hMicroListElement)
{
   return( _hMicroListElement->lIndex );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
struct tdstEngineObject_ * fn_p_stGetEngineObjectInMicroListElement(MIC_tdxHandleToMicro _hMicroListElement)
{
   return( _hMicroListElement->hMicroObj );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
struct tdstEngineObject_ * fn_p_stGetFirstEngineObjectInMicroList(void)
{
   MIC_tdxHandleToMicro hMicroElement;
 
   hMicroElement = LST2_M_DynamicGetFirstElement(&g_stIndexMicrosList.hMicrosList);
   if( hMicroElement )
      return( hMicroElement->hMicroObj );
   else
      return NULL;
}
 
/*------------------------------------------------------------------
 *------------------------------------------------------------------
 * WARNING :  these functions are to use only with the ONE micro
 *            version of the GamLib
 *------------------------------------------------------------------
 *-----------------------------------------------------------------*/
 
/*------------------------------------------------------------------
 * Put micro on another character
 *-----------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void fn_vChangeCharacterForMicro(struct tdstEngineObject_ * _p_stEngineCharacter)
{
   LST2_M_DynamicGetFirstElement(&g_stIndexMicrosList.hMicrosList)->hMicroObj = _p_stEngineCharacter;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*------------------------------------------------------------------
 * Put micro on another character (AI version)
 *-----------------------------------------------------------------*/
void GAM_fn_vChangeCharacterForMicro(HIE_tdxHandleToSuperObject _hCharacter)
{
   LST2_M_DynamicGetFirstElement(&g_stIndexMicrosList.hMicrosList)->hMicroObj = (struct tdstEngineObject_ *)HIE_fn_hGetSuperObjectObject(_hCharacter);
}
 
/*------------------------------------------------------------------
 *------------------------------------------------------------------
 * End of functions for the ONE micro specific version of the GamLib
 *------------------------------------------------------------------
 *-----------------------------------------------------------------*/
 
 
