/*========================================================================= * Always.c : This module contain all always functions * This is a part of the Game project. * * Version 1.0 * Creation date 09/08/96 * Revision date * * That file needs to be compatible for all platforms. * * (c) Ubi Studios 1996 *=======================================================================*/ /* *======================================================================= Modifications: New LST_M_??? Macros / Michaël / 070297 *=======================================================================*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #define D_3dData_StructureDefine /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #include "ToolsCPA.h" #include "Options/Options.h" #include "Macros.h" #include "safe.h" #include "Actions/AllActs.h" #define D_SectInfo_StructureDefine #include "Actions/SectInfo.h" #undef D_SectInfo_StructureDefine #include "Structur/Anim_s.h" #include "Structur/EngMode.h" #include "Structur/ErrGame.h" #include "Structur/MemGame.h" #include "Structur/Objects.h" #include "Structur/State.h" #include "Structur/StdObjSt.h" #include "Family.h" #include "Always.h" #include "GameEng.h" #include "ObjInit.h" #include "ZeMem.h" #include "ChanList.h" #include "MainChar.h" #include "Micros.h" #include "PlayAnim/PlayAnim.h" #ifdef U64 #include "RastMem.h" #endif /* U64 */ /* ANNECY AV DEMO {*/ #ifndef U64 #include "Specif/Demos.h" #endif /* END ANNECY AV }*/ #include "Micros.h" #include "objtype.h" #include "textfrmt.h" #ifdef GAM_USE_SNA #include "SNA.h" /*#include "PTC.h"*/ #endif /* GAM_USE_SNA */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #ifdef U64 extern void fn_vFirstInitMorphTaskList(unsigned long _ulNbMorphTasks, unsigned long _ulNbElements, unsigned long _ulNbPoints); #else /* U64 */ extern void fn_vFirstInitMorphTaskList(); #endif /* U64 */ extern void fn_vLastDeinitMorphTaskList(); extern ACP_tdxBool fn_bIsInFix(struct tdstEngineObject_ *p_stObject); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #if defined (ACTIVE_EDITOR) || defined (RETAIL) #define ENGassert(param) #else #define ENGassert(param) assert(param) #endif #if (!defined(FINAL_VERSION) || defined(FINAL_VERSION_FOR_TESTERS)) && defined(U64) #define D_WANT_OPTIMIZE_MEMORY #endif /* (!defined(FINAL_VERSION) || defined(FINAL_VERSION_FOR_TESTERS)) && defined(U64) */ #ifdef D_WANT_OPTIMIZE_MEMORY long g_lNbAllocatedAlways; long g_lMaxNbAllocatedAlways; long g_lAllowedNbAllocatedAlways; #endif /* D_WANT_OPTIMIZE_MEMORY */ //End XB /*----------------------------------------------------------------------------- * Description : Allocate an always engine object * with all game structures *----------------------------------------------------------------------------- * Input : Family, model and personal * Output : Pointer to the object *----------------------------------------------------------------------------- * Creation date : 09/10/96 Author : Francois *---------------------------------------------------------------------------*/ struct tdstEngineObject_ *fn_p_stAllocateAlwaysEngineObject(tdObjectType otObjectFamilyType,tdObjectType otObjectModelType,tdObjectType otObjectPersonalType) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ tdstEngineObject *p_stTempObject; /* long i;*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeEngineObject , 0 ); p_stTempObject=(tdstEngineObject *)M_p_GameMallocInHLM(sizeof(tdstEngineObject)); /* ANNECY AV {*/ /* Now, the mini-structures are allocated only when necessary M_ForAllMiniStructure(i) { g_a_stStructureHandleFunction[i].p_fn_vAllocFunction(p_stTempObject); } */ /*memset (p_stTempObject , 0 , sizeof (tdstEngineObject));*/ /* AR9904 Already done in alloc function */ /* We only allocated the StandardGame, 3dData and Brain mini-structures*/ #ifdef SHOW_RAST_MEM /*h_StandardGame*/ RM_fn_vInitAddInfo(); fn_vStdGameAlloc(p_stTempObject); RM_fn_vAddInfo(eMS4AStandardGame,eSubAlwaysGam,eGam); /*h_3dData*/ RM_fn_vInitAddInfo(); fn_v3dDataAlloc (p_stTempObject); RM_fn_vAddInfo(eMS4A3dData,eSubAlwaysGam,eGam); /*h_Brain*/ RM_fn_vInitAddInfo(); fn_vBrainAlloc(p_stTempObject); RM_fn_vAddInfo(eMS4ABrain,eSubAlwaysGam,eGam); #else fn_vStdGameAlloc (p_stTempObject); fn_v3dDataAlloc (p_stTempObject); fn_vBrainAlloc (p_stTempObject); #endif /* END ANNECY AV }*/ M_ObjectSetFamilyType(p_stTempObject,otObjectFamilyType); #ifndef U64 M_ObjectSetModelType(p_stTempObject,otObjectModelType); #endif M_ObjectSetPersonalType(p_stTempObject,otObjectPersonalType); /* ANNECY AV {*/ /* if (otObjectFamilyType!=C_InvalidObjectType) fn_v3dDataSetFamily(p_stTempObject->h_3dData,fn_hFindOrAddFAmily(otObjectFamilyType)); */ /* END ANNECY AV }*/ return(p_stTempObject); } /*----------------------------------------------------------------------------- * Description : Initialize the always structure (when the map is loaded) *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 08/10/96 Author : Francois *---------------------------------------------------------------------------*/ void fn_vFirstInitAlwaysStructure() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ tdstEngineObject *p_stTempEngineObject; unsigned long i; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #ifdef D_WANT_OPTIMIZE_MEMORY g_lNbAllocatedAlways=0; g_lMaxNbAllocatedAlways=0; g_lAllowedNbAllocatedAlways=g_stAlways.ulMaxNumberOfAlways; #endif /* D_WANT_OPTIMIZE_MEMORY */ /**** We allocate all structures used by a engine super-object ****/ if (g_stAlways.ulMaxNumberOfAlways) { #ifdef U64 RM_fn_vInitAddInfo(); #endif /* U64 */ g_stAlways.d_stAlwaysSuperObject = HIE_fn_p_stCreateSuperObjectTab(g_stAlways.ulMaxNumberOfAlways); MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeEngineObject , 0 ); #ifdef U64 RM_fn_vAddInfo(e4ASuperObject,eSubAlwaysGeo,eGeo); RM_fn_vInitAddInfo(); #endif /* U64 */ g_stAlways.d_stAlwaysEngineObjectInit = (struct tdstEngineObject_*)M_p_GameMallocInHLM(g_stAlways.ulMaxNumberOfAlways*sizeof(struct tdstEngineObject_)); MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeAlwaysGenerator , 0 ); #ifdef U64 RM_fn_vAddInfo(e4AEngineObject,eSubAlwaysGam,eGam); RM_fn_vInitAddInfo(); #endif /* U64 */ g_stAlways.d_hAlwaysGenerator = (HIE_tdxHandleToSuperObject *)M_p_GameMallocInHLM(g_stAlways.ulMaxNumberOfAlways * sizeof(HIE_tdxHandleToSuperObject) ); #if defined(ACTIVE_EDITOR) g_stAlways.d_bIsReferencedInLevel = (ACP_tdxBool *)M_p_GameMallocInHLM(g_stAlways.ulMaxNumberOfAlways * sizeof(ACP_tdxBool) ); #endif /* ACTIVE_EDITOR */ #ifdef U64 RM_fn_vAddInfo(e4AGenerator,eSubAlwaysGam,eGam); #endif /* U64 */ /* ANNECY AV DEMO {*/ #ifndef U64 DEMO_fn_vStartOfAlwaysCreation (); /* For the DEMO module to know the number of the first created always*/ #endif /* END ANNECY AV }*/ for (i=0;ih_3dData)); M_SetSuperObject(p_stTempEngineObject,HIE_fn_hGetElementFromSuperObjectTab(g_stAlways.d_stAlwaysSuperObject,i)); /* ANNECY AV {*/ /* This is already done in the fn_p_stAllocatedAlwaysEngineObject function // *** Allocate all object's structures *** - Oliv' - Portage v15 - 1 warning removed here M_ForAllMiniStructureNULL(p_stTempEngineObject,j) { g_a_stStructureHandleFunction[j].p_fn_vAllocFunction(p_stTempEngineObject); } */ /* END ANNECY AV }*/ memcpy(&(g_stAlways.d_stAlwaysEngineObjectInit[i]),p_stTempEngineObject,sizeof(struct tdstEngineObject_)); memset(p_stTempEngineObject,0,sizeof(struct tdstEngineObject_)); } } } /*----------------------------------------------------------------------------- * Description : Desinitialize the always structure (when the map is finish) *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 08/10/96 Author : Francois *---------------------------------------------------------------------------*/ void fn_vLastDesinitAlwaysStructure() { /**** Start by kill all active always in the map ****/ fn_vKillAllAlways(); if (g_stAlways.ulMaxNumberOfAlways) { g_stAlways.d_stAlwaysEngineObjectInit = NULL; g_stAlways.d_stAlwaysSuperObject = NULL; g_stAlways.d_hAlwaysGenerator = NULL; #if defined(ACTIVE_EDITOR) g_stAlways.d_bIsReferencedInLevel = NULL; #endif /* ACTIVE_EDITOR */ } } /*----------------------------------------------------------------------------- * Description : Add a always model to the chain list *----------------------------------------------------------------------------- * Input : engine object's pointer * Output : void *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *---------------------------------------------------------------------------*/ void fn_vAddAnAlwaysModel(struct tdstEngineObject_ *p_stAlwaysObject) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* Oliv' - Portage v15*/ #ifndef U64 long i; ALW_tdxHandleToModelList h_AlwaysModelChild; #endif /* EndOfOliv'*/ ALW_tdxHandleToModelList h_NewAlwaysModel; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #ifndef U64 LST2_M_DynamicForEachElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,i) { if (h_AlwaysModelChild->otObjectModelType==M_ObjectGetModelType(p_stAlwaysObject)) { M_GameWarningError(E_uwGameAddAnAlwaysModelAlreadyExist); p_stAlwaysObject = fn_p_stFreeEngineObject(p_stAlwaysObject); Erm_M_ClearLastError(C_ucErmDefaultChannel); } } #endif if (p_stAlwaysObject!=NULL) { MMG_fn_vAddMemoryInfo( MMG_C_lTypeGAM , MMG_C_lSubTypeAlwaysModel , 0 ); h_NewAlwaysModel = (struct tdstAlwaysModelList_ *)M_p_GameMallocInHLM(sizeof(struct tdstAlwaysModelList_)); h_NewAlwaysModel->p_stAlwaysObject = p_stAlwaysObject; #ifdef U64 h_NewAlwaysModel->otObjectModelType = M_ObjectGetPersonalType(p_stAlwaysObject); #else h_NewAlwaysModel->otObjectModelType = M_ObjectGetModelType(p_stAlwaysObject); #endif LST2_M_DynamicAddTail(&(g_stAlways.ALW_h_LstAlwaysModel),h_NewAlwaysModel); /* Oliv' - Portage v15*/ if( p_stAlwaysObject->h_StandardGame ) fn_vStandardGameSetAlways( p_stAlwaysObject->h_StandardGame, TRUE ); /* Gus: Le flag Always dans la dynam sert uniquement a savoir ou elle est allouee. IL NE FAUT PAS LE CHANGER !!!!! if( p_stAlwaysObject->h_Dynam ) { DNM_tdstDynamics* p_stDynamic; if( (p_stDynamic = fn_p_stDynamGetDynamics(p_stAlwaysObject->h_Dynam)) != NULL ) DNM_M_vDynamicsSetAlways ( p_stDynamic, TRUE ); } */ /* EndOfOliv'*/ } } /*----------------------------------------------------------------------------- * Description : Destroy all always model chain list *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *---------------------------------------------------------------------------*/ void fn_vKillAllAlwaysModel() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ long i; ALW_tdxHandleToModelList h_AlwaysModelChild,h_AlwaysModelNextChild; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LST2_M_DynamicForEachMovingElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,h_AlwaysModelNextChild,i) { /* if the always model is in fix, then desinit it*/ /* else, destroy it !*/ if ( fn_bIsInFix(h_AlwaysModelChild->p_stAlwaysObject) ) { /* desinit*/ fn_vDesinitOneObject(h_AlwaysModelChild->p_stAlwaysObject,OTI_MapLoaded); } else { LST2_M_DynamicIsolate(h_AlwaysModelChild); /* Oliv - 14/10/1998 - Cannot free Gam Level Memory*/ #if !defined(U64) h_AlwaysModelChild->p_stAlwaysObject = fn_p_stFreeEngineObject(h_AlwaysModelChild->p_stAlwaysObject); #else h_AlwaysModelChild->p_stAlwaysObject = NULL; #endif /* EndOfOliv'*/ } /*h_AlwaysModelChild->p_stAlwaysObject=fn_p_stFreeEngineObject(h_AlwaysModelChild->p_stAlwaysObject);*/ /*M_GameFreeInHLM(h_AlwaysModelChild);*/ } } /*----------------------------------------------------------------------------- * Description : init all always model chain list *----------------------------------------------------------------------------- * Input : type of initialisation * Output : none *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *---------------------------------------------------------------------------*/ void fn_vInitAlwaysModel(enum tdeObjectTreeInit_ eObjIniType) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; ALW_tdxHandleToModelList h_AlwaysModelChild; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LST2_M_DynamicForEachElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,i) { fn_vInitOneObject(h_AlwaysModelChild->p_stAlwaysObject,eObjIniType); } } /*----------------------------------------------------------------------------- * Description : Allocate a always by a type *----------------------------------------------------------------------------- * Input : Type of always, father in hierarchy * Output : Engine super object structure (NULL if error) *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *---------------------------------------------------------------------------*/ unsigned char fn_ucIsAnAlwaysObject(struct tdstEngineObject_ *p_stEngineObject) { /* ANNECY MT - 12/10/98 {*/ return (fn_bStandardGameIsAlways (p_stEngineObject -> h_StandardGame)); /* END ANNECY MT }*/ } /*----------------------------------------------------------------------------- * Description : *----------------------------------------------------------------------------- * Input : * Output : *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *---------------------------------------------------------------------------*/ unsigned char fn_ucIsAnAlwaysModel(struct tdstEngineObject_ *p_stEngineObject) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; ALW_tdxHandleToModelList h_AlwaysModelChild; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (M_ObjectGetPersonalType(p_stEngineObject) >= C_AlwaysObjectType) return TRUE; LST2_M_DynamicForEachElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,i) { if (M_ObjectGetPersonalType(p_stEngineObject)==M_ObjectGetPersonalType(h_AlwaysModelChild->p_stAlwaysObject)) return TRUE; } return( FALSE ); } /*----------------------------------------------------------------------------- * Description : Allocate a always by a type *----------------------------------------------------------------------------- * Input : Type of always, father in hierarchy * Output : Engine super object structure (NULL if error) *----------------------------------------------------------------------------- * Creation date : 11/10/96 Author : Francois *----------------------------------------------------------------------------- * Modification : 18/09/98 Author : Marc *---------------------------------------------------------------------------*/ HIE_tdxHandleToSuperObject fn_p_stAllocateAlways ( tdObjectType otObjectModelType, HIE_tdxHandleToSuperObject p_stFatherSuperObject, HIE_tdxHandleToSuperObject _hGenerator, unsigned short uwAction, POS_tdstCompletePosition *p_stMatrix ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ HIE_tdxHandleToSuperObject h_stSuperObject=NULL; HIE_tdxHandleToSuperObject h_SOSector; unsigned long i,j; ALW_tdxHandleToModelList h_AlwaysModelChild; struct tdstEngineObject_ *p_stEngineObject=NULL; MTH3D_tdstVector *p_stTempVector=NULL; #ifdef __DEBUG_AI__ AI_tdstMind *p_stMind; #endif /* __DEBUG_AI__*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LST2_M_DynamicForEachElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,i) { /* * Search for the model */ if (h_AlwaysModelChild->otObjectModelType == otObjectModelType) { /* * search for a free case in always array */ h_stSuperObject = g_stAlways.d_stAlwaysSuperObject; for ( i = 0; ( i < g_stAlways.ulMaxNumberOfAlways ) && ( g_stAlways.d_hAlwaysGenerator[i] != NULL || HIE_M_hNextChild(h_stSuperObject) != NULL ); i ++ , h_stSuperObject ++ ); /* * none found : return NULL */ if (i >= g_stAlways.ulMaxNumberOfAlways) { #ifdef U64 M_PrintfWarningN64(("\n\nCan't create an always")); #endif /* U64 */ return NULL; } #ifdef D_WANT_OPTIMIZE_MEMORY g_lNbAllocatedAlways++; if(g_lMaxNbAllocatedAlwaysp_stAlwaysObject,j) { /* ANNECY AV {*/ /* Now, we allocate the mini-structure only when necessary*/ if (M_VoidMiniStructurePointer (& g_stAlways.d_stAlwaysEngineObjectInit [i] , j) == NULL) g_a_stStructureHandleFunction [j] . p_fn_vAllocFunction (& g_stAlways . d_stAlwaysEngineObjectInit [i]); /* END ANNECY AV }*/ M_CopyMSPointer(p_stEngineObject,&(g_stAlways.d_stAlwaysEngineObjectInit[i]),j); g_a_stStructureHandleFunction[j].p_fn_vCopyCloneMSFunction( p_stEngineObject,h_AlwaysModelChild->p_stAlwaysObject ); } M_ObjectSetPersonalType(p_stEngineObject,C_AlwaysObjectType+i); M_SetSuperObject(p_stEngineObject,h_stSuperObject); /* * Setting an initial state */ if( p_stEngineObject->h_3dData ) { fn_v3dDataSetMatrix(p_stEngineObject->h_3dData,p_stMatrix); } /* ANNECY AV DEMO {*/ #ifndef U64 #ifndef RETAIL DEMO_fn_vSaveAlwaysActivationDesactivation (h_stSuperObject,p_stTempVector,TRUE); #endif /* RETAIL */ #endif /* END ANNECY AV }*/ /* * Update GlobalMatrix */ POS_fn_vMulMatrixMatrix( HIE_fn_hGetSuperObjectGlobalMatrix(h_stSuperObject) , HIE_fn_hGetSuperObjectGlobalMatrix(p_stFatherSuperObject) , HIE_fn_hGetSuperObjectMatrix(h_stSuperObject) ); HIE_fn_vValidateGlobalMatrix(h_stSuperObject); /* ANNECY MT - 18/09/98 {*/ /* * Testing if always is generated in a good sector */ p_stTempVector = POS_fn_p_stGetTranslationVector (HIE_fn_hGetSuperObjectGlobalMatrix(h_stSuperObject)); h_SOSector = GAM_fn_hGetCurrentSector( _hGenerator ); if( ! SECT_fn_bIsInBorderBox( p_stTempVector, (SECT_tdxHandleOfSectorObject)HIE_fn_hGetSuperObjectObject(h_SOSector) ) ) { h_SOSector=SECT_fn_hResearchInWhatSectorIAm(SECT_hFatherSector,p_stTempVector); } if( !h_SOSector ) { g_stAlways.d_hAlwaysGenerator[ i ] = NULL; return NULL; } fn_vSectInfoSetCurrentSector(p_stEngineObject->h_SectInfo,h_SOSector); M_ForAllMiniStructureExceptNULL(p_stEngineObject,j) { g_a_stStructureHandleFunction[j].p_fn_vInitFunction(p_stEngineObject,OTI_AlwaysCreated); } /* * Add In Hierarchy */ if ( fn_ucStandardGameGetPlatFormType(M_GetMSHandle(h_stSuperObject,StandardGame)) ) { HIE_fn_vSuperObjectAddHead(p_stFatherSuperObject, h_stSuperObject); } else { HIE_fn_vSuperObjectAddTail(p_stFatherSuperObject, h_stSuperObject); } fn_vStandardGameSetIsActivable(p_stEngineObject->h_StandardGame,1); /* * Update Misc Flag */ /* ANNECY MT - 12/10/98 {*/ /* Oliv' - Portage v15 - THIS IS TOO LATE HERE. See AddAnAlwaysModel - so it's unnecessary now here*/ /* fn_vStandardGameSetAlways(p_stEngineObject->h_StandardGame,TRUE);*/ /* EndOfOliv'*/ /* END ANNECY MT }*/ /* * Update Bounding Volumes for always */ h_stSuperObject->hBoundingVolume = fn_vGetBoundingVolumeOfFamily(fn_h3dDataGetFamily(p_stEngineObject->h_3dData)); /* * Give name to always */ #ifdef __DEBUG_AI__ if (M_GetMSHandle(h_stSuperObject,Brain)) { p_stMind = AI_M_stGetMindOfSuperObj(h_stSuperObject); AI_M_SetPersoName (p_stMind, fn_szFindPersonalTypeNameOfPersonalType(M_ObjectGetPersonalType(h_AlwaysModelChild->p_stAlwaysObject))); } #endif /* __DEBUG_AI__*/ /* * Active the object' : now it's useless to call the 'fn_vForceActiveAnObject' function after this */ M_ActivateObject(p_stEngineObject); { fn_v3dDataSetStartTime(p_stEngineObject->h_3dData,g_stEngineStructure.stEngineTimer.ulCurrentTimerCount); fn_v3dDataSetTimePreviousFrame(p_stEngineObject->h_3dData,g_stEngineStructure.stEngineTimer.ulCurrentTimerCount); } /* reactive an object, so create its element3d array if necessary*/ if (fn_p_st3dDataGetCurrentFrame(p_stEngineObject->h_3dData)->p_stArrayOfElts3d == NULL) { tdstAnim3d * p_stCurrentAnim; tdxHandleToState hState; ENGassert(fn_h3dDataGetCurrentState(p_stEngineObject->h_3dData) != NULL); if (fn_h3dDataGetCurrentState(p_stEngineObject->h_3dData)) { hState = fn_h3dDataGetCurrentState(p_stEngineObject->h_3dData); p_stCurrentAnim = fn_p_stGetAnimInState(hState); if (p_stCurrentAnim) { /* ANNECY MT - 22/09/98 {*/ fn_vAllocArrayOfElts3d (p_stEngineObject -> h_3dData , p_stCurrentAnim -> ucMaxNumberOfElements); /*MMG_fn_vAddMemoryInfo( MMG_C_lTypeFamily , MMG_C_lSubTypeAnimation , p_stEngineObject->h_3dData->h_Family);*/ /*fn_p_st3dDataGetCurrentFrame(p_stEngineObject->h_3dData)->p_stArrayOfElts3d = (tdstElement3d*)TMP_M_p_Malloc(sizeof(tdstElement3d) * p_stCurrentAnim->ucMaxNumberOfElements);*/ fn_p_st3dDataGetCurrentFrame(p_stEngineObject->h_3dData)->p_stAnim = NULL; /*memset(fn_p_st3dDataGetCurrentFrame(p_stEngineObject->h_3dData)->p_stArrayOfElts3d,0,sizeof(tdstElement3d) * p_stCurrentAnim->ucMaxNumberOfElements);*/ /* END ANNECY MT }*/ } } /* reinit anim reference to force interpolation to re-create frame*/ fn_p_st3dDataGetCurrentFrame(p_stEngineObject->h_3dData)->p_stAnim = NULL; } /* END ANNECY MT }*/ #ifdef GAM_USE_SNA SNA_M_vUpdateOccurrenceToLoad(); #endif /* GAM_USE_SNA */ return(h_stSuperObject); } } M_GameWarningError(E_uwGameAllocateAlwaysUnknownModel); Erm_M_ClearLastError(C_ucErmDefaultChannel); return(NULL); } /*----------------------------------------------------------------------------- * Description : Destroy an allocated always *----------------------------------------------------------------------------- * Input : Rank in dynamic array * Output : void *----------------------------------------------------------------------------- * Creation date : 08/10/96 Author : Francois *----------------------------------------------------------------------------- * Modification date : 16/08/97 Modification Author : Gizmo * Modifications : *---------------------------------------------------------------------------*/ void fn_vKillAlwaysByPersonalType(tdObjectType otPersonalType) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ HIE_tdxHandleToSuperObject h_SuperObject; HIE_tdxHandleToSuperObject h_Child,h_NextChild; tdstEngineObject *p_stEngineObject; unsigned long ulRank; unsigned long i; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #ifdef D_WANT_OPTIMIZE_MEMORY g_lNbAllocatedAlways--; #endif /* D_WANT_OPTIMIZE_MEMORY */ ulRank = otPersonalType - C_AlwaysObjectType; SAF_M_AssertWithMsg ( ulRank >= 0 && ulRank < g_stAlways.ulMaxNumberOfAlways , "l'objet detruit n'est pas un always mais est considéré comme tel!" ) ; h_SuperObject = HIE_fn_hGetElementFromSuperObjectTab(g_stAlways.d_stAlwaysSuperObject,ulRank); /* If this always a text, clear all datas of this text for TEXT_Affiche function*/ TFMT_ucClearNumberOfCurrentTextAffiche(h_SuperObject); /* stop sounf for that always*/ SND_fn_vKillObjectSound2((long)h_SuperObject,g_lSoundObjectTypeAnim); /* ANNECY AV DEMO {*/ #ifndef U64 #ifndef RETAIL DEMO_fn_vSaveAlwaysActivationDesactivation(h_SuperObject,NULL,FALSE); /*save Kill of always*/ #endif /* RETAIL */ #endif /* END ANNECY AV }*/ /* fn_vRemoveAllAnimLightsFromSectorList(h_SuperObject);*/ /*XB980824*/ #ifndef D_THROW_MGT if( M_GetMSHandle( h_SuperObject, MSMagnet) ) MGT_fn_vDeleteObjectFromMagnetList(h_SuperObject); #endif /* D_THROW_MGT */ /*End XB*/ p_stEngineObject = (tdstEngineObject *)HIE_fn_hGetSuperObjectObject(h_SuperObject); #ifndef U64 if (M_ObjectGetModelType(p_stEngineObject)==C_InvalidObjectType) M_GameInformationError(E_uwGameKillAlwaysByRankInvalidObject); #endif /* * reset generator */ g_stAlways.d_hAlwaysGenerator[ ulRank ] = NULL; /* * Free the always object place */ fn_vRemoveObjectInSectorList(h_SuperObject); M_ObjectSetFamilyType(p_stEngineObject,C_InvalidObjectType); #ifndef U64 M_ObjectSetModelType(p_stEngineObject,C_InvalidObjectType); #endif M_ObjectSetPersonalType(p_stEngineObject,C_AlwaysObjectType); /* * Extract the super-object from the hiérarchie and reput these engine children at the world hierarchie's level */ /* destroy all active channels and SO*/ PLA_fn_vDesInitAllChildOfCharacter(h_SuperObject,(struct tdstEngineObject_*)HIE_fn_hGetSuperObjectObject(h_SuperObject)); fn_vFreeMorphList(&(p_stEngineObject->h_3dData->hMorphChannelList)); /* Anti-bug: Free dynamics*/ if( p_stEngineObject->h_Dynam ) fn_v_DynamicFree( p_stEngineObject->h_Dynam ); /* isolate the always*/ HIE_fn_vPseudoIsolate(h_SuperObject); /* if it is a platform, put all its eventual sons as child of the world*/ if (fn_ucStandardGameGetPlatFormType(M_GetMSHandle(h_SuperObject,StandardGame))) { HIE_M_ForEachMovingChildOf(h_SuperObject,h_Child,h_NextChild,i) { ENGassert(HIE_fn_ulGetSuperObjectType(h_Child) == HIE_C_ulActor); if (HIE_fn_ulGetSuperObjectType(h_Child)==HIE_C_ulActor) fn_vReputCharacterSuperObjectAtTheWorld(h_Child); } } if (HIE_fn_SO_bIsSuperimposed (h_SuperObject)) { HIE_fn_SO_vClearSuperimposedFlag (h_SuperObject); } memset(p_stEngineObject,0,sizeof(struct tdstEngineObject_)); } /*----------------------------------------------------------------------------- * Description : Destroy all allocated always *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 08/10/96 Author : Francois *----------------------------------------------------------------------------- * Modification date : Modification Author : * Modifications : *---------------------------------------------------------------------------*/ void fn_vKillAllAlways() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; tdstEngineObject *p_stEngineObject; HIE_tdxHandleToSuperObject hSO; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ for (i=0;ih_StandardGame!=NULL) fn_vKillAlwaysByPersonalType(M_ObjectGetPersonalType(p_stEngineObject)); } } /*----------------------------------------------------------------------------- * Description : return the number of free always *----------------------------------------------------------------------------- * Input : void * Output : long *----------------------------------------------------------------------------- * Creation date : 28/01/98 Author : Francois *----------------------------------------------------------------------------- * Modification date : Modification Author : * Modifications : *---------------------------------------------------------------------------*/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ unsigned long fn_ulGetNumberOfFreeAlways(void) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; unsigned long ulReturn = 0; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ for (i=0;ih_3dData==NULL) ulReturn++; } return(ulReturn); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /*----------------------------------------------------------------------------- * Description : return the number of live always that belong to a given actor *----------------------------------------------------------------------------- * Input : actor superobject * Output : long *----------------------------------------------------------------------------- * Creation date : 27/07/98 Author : Benoit Germain *----------------------------------------------------------------------------- * Modification date : Modification Author : * Modifications : *---------------------------------------------------------------------------*/ unsigned long fn_ulGetNumberOfAlwaysBelongingToMe(HIE_tdxHandleToSuperObject _hGenerator) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; unsigned long ulReturn = 0; tdstEngineObject *hAlwaysObject; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ for (i = 0 ; i < g_stAlways.ulMaxNumberOfAlways ; i ++) { hAlwaysObject = HIE_fn_hGetSuperObjectObject(HIE_fn_hGetElementFromSuperObjectTab(g_stAlways.d_stAlwaysSuperObject,i)); if ( (hAlwaysObject != NULL) && (hAlwaysObject->h_3dData != NULL) && (g_stAlways.d_hAlwaysGenerator[i] == _hGenerator) ) { ulReturn ++; } } return ulReturn; } /*----------------------------------------------------------------------------- * Description : Allocate maximum size for Brain MiniStructure *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 07/07/97 Author : Olivier Jourdan *----------------------------------------------------------------------------- * Modification date : Modification Author : * Modifications : *---------------------------------------------------------------------------*/ void fn_vInitMindForAlways() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned long i; unsigned long ulSizeMax=0; unsigned long ulTmpSize; AI_tdxHandleToMind hMind; ALW_tdxHandleToModelList h_AlwaysModelChild; tdstEngineObject *p_stTempEngineObject; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ LST2_M_DynamicForEachElementOf(&(g_stAlways.ALW_h_LstAlwaysModel),h_AlwaysModelChild,i) { p_stTempEngineObject = h_AlwaysModelChild->p_stAlwaysObject; if( p_stTempEngineObject->h_Brain ) { hMind = M_pstGetMindOfBrain(p_stTempEngineObject->h_Brain); if( hMind ) { ulTmpSize = fn_ulGetSizeOfMindWithoutAIModel( hMind ); if( ulTmpSize > ulSizeMax ) ulSizeMax = ulTmpSize; } } } if ( ulSizeMax ) /*allocate a mind only if needed!!!*/ { for (i = 0; i < g_stAlways.ulMaxNumberOfAlways; i ++ ) { p_stTempEngineObject=&g_stAlways.d_stAlwaysEngineObjectInit[i]; if( p_stTempEngineObject->h_Brain ) { MMG_fn_vAddMemoryInfo( MMG_C_lTypeAI , MMG_C_lSubTypeMind , NULL ); hMind = (AI_tdxHandleToMind)M_p_GameMallocInHLM(ulSizeMax); memset(hMind,i+1,ulSizeMax); M_SetMindOfBrain(p_stTempEngineObject->h_Brain,hMind); } } } } /*----------------------------------------------------------------------------- * Description : Kill all desactivate always *----------------------------------------------------------------------------- * Input : void * Output : void *----------------------------------------------------------------------------- * Creation date : 07/07/97 Author : Olivier Jourdan *----------------------------------------------------------------------------- * Modification date : Modification Author : * Modifications : *---------------------------------------------------------------------------*/ void fn_vKillAllAlwaysInNonActiveSectors() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ tdstEngineObject *p_stAlwaysEngObj; HIE_tdxHandleToSuperObject *p_hGenerator; HIE_tdxHandleToSuperObject *p_hLastGenerator; HIE_tdxHandleToSuperObject hAlwaysSuperObject; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* * Init and do a loop on all always */ hAlwaysSuperObject = g_stAlways.d_stAlwaysSuperObject; p_hGenerator = g_stAlways.d_hAlwaysGenerator; p_hLastGenerator = p_hGenerator + g_stAlways.ulMaxNumberOfAlways; for( ; p_hGenerator < p_hLastGenerator; hAlwaysSuperObject++, p_hGenerator++ ) { /* * Get the always engine object */ p_stAlwaysEngObj = (tdstEngineObject *) HIE_fn_hGetSuperObjectObject( hAlwaysSuperObject ); /* * Test if always is actually used * always is not more used if it is activable and not more active or * if it depends on it's generator and this one is desactivate. */ if( ( p_stAlwaysEngObj->h_StandardGame ) && ( /*(M_ObjectIsActivable(p_stAlwaysEngObj) && !M_ObjectIsActive(p_stAlwaysEngObj)) ||*/ ( (fn_eStandardGameGetInitFlagWhenOutOfZone( p_stAlwaysEngObj->h_StandardGame ) == OI_WhenGeneratorIsDesactivated) && !M_ObjectIsActive( (tdstEngineObject *) HIE_fn_hGetSuperObjectObject( *p_hGenerator ) ) ) || ( (fn_ulStandardGameGetCustomBits( p_stAlwaysEngObj->h_StandardGame ) & GAM_C_CustBitDestroyWhenAnimEnded) && PLA_fn_bTestIfEndOfAction( hAlwaysSuperObject ) ) ) ) { /* Object is not in a active sector*/ fn_vKillEngineObjectOrAlwaysByPointer(p_stAlwaysEngObj); } if (*p_hGenerator == NULL) { HIE_M_hNextChild(hAlwaysSuperObject) = NULL; } } } /*----------------------------------------------------------------------------- * Description : Say if an always is generated by an object *----------------------------------------------------------------------------- * Input : always and generator * Output : 0 if False, 1 otherwise *----------------------------------------------------------------------------- * Creation date : 29/05/98 Author : Vincent Lhullier *---------------------------------------------------------------------------*/ unsigned char fn_ucIsAlwaysGeneratedByMe( HIE_tdxHandleToSuperObject _hAlways, HIE_tdxHandleToSuperObject _hGenerator ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ tdstEngineObject *p_stEngineObject; unsigned long ulRank; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if ( (_hGenerator == NULL) || (_hAlways == NULL) || (M_GetMSHandle( _hAlways, StandardGame) == NULL) || (( p_stEngineObject = (tdstEngineObject *)HIE_fn_hGetSuperObjectObject( _hAlways ) ) == NULL) ) return 0; ulRank = M_ObjectGetPersonalType(p_stEngineObject) - C_AlwaysObjectType; SAF_M_AssertWithMsg ( ulRank >= 0 && ulRank < g_stAlways.ulMaxNumberOfAlways , "the tested object is not an always!" ) ; return (unsigned char) ( g_stAlways.d_hAlwaysGenerator[ ulRank ] == _hGenerator ); } #ifndef U64 /*----------------------------------------------------------------------------- * Description : *----------------------------------------------------------------------------- * Input : * Output : *----------------------------------------------------------------------------- * Creation date : 30/04/99 Author : Marc TRABUCATO *---------------------------------------------------------------------------*/ void fn_vClearUnusedAlwaysInDemoMode() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ tdstEngineObject *p_stAlwaysEngObj; HIE_tdxHandleToSuperObject *p_hGenerator; HIE_tdxHandleToSuperObject *p_hLastGenerator; HIE_tdxHandleToSuperObject hAlwaysSuperObject; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* * Init and do a loop on all always */ hAlwaysSuperObject = g_stAlways.d_stAlwaysSuperObject; p_hGenerator = g_stAlways.d_hAlwaysGenerator; p_hLastGenerator = p_hGenerator + g_stAlways.ulMaxNumberOfAlways; for( ; p_hGenerator < p_hLastGenerator; hAlwaysSuperObject++, p_hGenerator++ ) { /* * Get the always engine object */ p_stAlwaysEngObj = (tdstEngineObject *) HIE_fn_hGetSuperObjectObject( hAlwaysSuperObject ); if (*p_hGenerator == NULL) { HIE_M_hNextChild(hAlwaysSuperObject) = NULL; } } } #endif