#ifdef _DEBUG
extern "C" unsigned long g_xMask;
#else
extern unsigned long g_xMask;
#endif
 
#include "AIUseCPA.h"
 
#include "specif/AIOption.h"
#include "AIMacros.h"
#include "AI_Erm.h"
 
#include "StrIntel.h"
#include "AI_Struc.h"
#include "DsgMem.h"
#include "Intell.h"
#include "EnumFunc.h"
 
#include "specif/AITools.h"
#include "DsgMem.h"
 
#include "Operator.h"
#include "EnumOper.h"
 
#include "Convert.h"
 
#define _WP_D_WAYPOINT_FRIEND_
#include "WPWayPt.h"
#define _WP_D_DEFINE_WAYPOINTS_
#define _WP_D_DEFINE_WAYS_
#define _WP_D_WPARC_FREIND_
#include "WP_Handl.h"
#include "WP_Func.h"
#include "WParc.h"
#undef _WP_D_WPARC_FREIND_
#undef _WP_D_DEFINES_WAYS_
#undef  _WP_D_DEFINE_WAYPOINTS_
 
#include "safe.h"
#include "prf.h"
 
#ifndef U64	/* MT300399 */
#include "SNA.h"
#include "PTC.h"
#endif

//KWN
#include "X:\cpa\tempgrp\GLIGLOU\MULTIDRV\inc\PvObj_st.h"
#include "GAM\specif\DS_TouchPanel.h"

/*
*=================================================================================================
*=================================================================================================
*/
#if !defined(OPTIMIZED_COMMAND)
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
tdstNodeInterpret *fn_p_stDefaultFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	p_SuperObjPerso=p_SuperObjPerso;
	p_stValue=p_stValue;
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
    M_AIFatalError(E_uwAIFatalNotValidFunction);
#endif
    return(p_stTree);
}
#endif /* _DEBUG_AI__*/
#endif /* OPTIMIZED_COMMAND*/
 
/*
*=================================================================================================
*=================================================================================================
*/
#include "Functio1.cxx"
 
/*
*=================================================================================================
*=================================================================================================
*/
 
/*=====================================================================================================================================
 Name:		ACT_DistanceAuCentrePerso 
 Author:	yann le tensorer
 Created:	september 18,1998 , AI functions optimizations.
 Aim:		this function calculates the distance between the bounding volume centers of the curent actor (or ultra able actor) and the given as 1st
			parameter actor
			if an actor has no bounding volume, the (0,0,0) local coordinate is taken instead of the center of BV
 =====================================================================================================================================*/
 
tdstNodeInterpret *fn_p_stDistanceToPersoCenter(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_					eFuncId=M_eFuncIdInterpret(p_stTree-1);
	GEO_tdxHandleToBoundingSphere	hBoundingSphere1,hBoundingSphere2;			/* bounding volume of both actors*/
	MTH3D_tdstVector				stCenter1,*p_stCenter1;			/* center of 1rst actor*/
	MTH3D_tdstVector				stCenter2,*p_stCenter2;			/* center of 2nd actor*/
	MTH3D_tdstVector				stVect;
	HIE_tdxHandleToSuperObject		p_SuperObjTarget;				/* perso given as first parameter*/
	MTH3D_tdstVector				stGlobalCenter1,stGlobalCenter2;
 
	/********************************************************************************/
	/* BEWARE THE ULTRA OPERATOR : Must be at the beginning and respect this syntax */
	/********************************************************************************/
    HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
	/********************************************************************************/
 
	/* read target actor*/
	M_EvalNextParameter(p_stValue);
	p_SuperObjTarget=M_GetSetParam_p_stSupObjValue(p_stValue);

	SAF_M_AssertWithMsg(p_SuperObjTarget, "l'acteur spécifié est nul"); 

	/* get bounding volume for both actors*/
	hBoundingSphere1 = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(p_SuperObjTarget);
	hBoundingSphere2 = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume(hNewSuperObjPerso);
 
	/* calculate global coordinates of both centers*/
	if (hBoundingSphere1)
	{
		p_stCenter1=&stCenter1; /* please, leave this line here!*/
		/*add center of BV to global position*/
		MTH3D_M_vMulMatrixVector(&stGlobalCenter1, &(p_SuperObjTarget->hGlobalMatrix->stRotationMatrix), &(hBoundingSphere1->stCenterPoint));
		MTH3D_M_vAddVector (p_stCenter1,&stGlobalCenter1,&(p_SuperObjTarget->hGlobalMatrix->stTranslationVector));
	}
	else
		p_stCenter1=&(p_SuperObjTarget->hGlobalMatrix->stTranslationVector);
 
	if (hBoundingSphere2)
	{
		p_stCenter2=&stCenter2;	/* please, leave this line here!*/
		/*add center of BV to global position*/
		MTH3D_M_vMulMatrixVector(&stGlobalCenter2, &(hNewSuperObjPerso->hGlobalMatrix->stRotationMatrix), &(hBoundingSphere2->stCenterPoint));
		MTH3D_M_vAddVector (p_stCenter2,&stGlobalCenter2,&(hNewSuperObjPerso->hGlobalMatrix->stTranslationVector));
	}
	else
		p_stCenter2=&(hNewSuperObjPerso->hGlobalMatrix->stTranslationVector);
 
	/* calculate and return distance*/
	MTH3D_M_vSubVector(&stVect,p_stCenter1,p_stCenter2);
	M_Full_GetSetParam_Float(p_stValue, MTH3D_M_xQuickNormVector(&stVect));
	return(p_stTree);
}
 
/*=====================================================================================================================================
 Name:		ACT_DistanceAuPerso 
 Author:	yann le tensorer
 Created:	september 22,1998 , AI functions optimizations.
 Aim:		this function calculates the distance between the origin of two actors
 =====================================================================================================================================*/
tdstNodeInterpret *fn_p_stDistanceToPerso(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_					eFuncId=M_eFuncIdInterpret(p_stTree-1);
	MTH3D_tdstVector				*p_stCenter1;			/* global position of 1rst actor*/
	MTH3D_tdstVector				*p_stCenter2;			/* global position of 2nd actor*/
	MTH3D_tdstVector				stVect;
	HIE_tdxHandleToSuperObject		p_SuperObjTarget;		/* actor given as first parameter*/
 
 
	/********************************************************************************/
	/* BEWARE THE ULTRA OPERATOR : Must be at the beginning and respect this syntax */
	/********************************************************************************/
    HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
	/********************************************************************************/
 
	/* read target actor*/
	M_EvalNextParameter(p_stValue);
 
	/* if non valid object given...*/
	if (M_GetSetParam_xValue(p_stValue)==0) 
	{
		/*we return an infinite distance*/
		M_Full_GetSetParam_Float(p_stValue, MTH_C_InfinitPlus);
		return(p_stTree);
	}
 
	p_SuperObjTarget=M_GetSetParam_p_stSupObjValue(p_stValue);
	SAF_M_AssertWithMsg(p_SuperObjTarget, "l'acteur spécifié est nul");  
	p_stCenter1=&(p_SuperObjTarget->hGlobalMatrix->stTranslationVector);
	p_stCenter2=&(hNewSuperObjPerso->hGlobalMatrix->stTranslationVector);
 
	/* calculate and return distance*/
	MTH3D_M_vSubVector(&stVect,p_stCenter1,p_stCenter2);
	M_Full_GetSetParam_Float(p_stValue, MTH3D_M_xQuickNormVector(&stVect));
	return(p_stTree);
}
 
/*=====================================================================================================================================
 Name:		ACT_PositionAbsoluePerso
 Author:	yann le tensorer
 Created:	september 21,1998 , AI functions optimizations.
 Aim:		Returns the absolute (global coordinates) position of an actor
 =====================================================================================================================================*/
 
tdstNodeInterpret *fn_p_stGetPersoAbsolutePosition(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	/*because of ultra operator...*/
	enum tdeFuncId_					eFuncId=M_eFuncIdInterpret(p_stTree-1);
    HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
 
	/* we just return the position*/
	M_Full_GetSetParam_p_stVertex(p_stValue,&(hNewSuperObjPerso->hGlobalMatrix->stTranslationVector));
	return(p_stTree);
}
 
/*=====================================================================================================================================
 Name:		ACT_MaPositionAbsolue
 Author:	yann le tensorer
 Created:	september 22,1998 , AI functions optimizations.
 Aim:		Returns the absolute (global coordinates) position of the current actor (not ultra able)
			this function is not ultra able, so quicker than fn_p_stGetPersoAbsolutePosition
			note: this function doesn exactly the same as the use of the "position" field and it is exactly as quick.
 =====================================================================================================================================*/
 
tdstNodeInterpret *fn_p_stGetMyAbsolutePosition(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	/* we just return the position*/
	M_Full_GetSetParam_p_stVertex(p_stValue,&(p_SuperObjPerso->hGlobalMatrix->stTranslationVector));
	return(p_stTree);
}
 
/*=====================================================================================================================================
 Name:		RESEAU_PositionAbsolueWp
 Author:	Benoit Germain
 Created:	October 15, 1998 , AI functions optimizations.
 Aim:		Returns the absolute (global coordinates) position of the given WP (not ultra able)
 =====================================================================================================================================*/
tdstNodeInterpret *fn_p_stGetWpAbsolutePosition(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	WP_tdhWayPoint		hWP;		/* pointer to the waypoint*/
 
	M_EvalNextParameter(p_stValue);
	hWP = M_GetSetParam_WayPointValue(p_stValue);
 
/* Oliv' - Portage v14 - Sorry, but GCC does not like accents at the end of string !!! ( I added a space )*/
  SAF_M_AssertWithMsg(hWP != WP_C_hWayPointInvalid, "Waypoint non valide spécifié ");
/* EndOfOliv'*/
	if ( hWP != WP_C_hWayPointInvalid )
	{
		if (hWP->m_hSuperObject)  /* does the waypoint have a superobject ? (dynamic waypoint)*/
		{
			/* get the location of the WP directly in the tdstPAram return structure*/
			WP_fnv_WayPoint_ComputeLocation(hWP, &M_GetSetParam_stVertexValue(p_stValue));
			/* and set the correct value type*/
			M_GetSetParam_Type(p_stValue) = E_vt_Vector;
		}
		else
		/* 99 % of the waypoints... avoid a procedure call */
		{
			M_Full_GetSetParam_p_stVertex(p_stValue,&(hWP->m_stVertex));
		}
	}
	else /*the waypoint is invalid: return NULL*/
	{
		MTH3D_M_vNullVector(&M_GetSetParam_stVertexValue(p_stValue))
		M_GetSetParam_Type(p_stValue) = E_vt_Vector;
	}
	return p_stTree;
}
 
/*=====================================================================================================================================
 
 =====================================================================================================================================*/
tdstNodeInterpret *fn_p_stDistanceFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	unsigned char	ucFlags;
	MTH_tdxReal		xReal = MTH_C_ZERO;
 
	/********************************************************************************/
	/* BEWARE THE ULTRA OPERATOR : Must be at the beginning and respect this syntax */
	/********************************************************************************/
    HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
	/********************************************************************************/
 
	switch (eFuncId)
	{

	case eFunc_GetPersoAbsolutePosition:
		{
			MTH3D_tdstVector stVector;
 
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(hNewSuperObjPerso), &stVector);
			M_Full_GetSetParam_p_stVertex(p_stValue,&stVector);
			return(p_stTree);
			break;
		}
	
		/*
	case eFunc_GetWPAbsolutePosition:
		{
			MTH3D_tdstVector	stVector;
			WP_tdhWayPoint		hWP;
 
			M_EvalNextParameter(p_stValue);
			hWP = M_GetSetParam_WayPointValue(p_stValue);
 
			WP_fnv_WayPoint_ComputeLocation(hWP,&stVector);
 
			M_Full_GetSetParam_p_stVertex(p_stValue,&stVector);
			return(p_stTree);
			break;
		}
		*/
	case eFunc_GetAngleAroundZToPerso:
		{
			MTH3D_tdstVector stVector1,stVector2;
			MTH_tdxReal xAngleEnd,xAngleStart,xDeltaAngle;
			HIE_tdxHandleToSuperObject  hAimedPerso;
 
			M_EvalNextParameter(p_stValue);
			hAimedPerso=M_GetSetParam_p_stSupObjValue(p_stValue);
 
			SAF_M_AssertWithMsg(hAimedPerso, "l'acteur spécifié est nul");  

			/* direction initiale -Y exprimée dans repère global */
			MTH3D_M_vSetVectorElements(&stVector1,MTH_C_ZERO,MTH_C_MinusONE,MTH_C_ZERO);
 
			POS_fn_vMulMatrixVector(&stVector1,HIE_fn_hGetSuperObjectGlobalMatrix(hNewSuperObjPerso),&stVector1);
			xAngleStart=fn_xComputeDirectionAngle(&stVector1);
			xAngleStart=fn_xRealModuloAround(MTH_C_ZERO,MTH_C_2Pi,xAngleStart);
 
			/* direction finale -Y exprimée dans global */
			/**** BEWARE ULTRA ****/
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(hNewSuperObjPerso),&stVector1);
			POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectGlobalMatrix(hAimedPerso),&stVector2);
			MTH3D_M_vSubVector(&stVector2, &stVector2, &stVector1);
			xAngleEnd=fn_xComputeDirectionAngle(&stVector2);
			xAngleEnd=fn_xRealModuloAround(MTH_C_ZERO,MTH_C_2Pi,xAngleEnd);
 
			xDeltaAngle=MTH_M_xRadToDeg(fn_xComputeBestEcartDirectionAngle(xAngleStart,xAngleEnd));
 
			M_Full_GetSetParam_Float(p_stValue, xDeltaAngle);
			return(p_stTree);
			break;
		}
	case eFunc_DistanceToWP:
		{
			M_EvalNextParameter(p_stValue);
			xReal=fn_xDistanceBetweenPersoAndWP(hNewSuperObjPerso, M_GetSetParam_WayPointValue(p_stValue));
			M_Full_GetSetParam_Float(p_stValue, xReal);
			return(p_stTree);
			break;
		}
	default :
		{
			HIE_tdxHandleToSuperObject	p_SuperObjTarget;
			M_EvalNextParameter(p_stValue);
			p_SuperObjTarget=M_GetSetParam_p_stSupObjValue(p_stValue);
			SAF_M_AssertWithMsg(p_SuperObjTarget, "l'acteur spécifié est nul");  
			switch (eFuncId)
			{
			/*case eFunc_DistanceToPerso			: ucFlags=C_DISTANCE_XYZ | DISTANCE_TO_ORIGIN; break;*/
			case eFunc_DistanceXToPerso			: ucFlags=C_DISTANCE_X	 | DISTANCE_TO_ORIGIN; break;
			case eFunc_DistanceYToPerso			: ucFlags=C_DISTANCE_Y   | DISTANCE_TO_ORIGIN; break;
			case eFunc_DistanceZToPerso			: ucFlags=C_DISTANCE_Z   | DISTANCE_TO_ORIGIN; break;
			case eFunc_DistanceXYToPerso		: ucFlags=C_DISTANCE_XY  | DISTANCE_TO_ORIGIN; break;
			case eFunc_DistanceXZToPerso		: ucFlags=C_DISTANCE_XZ  | DISTANCE_TO_ORIGIN; break;
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
			case eFunc_DistanceYZToPerso		: ucFlags=C_DISTANCE_YZ  | DISTANCE_TO_ORIGIN; break;
			case eFunc_DistanceXToPersoCenter   : ucFlags=C_DISTANCE_X   | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
			case eFunc_DistanceYToPersoCenter   : ucFlags=C_DISTANCE_Y   | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
			case eFunc_DistanceZToPersoCenter   : ucFlags=C_DISTANCE_Z   | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
			case eFunc_DistanceXYToPersoCenter  : ucFlags=C_DISTANCE_XY  | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
			case eFunc_DistanceXZToPersoCenter  : ucFlags=C_DISTANCE_XZ  | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
			case eFunc_DistanceYZToPersoCenter  : ucFlags=C_DISTANCE_YZ  | DISTANCE_TO_CENTER_OF_BOUNDING_VOLUME; break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
			default								: ucFlags = 0; break;
			}
			xReal=fn_xExtendedDistanceBetweenPerso(hNewSuperObjPerso,p_SuperObjTarget,ucFlags);
			M_Full_GetSetParam_Float(p_stValue, xReal);
			return(p_stTree);
			break;
		}
	}
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stMathTernarReal(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId = M_eFuncIdInterpret(p_stTree-1);
	MTH_tdxReal		x1, x2, xRet;
  ACP_tdxBool bTestResult;
 
	M_EvalNextParameter(p_stValue);
 
  if ( eFuncId == eFunc_TernOp )
  {
	  bTestResult = M_GetSetParam_lValue(p_stValue);
  }
  else
  {
  	x1 = M_ReturnParam_xValue(p_stValue);
	  M_EvalNextParameter(p_stValue);
	  x2 = M_ReturnParam_xValue(p_stValue);
 
    /* evaluate the condition*/
	  switch ( eFuncId )
	  {
	  case eFunc_TernInf:
		  bTestResult = MTH_M_bLess(x1, x2);
		  break;
 
	  case eFunc_TernSup:
		  bTestResult = MTH_M_bGreater(x1, x2);
		  break;
 
	  case eFunc_TernInfEq:
		  bTestResult = MTH_M_bLessEqual(x1, x2);
		  break;
 
	  case eFunc_TernSupEq:
		  bTestResult = MTH_M_bGreaterEqual(x1, x2);
		  break;
 
	  case eFunc_TernEq:
		  bTestResult = MTH_M_bEqual(x1, x2);
		  break;
 
	  default:
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
  	  M_AIFatalError(E_uwAIFatalNotValidFunction);
#endif
      bTestResult = FALSE; /*so that we dont get a compilation warning*/
  	  break;
	  }
  }
 
  /*now, according to the condition, we know which argument will be returned*/
  /*-> we can avoid to evaluate the one that wont be returned!*/
  if ( bTestResult )
  {
    /* the test is true: we evaluate the first parameter*/
  	M_EvalNextParameter(p_stValue);
    xRet = M_ReturnParam_xValue(p_stValue);
    /*and skip the remaining parameters (that is the second possible return value)*/
    p_stTree = fn_p_stSkipThisArgument(p_stTree);
  }
  else
  {
    /* the test is false: we skip the first parameter, but not the second one!!!*/
    p_stTree = fn_p_stSkipThisArgument(p_stTree);
    /*and evaluate the second parameter*/
  	M_EvalNextParameter(p_stValue);
    xRet = M_ReturnParam_xValue(p_stValue);
  }
 
  /*now we return the evaluated parameter!*/
  M_Full_GetSetParam_Float(p_stValue,xRet);
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stMathFunctionInt(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	long			lFirstValue=0;
 
	M_EvalNextParameter(p_stValue);
	lFirstValue=M_ReturnParam_lValue(p_stValue);
 
	switch(eFuncId)
	{
	case eFunc_Int:
		break;
 
	case eFunc_RandomInt:
		{
			long lMax;
			M_EvalNextParameter(p_stValue);
			lMax=M_ReturnParam_lValue(p_stValue);
 
			lFirstValue=RND_fn_lGetLongRandomValue(0,lFirstValue,lMax);
		}
		break;
	default:
		M_Full_GetSetParam_Integer(p_stValue,lFirstValue);
		return(p_stTree);
		break;
	}
	M_Full_GetSetParam_Integer(p_stValue,lFirstValue);
	return(p_stTree);
}
 
/*=====================================================================================================================================
 Name:		MATH_ValeurAbsolue
 Author:	yann le tensorer
 Created:	september 22,1998 , AI functions optimizations.
 Aim:		Returns the absolute value of a float
 Modif: september 24, 1998, bug correction: when argument was not of float type, this function returned shit!
 =====================================================================================================================================*/
tdstNodeInterpret *fn_p_stMathAbsoluteValue(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	MTH_tdxReal xAbs;
	
  /*evaluate the expression*/
	M_EvalNextParameter(p_stValue);
 
  /*convert it to float if relevant*/
  xAbs = M_ReturnParam_xValue(p_stValue);
 
  /*take its absolute value*/
	M_Full_GetSetParam_Float(p_stValue,MTH_M_xAbs(xAbs));
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stMathFunctionReal(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	MTH_tdxReal		xFirstReal;
 
	M_EvalNextParameter(p_stValue);
	xFirstReal=M_ReturnParam_xValue(p_stValue);
 
	switch(eFuncId)
	{
	case eFunc_Real:
		break;
 
	case eFunc_Sinus:
		xFirstReal=MTH_M_xSin( MTH_M_xDegToRad(xFirstReal) );
		break;
 
	case eFunc_Cosinus:
		xFirstReal=MTH_M_xCos( MTH_M_xDegToRad(xFirstReal) );
		break;
 
	case eFunc_Square:
		xFirstReal=MTH_M_xSqr(xFirstReal);
		break;
 
	case eFunc_SquareRoot:
		xFirstReal=MTH_M_xQuickSqrt(xFirstReal);
		break;
 
	case eFunc_RandomReal:
		{
			MTH_tdxReal xMax;
 
			M_EvalNextParameter(p_stValue);
			xMax=M_ReturnParam_xValue(p_stValue);
 
			xFirstReal=RND_fn_xGetRealRandomValue(0,xFirstReal,xMax);
		}
		break;
 
	case eFunc_Sign:
		xFirstReal = MTH_M_bLessZero(xFirstReal) 
			? MTH_M_xFloatToReal(-1.0f)
			: (MTH_M_bGreaterZero(xFirstReal) ? MTH_M_xFloatToReal(1.0f) : MTH_C_ZERO);
		break;
 
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
	case eFunc_Cube:
		xFirstReal=MTH_M_xMul(MTH_M_xSqr(xFirstReal), xFirstReal);
		break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
	case eFunc_Modulo:
		{
			MTH_tdxReal xMin, xMax, xModulo;
 
			M_EvalNextParameter(p_stValue);
			xMin=M_ReturnParam_xValue(p_stValue);
			M_EvalNextParameter(p_stValue);
			xMax=M_ReturnParam_xValue(p_stValue);
 
			xModulo = MTH_M_xSub(xMax, xMin);
 
			while(MTH_M_bGreaterEqual(xFirstReal, xMax))
				xFirstReal = MTH_M_xSub(xFirstReal, xModulo);
			while(MTH_M_bLess(xFirstReal, xMin))
				xFirstReal = MTH_M_xAdd(xFirstReal, xModulo);
		}
		break;
 
	case eFunc_MinimumReal :
		{
			MTH_tdxReal xMax;
 
			M_EvalNextParameter(p_stValue);
			xMax=M_ReturnParam_xValue(p_stValue);
 
			xFirstReal=MTH_M_xMin(xFirstReal,xMax);
		}
		break;
 
	case eFunc_MaximumReal :
		{
			MTH_tdxReal xMax;
 
			M_EvalNextParameter(p_stValue);
			xMax=M_ReturnParam_xValue(p_stValue);
 
			xFirstReal=MTH_M_xMax(xFirstReal,xMax);
		}
		break;
 
	case eFunc_DegreeToRadian :
		xFirstReal=MTH_M_xDegToRad(xFirstReal);
		break;
 
	case eFunc_RadianToDegree :
		xFirstReal=MTH_M_xRadToDeg(xFirstReal);
		break;
 
/*	case eFunc_AbsoluteValue :
		xFirstReal=MTH_M_xAbs(xFirstReal);
		break;
	*/
 
	case eFunc_LimitRealInRange:
		{
			MTH_tdxReal  xMin, xMax;
 
			M_EvalNextParameter(p_stValue);
			xMin = M_ReturnParam_xValue(p_stValue);
      if ( MTH_M_bLess(xFirstReal, xMin) )
      {
				xFirstReal = xMin;
        /*skip the remaining parameter, since we know that the value is oustide the range...*/
        p_stTree = fn_p_stSkipThisArgument(p_stTree);
      }
      else
      {
			  M_EvalNextParameter(p_stValue);
			  xMax = M_ReturnParam_xValue(p_stValue);
 
#ifndef U64
        /*the provided max must be greater than the provided min!*/
        SAF_M_AssertWithMsg(MTH_M_bGreaterEqual(xMax, xMin), "The max value must be greater or equal to the min value!");
#endif /* U64 */
 
			  if ( MTH_M_bGreater(xFirstReal, xMax) )
				  xFirstReal = xMax;
      }
		}
		break;
 
	default:
		M_Full_GetSetParam_Float(p_stValue,xFirstReal);
		return(p_stTree);
		break;
	}
    M_Full_GetSetParam_Float(p_stValue,xFirstReal);
	return(p_stTree);
}
 
 
/* VecteurLocalToGlobal,AbsoluteVector*/
/* compute an absolute (global) vector with a vector relative (local) to a perso*/
/* Yann le tensorer, optimizations sept,16 1998*/
tdstNodeInterpret *fn_p_stLocalToGlobal(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	MTH3D_tdstVector *p_stVector = &M_GetSetParam_stVertexValue(p_stValue);
	HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
 
	M_EvalNextParameter(p_stValue);
 
	MTH3D_M_vMulMatrixVector(p_stVector, &(hNewSuperObjPerso->hGlobalMatrix->stRotationMatrix), p_stVector);
 
	return(p_stTree);
}
 
/* FQ IAenC*/
tdstNodeInterpret *fn_p_stDummyFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
#ifdef U64
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	M_PrintfStopErrorN64(("DummyFunction %d, spo=0x%x!!", eFuncId, p_SuperObjPerso));
#endif /* U64 */

	return p_stTree;
}
 
/* VecteurGlobalToLocal,RelativeVector*/
/* compute a relative (local) to a perso vector from an absolute (global) vector*/
/* Yann le tensorer, optimizations sept,16 1998*/
tdstNodeInterpret *fn_p_stGlobalToLocal(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	MTH3D_tdstVector *p_stVector = &M_GetSetParam_stVertexValue(p_stValue);
	HIE_tdxHandleToSuperObject hNewSuperObjPerso;
	MTH3D_tdstMatrix stTransposedMatrix;
 
	fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
 
	M_EvalNextParameter(p_stValue);
 
	/*the rotation matrix is always normalized, we can transpose without problems*/
	MTH3D_M_vTranspMatrixWithoutBuffer(&stTransposedMatrix,&(hNewSuperObjPerso->hGlobalMatrix->stRotationMatrix))
	MTH3D_M_vMulMatrixVector(p_stVector, &stTransposedMatrix, p_stVector);
 
	return(p_stTree);
}
 
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stVectorFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	MTH3D_tdstVector *p_stVector = &M_GetSetParam_stVertexValue(p_stValue);
 
	M_EvalNextParameter(p_stValue);
 
	switch ( eFuncId )
	{
	case eFunc_RotateVector:
		{
			/* keep the rotated vector here */
			MTH3D_tdstVector stRotated = *p_stVector;
			MTH3D_tdstMatrix stMatrix;
			MTH_tdxReal xAngle;
			/* read the rotation angle */
			M_EvalNextParameter(p_stValue);
			xAngle = M_ReturnParam_xValue(p_stValue);
			if ( !MTH_M_bIsNull(xAngle) )
			{
				/* the rotation axis in in p_stVector */
				M_EvalNextParameter(p_stValue);
				SAF_M_AssertWithMsg(!MTH3D_M_bIsNullVector(p_stVector), "l'axe de rotation ne peut être indéterminé!");

				/* build a quaternion from the vector and the angle */
				xAngle = MTH_M_xMul(MTH_M_xDegToRad(xAngle),MTH_M_xNeg(MTH_C_Inv2));
 				MTH3D_M_vMulScalarVector(p_stVector,MTH_M_xSin(xAngle),p_stVector);
 				POS_fn_vQuatToMat(&stMatrix,p_stVector->xX,p_stVector->xY,p_stVector->xZ,MTH_M_xCos(xAngle));
				/* perform the rotation on the rotated vector, the result is already the the return structure */
		 		MTH3D_M_vMulMatrixVector(p_stVector, &stMatrix, &stRotated);
			}
			else
			{
				/* the angle is null, so ignore the rotation axis! */
				p_stTree = fn_p_stSkipThisArgument(p_stTree);
				/* and directly store the initial vector in the result value */
				M_Full_GetSetParam_p_stVertex(p_stValue, &stRotated);
			}
		}
		return p_stTree;
		break;

	case eFunc_TemporalVectorCombination:
	case eFunc_VectorCombination:
		{
			MTH_tdxReal xScalar, xTmp;
			MTH3D_tdstVector stV1 = *p_stVector;
 
			M_EvalNextParameter(p_stValue);
			xTmp = M_ReturnParam_xValue(p_stValue);
 
			SAF_M_AssertWithMsg(MTH_M_bGreaterEqualZero(xTmp) && MTH_M_bLessEqual(xTmp, MTH_C_ONE), "the scalar value must be between 0 and 1 inclusive");
 
			if ( (eFuncId == eFunc_VectorCombination) || MTH_M_bEqualZero(xTmp) )
				xScalar = xTmp;
			else
			{
				register int iNbFrames = MTH_M_xRealToLong(
					MTH_M_xAdd(
						MTH_M_xDiv(
							MTH_M_xLongToReal(M_ulGetUsefulDeltaTimeInMilliSeconds(g_stEngineStructure.stEngineTimer)),
							MTH_M_xMul(M_xGetFrameLength(g_stEngineStructure.stEngineTimer), MTH_M_xFloatToReal(1000.0f))
						),
						MTH_C_Inv2
					)
				);
				switch ( iNbFrames )
				{
				case 1:
					xScalar = xTmp; /* unchanged*/
					break;
 
				case 2:
					xScalar = MTH_M_xMul(xTmp, xTmp); /* squared*/
					break;
 
				case 3:
					xScalar = MTH_M_xMul(MTH_M_xMul(xTmp, xTmp), xTmp); /* cubed*/
					break;
 
				case 4:
					xTmp = MTH_M_xMul(xTmp, xTmp);
					xScalar = MTH_M_xMul(xTmp, xTmp); /* 4th power*/
					break;
 
				case 5:
					xScalar = MTH_M_xMul(xTmp, xTmp);
					xScalar = MTH_M_xMul(MTH_M_xMul(xScalar, xScalar), xTmp); /* 5th power*/
					break;
 
				default:
					xScalar = MTH_M_xMul(MTH_M_xMul(xTmp, xTmp), xTmp); /* 6th power*/
					xScalar = MTH_M_xMul(xScalar, xScalar);
				}
			}
 
			M_EvalNextParameter(p_stValue);
			/* p_stvector already points in there -> *p_stvector == V2*/
 
			/*result = V1 * r + V2 * ( 1 - r ) = r * (V1 - V2) + V2*/
			/* 6 mul, 1 sub, 3 add -> 3 sub, 3 mul, 3 add -> 3 mul changed into 2 sub -> faster*/
			MTH3D_M_vSubVector(&stV1, &stV1, p_stVector); /* V1 - V2*/
			MTH3D_M_vMulScalarVector(&stV1, xScalar, &stV1); /* ( V1 - V2) * r*/
			MTH3D_M_vAddVector(p_stVector, &stV1, p_stVector); /* ( V1 - V2) * r + V2*/
			/*this is enough, because we saved the result vector directly in the p_stValue, which is already of vector type*/
			/* -> no need to store the result here, because p_stValue already holds it*/
		}
		return p_stTree;
		break;
 
	case eFunc_VectorContribution:
		{
			MTH_tdxReal xScalar;
			/* the first vector is the one that gets projected on the contribution direction*/
			MTH3D_tdstVector stProjectedVector = *p_stVector;
			/*get the normalized vector on which it is projected*/
			M_EvalNextParameter(p_stValue);
 
			if ( !MTH3D_M_bIsNullVector(p_stVector) )
			{
				MTH3D_M_vNormalizeVector(p_stVector, p_stVector);
				/*get the proportionality coeff*/
				xScalar = MTH3D_M_xDotProductVector(p_stVector,&stProjectedVector);
				/*multiply the projecting direction by the coeff: this is the contribution of the projecting direction*/
				MTH3D_M_vMulScalarVector(p_stVector, xScalar, p_stVector);
				/*this is enough, because we saved the result vector directly in the p_stValue, which is already of vector type*/
				/* -> no need to store the result here, because p_stValue already holds it*/
			}
			else /*if the projection vector is null, keep the original projected vector*/
				*p_stVector = stProjectedVector;
		}
		return p_stTree;
		break;
 
	case eFunc_ScaledVector:
		{
			MTH3D_tdstVector stVertex;
			MTH_tdxReal xScalar;
 
			/*because we use p_stValue, that contains the vector, which will trash the X component when we read the next arg*/
			stVertex = *p_stVector;
			M_EvalNextParameter(p_stValue);
			xScalar = M_ReturnParam_xValue(p_stValue);
			MTH3D_M_vMulScalarVector(&stVertex, xScalar, &stVertex);
			M_Full_GetSetParam_p_stVertex(p_stValue, &stVertex);
		}
		return(p_stTree);
		break;
 
	case eFunc_GetVectorNorm:
		M_Full_GetSetParam_Float(p_stValue,MTH3D_M_xNormVector(p_stVector) );
		return(p_stTree);
		break;
 
	//KWN : begin
	case eFunc_GetScreenCoordinates:
		{
			/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
			MTH3D_tdstVector			stVertex = *p_stVector;			
			GLI_tdstCamera				*p_stCam;
			MTH3D_tdstVector			stTempVect3D;
			GLI_tdstAligned2DVector		stTempVect2D;			
			GLD_tdstViewportAttributes	*p_stVpt;			
			/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
			//Appel de la matrice de camera
			p_stVpt = &g_stEngineStructure.stViewportAttr;

			p_stCam=(((GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam);
			POS_fn_vMulMatrixVertex( &stTempVect3D, &(p_stCam->stMatrix), &stVertex);			
			GLI_xSerialProjection(p_stCam, 1, (GLI_tdstAligned3DVector*)&stTempVect3D, &stTempVect2D);
			stVertex.xX = stTempVect2D.xX * (1000.0 / g_stEngineStructure.stViewportAttr.dwWidth);
			stVertex.xY = stTempVect2D.xY * (1000.0 / g_stEngineStructure.stViewportAttr.dwHeight);

			M_Full_GetSetParam_p_stVertex(p_stValue, &stVertex);
		}
		
		return(p_stTree);
		break;
	//KWN : End
	default:
		break;
	}
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
	M_AIFatalError(E_uwAIFatalNotValidFunction);
#endif
	return(p_stTree);
}

tdstNodeInterpret *fn_p_stRealFunction (HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
/* XB 04/06/99 */
/*	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1); */
/* End XB 04/06/99 */
	MTH_tdxReal xValue1, xValue2, xCoeff, xResult, xTmp;
	int iNbFrames;
 
	M_EvalNextParameter(p_stValue);
	xValue1 = M_ReturnParam_xValue (p_stValue);

	M_EvalNextParameter(p_stValue);
	xCoeff = M_ReturnParam_xValue (p_stValue);

	M_EvalNextParameter(p_stValue);
	xValue2 = M_ReturnParam_xValue (p_stValue);

	SAF_M_AssertWithMsg(MTH_M_bGreaterEqualZero(xCoeff) && MTH_M_bLessEqual(xCoeff, MTH_C_ONE), "the scalar value must be between 0 and 1 inclusive");
 
	iNbFrames = MTH_M_xRealToLong(
		MTH_M_xAdd(
			MTH_M_xDiv(
				MTH_M_xLongToReal(M_ulGetUsefulDeltaTimeInMilliSeconds(g_stEngineStructure.stEngineTimer)),
				MTH_M_xMul(M_xGetFrameLength(g_stEngineStructure.stEngineTimer), MTH_M_xFloatToReal(1000.0f))
		),
			MTH_C_Inv2
		)
	);
	switch ( iNbFrames )
	{
	case 1:
		xResult = xCoeff; /* unchanged*/
		break;

	case 2:
		xResult = MTH_M_xMul(xCoeff, xCoeff); /* squared*/
		break;

	case 3:
		xResult = MTH_M_xMul(MTH_M_xMul(xCoeff, xCoeff), xCoeff); /* cubed*/
		break;

	case 4:
		xTmp = MTH_M_xMul(xCoeff, xCoeff);
		xResult = MTH_M_xMul(xTmp, xTmp); /* 4th power*/
		break;

	case 5:
		xTmp = MTH_M_xMul(xCoeff, xCoeff);
		xResult = MTH_M_xMul(MTH_M_xMul(xTmp, xTmp), xCoeff); /* 5th power*/
		break;

	default:
		xTmp = MTH_M_xMul(MTH_M_xMul(xCoeff, xCoeff), xCoeff); /* 6th power*/
		xResult = MTH_M_xMul(xTmp, xTmp);
	}
 
	/*result = x1 * r + x2 * ( 1 - r ) = r * (x1 - x2) + x2*/
	xValue1 = MTH_M_xSub ( xValue1, xValue2 ); /* x1 - x2 */		
	xResult = MTH_M_xMul ( xValue1,xResult );  /* r * (x1 - x2) */ 
	xResult = MTH_M_xAdd ( xResult, xValue2 ); /* r * (x1 - x2) + x2 */ 

	M_Full_GetSetParam_Float ( p_stValue, xResult );
	return p_stTree;
}



/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stHitPointsAndHitPointsMaxFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	tdstEngineObject *p_stObject;
	long lValue=0;
 
	/* get perso*/
	M_EvalNextParameter(p_stValue);
#if defined(__DEBUG_AI__)
	M_VerifyTypeOfParamAction(p_stValue, E_vt_Perso);
#endif
    p_stObject= M_GetSetParam_p_stEngineObjValue(p_stValue);
 
	switch(eFuncId)
	{
	case eFunc_GetHitPoints:
		lValue=(long) fn_ucGetHitPoints(p_stObject);
		break;
 
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
	case eFunc_AddAndGetHitPoints:
		M_EvalNextParameter(p_stValue); /* hitpoints to add*/
		fn_vAddHitPoints(p_stObject, (unsigned char) M_ReturnParam_lValue(p_stValue));
		lValue=(long) fn_ucGetHitPoints(p_stObject);
		break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
	case eFunc_SubAndGetHitPoints:
		M_EvalNextParameter(p_stValue); /* hitpoints to sub*/
		lValue=(long) fn_ucSubHitPoints(p_stObject, (unsigned char) M_ReturnParam_lValue(p_stValue));
		break;
 
	case eFunc_GetHitPointsMax:
		lValue=(long) fn_ucGetHitPointsMax(p_stObject);
		break;
 
	case eFunc_AddAndGetHitPointsMax:
		M_EvalNextParameter(p_stValue); /* hitpoints to add*/
		fn_vAddHitPointsMax(p_stObject, (unsigned char) M_ReturnParam_lValue(p_stValue));
		lValue=(long) fn_ucGetHitPointsMax(p_stObject);
		break;
 
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
	case eFunc_SubAndGetHitPointsMax:
		M_EvalNextParameter(p_stValue); /* hitpoints to sub*/
		lValue=(long) fn_ucSubHitPointsMax(p_stObject, (unsigned char) M_ReturnParam_lValue(p_stValue));
		break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
	default:
		lValue=0;
		break;
	}
	M_Full_GetSetParam_Integer(p_stValue, lValue );
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stTimeFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
    unsigned long ulCurrentTime=g_stEngineStructure.stEngineTimer.ulCurrentTimerCount;
 
	switch(eFuncId)
	{
	case eFunc_GetTime:
		break;
 
	case eFunc_GetElapsedTime:
		{
			unsigned long ulSavedTime;
 
			M_EvalNextParameter(p_stValue); /* dsgvar integer or constant*/
			ulSavedTime=M_GetSetParam_ulTimeValue(p_stValue);
			if (ulCurrentTime>=ulSavedTime)
			{
				ulCurrentTime-=ulSavedTime;
			}
			else
			{
				ulCurrentTime = (unsigned long)(-(long)(ulCurrentTime-ulSavedTime));
			}
		}
		break;
	default:
		break;
	}
	M_Full_GetSetParam_Time(p_stValue, ulCurrentTime );
	return(p_stTree);
}

/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stListFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	tdstList *p_stList;
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
 
	M_EvalNextParameter(p_stValue);
	p_stList=(tdstList *) M_GetSetParam_Dsg_List(p_stValue);
 
	switch(eFuncId)
	{
	case eFunc_GivePersoInList :
		M_EvalNextParameter(p_stValue);
		M_Full_GetSetParam_Perso(p_stValue, fn_p_stGetPersoInList(p_stList, (unsigned char) M_GetSetParam_lValue(p_stValue)) );
		return(p_stTree);
		break;
 
	case eFunc_ListSize :
		M_Full_GetSetParam_Integer(p_stValue, (long)M_ucNbEltInList(p_stList) );
		return(p_stTree);
		break;
 
	default:
		break;
	}
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
	M_AIFatalError(E_uwAIFatalNotValidFunction);
#endif
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stInputFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	M_EvalNextParameter(p_stValue);
#ifdef USE_IPT_DX5
	M_Full_GetSetParam_Integer(p_stValue,(MTH_M_xRealToLong(IPT_fn_xGetAnalogicValue((IPT_tdxHandleToEntryElement) M_GetSetParam_lValue(p_stValue)))));
#else /* USE_IPT_WIN */
	M_Full_GetSetParam_Integer(p_stValue,(IPT_fn_lGetAnalogicValue((IPT_tdxHandleToEntryElement) M_GetSetParam_lValue(p_stValue))));
#endif /* USE_IPT_WIN */
	return(p_stTree);
}
 
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stMiscFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	switch(eFuncId)
	{
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT 08/06/99 { */
	case eFunc_GetSubMapId:
		M_Full_GetSetParam_Integer(p_stValue, GAM_M_GetSubMap(fn_lGetSubMapNumber()));
		return p_stTree;
		break;
#endif /* _AI_EXCLUDE_NEVER_USED_ } */
 
  case eFunc_GetGlobalCounter: /* get the current value of the global map counter*/
		M_Full_GetSetParam_Integer(p_stValue, g_stEngineStructure.ucLevelGlobalCounter);
    return p_stTree;
    break;
 
  case eFunc_CountGeneratedObjects: /*get the number of always generated by the perso that are still active*/
    {
      long lNbAlways;
      /*get the perso to manage*/
			M_EvalNextParameter(p_stValue);
      /*scan the always list, and count those whose generator is that actor*/
      lNbAlways = fn_ulGetNumberOfAlwaysBelongingToMe(M_GetSetParam_p_stSupObjValue(p_stValue));
 
			M_Full_GetSetParam_Integer(p_stValue, lNbAlways);
    }
		return p_stTree;
		break;
 
 
	case eFunc_CastIntegerToChannel:
		/*read the integer argument*/
		M_EvalNextParameter(p_stValue);
		/*now say it is a channel identifier*/
		M_GetSetParam_Type(p_stValue) = E_vt_Module;
		return p_stTree;
		break;
 
	case eFunc_GenerateObject :
		{
			tdstEngineObject *p_stEngineObject=NULL;
			HIE_tdxHandleToSuperObject p_SuperObjPersoGenerated=NULL;
			MTH3D_tdstVector *p_stVertex;
 
			/* get always model*/
			M_EvalNextParameter(p_stValue);
#if defined(__DEBUG_AI__)
			M_VerifyTypeOfParamAction(p_stValue, E_vt_Perso);
#endif
			p_stEngineObject=M_GetSetParam_p_stEngineObjValue(p_stValue);
 
			/* get initial position*/
			M_EvalNextParameter(p_stValue);
#if defined(__DEBUG_AI__)
			M_VerifyTypeOfParamAction(p_stValue, E_vt_Vector);
#endif
			p_stVertex = &M_GetSetParam_stVertexValue(p_stValue);
 
#ifndef U64
#ifndef RETAIL
			/* test pour debuggage, en release, mais quand même pas en retail ... */
			if (p_stEngineObject==(void*)0x12345678)
			{
				/* ici, on a parfois un bug qui n'apparait qu'en release quand les donnees sont mauvaises*/
				/* en l'occurence, l'always n'a pas été chargé:*/
				/* cause habituelle: il n'est ni dans le game.fix, ni dans le .lvl du niveau*/
				__asm 
				{
					int 3
				}
 
				p_stEngineObject=NULL;
			}
#endif
#endif
 
			if (p_stEngineObject!= NULL)
			{
				if (fn_ucIsAnAlwaysModel(p_stEngineObject))
				{
					POS_tdstCompletePosition stMatrix;
#ifdef U64
					tdObjectType otObjectModelType = M_ObjectGetPersonalType(p_stEngineObject);
#else 
					tdObjectType otObjectModelType = M_ObjectGetModelType(p_stEngineObject);
#endif 
 
					POS_fn_vSetIdentityMatrix(&stMatrix);
					POS_fn_vSetTranslationVector(&stMatrix,p_stVertex);
 
					p_SuperObjPersoGenerated = fn_p_stAllocateAlways(otObjectModelType, gp_stDynamicWorld, p_SuperObjPerso, 0, &stMatrix);
					/*Bart : M_Full_GetSetParam_Perso(p_stValue, p_SuperObjPersoGenerated);*/
 /* ANNECY MT - 18/09/98 { next call is now useless
					if ( p_SuperObjPersoGenerated != NULL )
					{
						fn_vForceActiveAnObject(M_GetEngineObject( p_SuperObjPersoGenerated ) );
					}
   END ANNECY MT } */
				}
			}
      M_Full_GetSetParam_Perso(p_stValue, p_SuperObjPersoGenerated); /* NULL if error !*/
		}
		return p_stTree;
		break;
 
	default:
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
		M_AIFatalError(E_uwAIFatalNotValidFunction);
#endif
		return(p_stTree);
		break;
	}
}
 
/*
*=================================================================================================
*=================================================================================================
*/
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
tdstNodeInterpret *fn_p_stGameMaterialFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	GMT_tdxHandleToGameMaterial	hGameMaterial=GMT_C_ulInvalidHandle;
    DNM_tdstReport *p_stDynamReport;
 
    /********************************************************************************/
    /* BEWARE THE ULTRA OPERATOR : Must be at the beginning and respect this syntax */
    /********************************************************************************/
    HIE_tdxHandleToSuperObject hNewSuperObjPerso;
    fn_vGetUltraOperatorPerso(fn_ucGetFunctionUltraOperator(eFuncId),p_SuperObjPerso,&hNewSuperObjPerso);
    /********************************************************************************/
	switch ( eFuncId )
	{
	case eFunc_GetLastTraversedMaterialType:
	case eFunc_GetLastTraversedMaterial:
		{
			MS_tdxHandleToBrain hBrain;
/* Oliv' - Portage v14 - to reduce number of warnings*/
			if( (hBrain = M_GetMSHandle(hNewSuperObjPerso,Brain)) != 0 ) /*VOLUNTARY ASSIGNMENT!*/
			{
				/*read the handle of the collided material*/
				hGameMaterial = M_hGetLastCollidedGoThroughMaterialOfBrain(hBrain);
				if ( GMT_fn_b_ulIsValid(hGameMaterial) )
				{
					/* return the cmt identifier instead*/
					if ( eFuncId == eFunc_GetLastTraversedMaterialType )
					{
 
						GMT_tdxHandleToCollideMaterial hMaterialCollide = GMT_fn_hGetCollideMaterial(hGameMaterial);
						GMT_tdxMask xMask = (GMT_tdxMask) 0;
						if ( hMaterialCollide != GMT_C_InvalidCollideMaterial )
							xMask = GMT_fn_hGetCollideMaterialIdentifier(hMaterialCollide);
						/*set the return value and exit*/
						M_Full_GetSetParam_Mask(p_stValue,xMask);
					}
				}
				else
					M_Full_GetSetParam_Mask(p_stValue,0);
			}
		}
		return p_stTree;
		break;
 
	case eFunc_GetCurrentCollidedGMT:
		if ((p_stDynamReport = fn_pstGetDNMReport(hNewSuperObjPerso)) != NULL)
			hGameMaterial=DNM_M_hObstacleGetCollidedMaterial(DNM_M_p_stReportGetGround(p_stDynamReport));
		break;
	default:
		break;
	}
 
	M_Full_GetSetParam_hGameMaterial(p_stValue,hGameMaterial);
	return(p_stTree);
}
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
/*
*=================================================================================================
*=================================================================================================
*/
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
tdstNodeInterpret *fn_p_stVisualGameMaterialFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	GMT_tdxHandleToGameMaterial		hGameMaterial;
	ACP_tdxHandleOfMaterial			hVisualMaterial=NULL;
	MTH_tdxReal xValue=MTH_C_ZERO;
	GEO_tdstColor stColor;
	long lValue;
	float fU,fV;
 
	M_EvalNextParameter(p_stValue);
	hGameMaterial=M_GetSetParam_hGameMaterial(p_stValue);
    if (GMT_fn_b_ulIsValid(hGameMaterial))
	{
		hVisualMaterial=GMT_fn_hGetVisualMaterial(hGameMaterial);
		if (hVisualMaterial!=NULL)
		{
			switch(eFuncId)
			{
			case eFunc_GetVisualGMTColor:
				#ifdef CONST_VMT
					stColor.xR = stColor.xG = stColor.xB = 0.7;
				#else
				GLI_xGetMaterialColor(hVisualMaterial,&stColor);
				#endif
				fn_vConvertColorToParam(&stColor,p_stValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTSpecularCoef:
				#ifdef CONST_VMT
					stColor.xR = stColor.xG = stColor.xB = 0.9;
					/*lValue = 5;*/
				#else
				GLI_xGetMaterialSpecularCoef(hVisualMaterial,&lValue,&stColor);
				#endif
				fn_vConvertColorToParam(&stColor,p_stValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTSpecularExponent:
				#ifdef CONST_VMT
					/*stColor.xR = stColor.xG = stColor.xB = 0.7;*/
					lValue = 5;
				#else
				GLI_xGetMaterialSpecularCoef(hVisualMaterial,&lValue,&stColor);
				#endif
				M_Full_GetSetParam_Integer(p_stValue,lValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTDiffuseCoef:
				#ifdef CONST_VMT
					stColor.xR = stColor.xG = stColor.xB = 0.7;
				#else
					GLI_xGetMaterialDiffuseCoef(hVisualMaterial,&stColor);
				#endif
				fn_vConvertColorToParam(&stColor,p_stValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTAmbientCoef:
				#ifdef CONST_VMT
					stColor.xR = stColor.xG = stColor.xB = 0.1;
				#else
					GLI_xGetMaterialAmbientCoef(hVisualMaterial,&stColor);
				#endif
				fn_vConvertColorToParam(&stColor,p_stValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTTextureScrollingCoefU:
				GLI_xGetMaterialTextureScrollingCoef(hVisualMaterial,/*NOT_USED_FOR_THE_MOMENT*/ 0,&lValue,&fU,&fV);
				xValue=MTH_M_xFloatToReal(fU);
				M_Full_GetSetParam_Float(p_stValue,xValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTTextureScrollingCoefV:
				GLI_xGetMaterialTextureScrollingCoef(hVisualMaterial,/*NOT_USED_FOR_THE_MOMENT*/ 0,&lValue,&fU,&fV);
				xValue=MTH_M_xFloatToReal(fV);
				M_Full_GetSetParam_Float(p_stValue,xValue);
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTFrame:
				M_Full_GetSetParam_Integer(p_stValue,GLI_lGetCurrentAnimatedTextureNumber(hVisualMaterial));
				return(p_stTree);
				break;
 
			case eFunc_GetVisualGMTNumberOfFrames:
				M_Full_GetSetParam_Integer(p_stValue,GLI_lGetMaterialNumberOfAnimatedTexture(hVisualMaterial));
				return(p_stTree);
				break;
 
/*XB(07/01/98)*/
			default:
#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
				M_AIFatalError(E_uwAIFatalNotValidFunction);
				return(p_stTree);
#endif
				break;
/*End XB*/
			}
		}
	}
	M_Full_GetSetParam_Integer(p_stValue,0);
	return(p_stTree);
}
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
/*
*=================================================================================================
*=================================================================================================
*/
#if defined(__DEBUG_AI__)
void fn_vWarningForColor(HIE_tdxHandleToSuperObject p_SuperObjPerso)
{
	char MyMsg[500];
	AI_tdstMind *p_stMind=(AI_M_stGetMindOfSuperObj(p_SuperObjPerso));
	sprintf(MyMsg,"during color evaluation from p_stMind (%s)\n current comport (%s)\n",AI_M_szGetPersoName(p_stMind),M_GetNameComport(M_GetCurrentComport(M_GetIntellOrReflex(p_stMind))));
	M_AIWarningErrorAndNeverStopForDebug(E_uwAIWarningTruncateAffectation, C_ucErmNoOpenInfoWindow,MyMsg);
}
#endif
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalRedOrGreenOrBlueOrAlpha(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,long *lValue)
{
	tdstGetSetParam stParam;
 
	M_EvalNextParameter(&stParam);
	*lValue=M_ReturnParam_lValue(&stParam);
#if defined(__DEBUG_AI__)
	if ( (*lValue<0) || (*lValue>100) )
	{
		fn_vWarningForColor(p_SuperObjPerso);
	}
#endif
	if (*lValue>100) *lValue=100;
	else if (*lValue<0) *lValue=0;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalRed(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	long lValue;
	p_stTree=fn_p_stEvalRedOrGreenOrBlueOrAlpha(p_SuperObjPerso,p_stTree,&lValue);
	M_GetSetParam_RedValue(p_stValue)=lValue;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalGreen(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	long lValue;
	p_stTree=fn_p_stEvalRedOrGreenOrBlueOrAlpha(p_SuperObjPerso,p_stTree,&lValue);
	M_GetSetParam_GreenValue(p_stValue)=lValue;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalBlue(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	long lValue;
	p_stTree=fn_p_stEvalRedOrGreenOrBlueOrAlpha(p_SuperObjPerso,p_stTree,&lValue);
	M_GetSetParam_BlueValue(p_stValue)=lValue;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalAlpha(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	long lValue;
	p_stTree=fn_p_stEvalRedOrGreenOrBlueOrAlpha(p_SuperObjPerso,p_stTree,&lValue);
	M_GetSetParam_AlphaValue(p_stValue)=lValue;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalRGB(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	M_GetSetParam_AlphaValue(p_stValue)=0;
 
	p_stTree=fn_p_stEvalRed(p_SuperObjPerso,p_stTree,p_stValue);
	p_stTree=fn_p_stEvalGreen(p_SuperObjPerso,p_stTree,p_stValue);
	p_stTree=fn_p_stEvalBlue(p_SuperObjPerso,p_stTree,p_stValue);
 
	M_GetSetParam_Type(p_stValue)=E_vt_Color;
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static tdstNodeInterpret *fn_p_stEvalRGBA(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	p_stTree=fn_p_stEvalRGB(p_SuperObjPerso, p_stTree,p_stValue);
	p_stTree=fn_p_stEvalAlpha(p_SuperObjPerso,p_stTree,p_stValue);
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
static long fn_lAddColor(long color1,long color2)
{
	RGBAStruct c1;
	RGBAStruct c2;
	RGBAStruct c3;
	long r,g,b,a;
 
	RGBA_Color(c1)=color1;
	RGBA_Color(c2)=color2;
 
	r=RGBA_Red(c1)	 + RGBA_Red(c2);
	g=RGBA_Green(c1) + RGBA_Blue(c2);
	b=RGBA_Blue(c1)	 + RGBA_Green(c2);
	a=RGBA_Alpha(c1) + RGBA_Alpha(c2);
 
	if (r<0) r=0; else if (r>100) r=100;
	if (g<0) g=0; else if (g>100) g=100;
	if (b<0) b=0; else if (b>100) b=100;
	if (a<0) a=0; else if (a>100) a=100;
 
	RGBA_Red(c3)=r;
	RGBA_Green(c3)=g;
	RGBA_Blue(c3)=b;
	RGBA_Alpha(c3)=a;
 
	return(RGBA_Color(c3));
}
 
/*
*=================================================================================================
*=================================================================================================
*/
tdstNodeInterpret *fn_p_stColorFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	long lValue=0;
	long color1=0,color2=0;
	RGBAStruct rgba;
 
	RGBA_Color(rgba)=0;
 
	switch(eFuncId)
	{
	case eFunc_ColorRedGreenBlueAlpha:
		M_GetSetParam_lValue(p_stValue)=0;
		return(fn_p_stEvalRGBA(p_SuperObjPerso,p_stTree,p_stValue));
		break;
 
	case eFunc_ColorRedGreenBlue:
		M_GetSetParam_lValue(p_stValue)=0;
		return(fn_p_stEvalRGB(p_SuperObjPerso,p_stTree,p_stValue));
		break;
 
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
	case eFunc_AddColor:
		M_EvalNextParameter(p_stValue);	color1=M_GetSetParam_ColorValue(p_stValue);
		M_EvalNextParameter(p_stValue);	color2=M_GetSetParam_ColorValue(p_stValue);
		M_Full_GetSetParam_ColorValue(p_stValue,fn_lAddColor(color1,color2));
		return(p_stTree);
		break;
 
	case eFunc_AddRed:
		M_EvalNextParameter(p_stValue);	color1=M_GetSetParam_ColorValue(p_stValue);
		M_EvalNextParameter(p_stValue);
		RGBA_Red(rgba)=M_ReturnParam_lValue(p_stValue);	color2=RGBA_Color(rgba);
		M_Full_GetSetParam_ColorValue(p_stValue,fn_lAddColor(color1,color2));
		return(p_stTree);
		break;
 
	case eFunc_AddGreen:
		M_EvalNextParameter(p_stValue); color1=M_GetSetParam_ColorValue(p_stValue);
		M_EvalNextParameter(p_stValue);
		RGBA_Green(rgba)=M_ReturnParam_lValue(p_stValue); color2=RGBA_Color(rgba);
		M_Full_GetSetParam_ColorValue(p_stValue,fn_lAddColor(color1,color2));
		return(p_stTree);
		break;
 
	case eFunc_AddBlue:
		M_EvalNextParameter(p_stValue);	color1=M_GetSetParam_ColorValue(p_stValue);
		M_EvalNextParameter(p_stValue);
		RGBA_Blue(rgba)=M_ReturnParam_lValue(p_stValue); color2=RGBA_Color(rgba);
		M_Full_GetSetParam_ColorValue(p_stValue,fn_lAddColor(color1,color2));
		return(p_stTree);
		break;
 
	case eFunc_AddAlpha:
		M_EvalNextParameter(p_stValue);	color1=M_GetSetParam_ColorValue(p_stValue);
		M_EvalNextParameter(p_stValue);
		RGBA_Alpha(rgba)=M_ReturnParam_lValue(p_stValue); color2=RGBA_Color(rgba);
		M_Full_GetSetParam_ColorValue(p_stValue,fn_lAddColor(color1,color2));
		return(p_stTree);
		break;
 
	case eFunc_ColorRed:
		M_EvalNextParameter(p_stValue);
		lValue=M_GetSetParam_RedValue(p_stValue);
		break;
 
	case eFunc_ColorGreen:
		M_EvalNextParameter(p_stValue);
		lValue=M_GetSetParam_GreenValue(p_stValue);
		break;
 
	case eFunc_ColorBlue:
		M_EvalNextParameter(p_stValue);
		lValue=M_GetSetParam_BlueValue(p_stValue);
		break;
 
	case eFunc_ColorAlpha:
		M_EvalNextParameter(p_stValue);
		lValue=M_GetSetParam_AlphaValue(p_stValue);
		break;
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/
 
	default:
		break;
	}
 
#if defined(__DEBUG_AI__)
	if ( (M_GetSetParam_Type(p_stValue)!=E_vt_Color)  || (lValue<0) || (lValue>100) )
	{
		fn_vWarningForColor(p_SuperObjPerso);
	}
#endif
	if (lValue<0) lValue=0; else if (lValue>100) lValue=100;
	M_Full_GetSetParam_Integer(p_stValue,lValue);
	return(p_stTree);
}
 
/*
*=================================================================================================
*=================================================================================================
*/
#if !defined(_AI_EXCLUDE_NEVER_USED_) /* MT {*/
tdstNodeInterpret *fn_p_st_SPO_GetDrawFlag(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree,tdstGetSetParam *p_stValue)
{
    tdstGetSetParam				stParam;
	HIE_tdxHandleToSuperObject	hSpo;
	long						lBit;
	long						lReturn = -1;
 
	/* get the function parameters*/
	M_EvalNextParameter(&stParam);
	hSpo=M_GetSetParam_SuperObjectValue(&stParam);
	M_EvalNextParameter(&stParam);
	lBit = M_GetSetParam_lValue(&stParam);
 
	if ( (hSpo != NULL) && (lBit >= 0) && (lBit <= 31 ) )
	{
		lReturn = (HIE_fn_lGetSuperObjectDrawMask( hSpo ) & (1 << lBit) ) ? 1 : 0;
	}
 
	M_Full_GetSetParam_Integer(p_stValue,lReturn );
	return(p_stTree);
}
#endif /* _AI_EXCLUDE_NEVER_USED_ }*/


/*
*=================================================================================================
*=================================================================================================
*/

tdstNodeInterpret *fn_p_stGetFrameLength(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	M_Full_GetSetParam_Float(p_stValue, g_stEngineStructure.stEngineTimer.xFrameLength);
	return (p_stTree);
}
 
 

/**********************************************************************
* Function fn_p_stIsAValidSlotName
* Parameters:
*		TEXT : Slot Name		
*		CONSTANT : index of slot
*		CONSTANT : Number of slots
**********************************************************************/
tdstNodeInterpret * fn_p_stIsAValidSlotName(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	tdstGetSetParam stParam;
	char			*pszString = NULL;
	char			a3_cName[4];
	char			a3_cDummyName[4];

	long			lIndex, lNumberOfSlots;
	long			i;
	long			lResult = 0;
	int				  Version;
	int				  NbSaveGameSlot;
#ifndef U64
	StructRecupPosSlot *p_CurrentStructRecupPosSlot;
#endif // U64

	M_EvalNextParameter(&stParam);
	pszString = (char *)fn_szGetStringFromTextOrStringParam(&stParam);
 
	M_EvalNextParameter(&stParam);
	lIndex = M_GetSetParam_lValue(&stParam) - 1;
 
	M_EvalNextParameter(&stParam);
	lNumberOfSlots = M_GetSetParam_lValue(&stParam);
 
    while( *pszString++ == '/')
    {
         while( *pszString++ != ':' );
    }
 
	memcpy(&a3_cName[0],pszString-1,3);
	pszString = &a3_cName[0];
 
	pszString[3] = '\0';
	a3_cDummyName[3] = '\0';

#ifndef U64
#ifdef ACTIVE_EDITOR
	Version = fn_iVersionN64_PC();
	if ( Version == 1 /* N64 */)
	{
		for (i=0; i < lNumberOfSlots; i++)
			{
				memcpy(a3_cDummyName , g_stGameOptions.a_szSlotNames[i], 3);
				if	((i != lIndex) &&
					(stricmp(a3_cDummyName, pszString) ==0))
				{
					lResult = i+1;
					break;
				}
			}
	}
	else if( Version == 2 /* PC */)
	{
		//int NbSaveGameSlot = fn_lGetNbAvailableSlotsPc();
		NbSaveGameSlot = g_ucNbSaveGameSlots;
		strncpy( g_a_szSlotNames, pszString, 3);

		p_CurrentStructRecupPosSlot = g_p_LastStructRecupPosSlot;
		for (i=0; i < NbSaveGameSlot; i++)
		{
			if	((i != lIndex) &&
				(strncmp( p_CurrentStructRecupPosSlot->a_szSlotNames, pszString, 3) ==0)) lResult = i+1;
			
			p_CurrentStructRecupPosSlot	= p_CurrentStructRecupPosSlot->pt_NextStructRecupPosSlot;
		}
		if( lResult != 0 ) g_bIsGameAlreadyExist = TRUE; //  utile pour le test dans fn_bSaveGameInSlot
		else g_bIsGameAlreadyExist = FALSE; 
	}
#else // PC sans editeur
	//int NbSaveGameSlot = fn_lGetNbAvailableSlotsPc();
	NbSaveGameSlot = g_ucNbSaveGameSlots;
	strncpy( g_a_szSlotNames, pszString, 3);

	p_CurrentStructRecupPosSlot = g_p_LastStructRecupPosSlot;
	for (i=0; i < NbSaveGameSlot; i++)
	{
		if	((i != lIndex) &&
			(strncmp( p_CurrentStructRecupPosSlot->a_szSlotNames, pszString, 3) ==0)) lResult = i+1;
		
		p_CurrentStructRecupPosSlot	= p_CurrentStructRecupPosSlot->pt_NextStructRecupPosSlot;
	}
	if( lResult != 0 ) g_bIsGameAlreadyExist = TRUE; //  utile pour le test dans fn_bSaveGameInSlot
	else g_bIsGameAlreadyExist = FALSE; 
#endif // EDITOR
#else // U64
	for (i=0; i < lNumberOfSlots; i++)
	{
		memcpy(a3_cDummyName , g_stGameOptions.a_szSlotNames[i], 3);
		if	((i != lIndex) &&
			(stricmp(a3_cDummyName, pszString) ==0))
		{
			lResult = i+1;
			break;
		}
	}
#endif // U64

	M_Full_GetSetParam_Integer( p_stValue, lResult );

	return(p_stTree);
}


tdstNodeInterpret *fn_p_stSaveGameFunction(HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	enum tdeFuncId_ eFuncId=M_eFuncIdInterpret(p_stTree-1);
	ACP_tdxBool bReturn = FALSE;
 	int Version = 0;

	/*
	#if defined(__DEBUG_AI__)
	M_VerifyTypeOfParamAction(&stParam,E_vt_Text);
	#endif
	*/

	switch ( eFuncId )
	{
	case eFunc_SaveGame:
	case eFunc_LoadGame:
	case eFunc_EraseGame:
		{
			long lSlotId;

			tdstGetSetParam stParam;
			M_EvalNextParameter(&stParam);

/***************F PEREZ ************/
#ifndef U64
			lSlotId = M_GetSetParam_lValue(&stParam);
			//lSlotId = fn_bRecupSlotNum(lSlotId);
#else
			lSlotId = M_GetSetParam_lValue(&stParam);
#endif // !U64

			/* Get the name of the slot*/
			 //M_EvalNextParameter(&stParam);
			 //pszSlotName = (char *)fn_szGetStringFromTextOrStringParam(&stParam) ;
			/*if( pszSlotName == NULL )
			{
				strncpy(szDummy, fn_cRecupSlotName(lSlotId), 3);
				szDummy[3] ='\0';
				 M_Full_GetSetParam_String(&stParam, szDummy);
			}*/

			  /* Get the number of lums */
			 //M_EvalNextParameter(&stParam);
			 //lNbOfLums = M_GetSetParam_lValue(&stParam);

			switch ( eFuncId )
			{
			case eFunc_SaveGame:

#ifdef U64
				SAF_M_AssertWithMsg((lSlotId >= 1 && lSlotId <= C_ucNbSaveGameSlots),"Slot de sauvegarde inexistant");
#else
				SAF_M_AssertWithMsg(( lSlotId >= 1 && lSlotId <= (long) fn_lGetNbAvailableSlotsPc() ),"Slot de sauvegarde inexistant");
#endif
				
				/*before we save the whole game status, force the current level to save itself, so that it is coherent with the rest*/
				if( (bReturn=fn_bLevelSaveGameAll()) == FALSE )
					break;
				/*make the player data save themselves as well for the same reason*/
				if( (bReturn=fn_bPlayerSaveGameAll()) == FALSE )
					break;
				/*now copy the current game status in the specified slot*/
				bReturn=fn_bSaveGameInSlot(lSlotId);
				g_stGameOptions.ulCurrentSlot = (unsigned long)lSlotId;
				break;
 
			case eFunc_LoadGame:

#ifdef U64
				SAF_M_AssertWithMsg((lSlotId >= 1 && lSlotId <= C_ucNbSaveGameSlots),"Slot de sauvegarde inexistant");
#else
				SAF_M_AssertWithMsg(( lSlotId >= 1 && lSlotId <= (long) fn_lGetNbAvailableSlotsPc() ),"Slot de sauvegarde inexistant");
#endif
				
				bReturn = fn_bLoadGameFromSlot(lSlotId);
				g_stGameOptions.ulCurrentSlot = (unsigned long)lSlotId;
/*FB120799 : As soon as we have loaded a saved game, we initialise the designer variables (without waiting for the next map loading)
this is necessary for the map 'menu' wich tests the array of bits as soon as it is loaded in order to know which map needs to be loaded : 'mapmonde' or 'jail10' 
*/
				if( fn_bLoadPlayerSaveGameAfterLoadLevel() && bReturn)
				{
					SAI_fn_bInitAllWhen(SAI_eInitWhenPlayerGameSavedLoaded);
				}

				break;
 
 
			case eFunc_EraseGame:
			/* Erase a saved game or the hidden slot (current save game) */
#ifdef U64
				SAF_M_AssertWithMsg((lSlotId >= 1 && lSlotId <= C_ucNbSaveGameSlots),"Slot de sauvegarde inexistant");
				bReturn = fn_bEraseGameInSlot(lSlotId);
				memset(g_stGameOptions.a_szSlotNames[lSlotId-1] , 0 , C_ucSaveGameSlotNameLength);
#else /* PC */
#ifdef ACTIVE_EDITOR
				Version = fn_iVersionN64_PC();
				if ( Version == 1 /* U64 */)
				{
					SAF_M_AssertWithMsg((lSlotId >= 1 && lSlotId <= C_ucNbSaveGameSlots),"Slot de sauvegarde inexistant");
					bReturn = fn_bEraseGameInSlot(lSlotId);
					memset(g_stGameOptions.a_szSlotNames[lSlotId-1] , 0 , C_ucSaveGameSlotNameLength);
				}
				else if( Version == 2 /* PC */)
				{
					SAF_M_AssertWithMsg(( lSlotId >= 1 && lSlotId <= (long) fn_lGetNbAvailableSlotsPc() ),"Slot de sauvegarde inexistant");
					bReturn = fn_bEraseGameInSlot(lSlotId);
					bReturn = fn_bEraseGameInSlotList(lSlotId);
				}
#else
				SAF_M_AssertWithMsg(( lSlotId >= 1 && lSlotId <= (long) fn_lGetNbAvailableSlotsPc() ),"Slot de sauvegarde inexistant");
				bReturn = fn_bEraseGameInSlot(lSlotId);
				bReturn = fn_bEraseGameInSlotList(lSlotId);
#endif // ACTIVE_EDITOR
#endif // U64
				if (lSlotId == (long) g_stGameOptions.ulCurrentSlot) // FB for Guillaume S.
					g_stGameOptions.ulCurrentSlot = 0;
				break;
 
			default:
				break;
			}
		}
		break;

	case eFunc_GetCurrentSlot:
		bReturn = g_stGameOptions.ulCurrentSlot;
		break;

	case eFunc_RepairCorruptSlot:
		bReturn = TRUE;
		break;

	default:
		#if defined(__DEBUG_AI__) || (defined(U64) && defined(D_CHECK_AI_FPCO))
		M_AIFatalError(E_uwAIFatalNotValidProcedure);
		#endif
		break;
	}

	M_Full_GetSetParam_Integer( p_stValue, (long)bReturn );
	return(p_stTree);
}


/************************************************************************************************************************************************/
/*KWN : begin***********************************************************************************************************************************************/
tdstNodeInterpret *fn_p_GetScreenDSActif (HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	M_Full_GetSetParam_Integer( p_stValue, 0 );
	return p_stTree;
}

tdstNodeInterpret *fn_p_GetStyletCordinates (HIE_tdxHandleToSuperObject p_SuperObjPerso, tdstNodeInterpret *p_stTree, tdstGetSetParam *p_stValue)
{
	MTH3D_tdstVector stVector;
	int X,Y;

	//TP_GetLatestCalibratedPointInAuto(&disp_point);		
	DS_bTPGetPosition(&X,&Y);

	stVector.xX = MTH_M_xMul(MTH_M_xLongToReal(X), MTH_M_xFloatToReal(1000.0f / (float)g_stEngineStructure.stViewportAttr.dwWidth));
	stVector.xY = MTH_M_xMul(MTH_M_xLongToReal(Y), MTH_M_xFloatToReal(1000.0f / (float)g_stEngineStructure.stViewportAttr.dwHeight));
	stVector.xZ = MTH_C_ZERO;

	M_Full_GetSetParam_p_stVertex(p_stValue,&stVector);
	
	return p_stTree;
}
/*KWN : End***********************************************************************************************************************************************/
/************************************************************************************************************************************************/


/*
*=================================================================================================
*=================================================================================================
*/
#if !defined(OPTIMIZED_COMMAND)
#include "ProtFunc.h"
 
void fn_vInitFunctionEntries(void)
{
	/* Init*/
#if defined(__DEBUG_AI__)
	fn_vInitFunctionTable(fn_p_stDefaultFunction);
#endif /* __DEBUG_AI__*/
 
	/* Function definitions*/
#define M_DEFINE_FUNCTION(a,b,english,c,d,e,f,g) \
	fn_vDefineFunctionEntry(M_FUNCTION_ENTRY(a,b,english,c,d,e,f)); \
	fn_vSetFunctionUltraOperator(a,g);
#include "DefFunc.h"
#undef M_DEFINE_FUNCTION
 
	/* Check*/
#if defined(__DEBUG_AI__)
	fn_vCheckFunctionTable(fn_p_stDefaultFunction);
#endif /* __DEBUG_AI__*/
}
#endif /* OPTIMIZED_COMMAND*/
 
 
