Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

be_aas_main.c File Reference

#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_libvar.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_log.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "be_aas_def.h"

Include dependency graph for be_aas_main.c:

Include dependency graph

Go to the source code of this file.

Functions

void AAS_ContinueInit (float time)
void QDECL AAS_Error (char *fmt,...)
int AAS_IndexFromModel (char *modelname)
int AAS_IndexFromString (char *indexname, char *stringindex[], int numindexes, char *string)
int AAS_Initialized (void)
int AAS_Loaded (void)
int AAS_LoadFiles (const char *mapname)
int AAS_LoadMap (const char *mapname)
char * AAS_ModelFromIndex (int index)
void AAS_ProjectPointOntoVector (vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj)
void AAS_SetInitialized (void)
int AAS_Setup (void)
void AAS_Shutdown (void)
int AAS_StartFrame (float time)
char * AAS_StringFromIndex (char *indexname, char *stringindex[], int numindexes, int index)
float AAS_Time (void)
void AAS_UpdateStringIndexes (int numconfigstrings, char *configstrings[])

Variables

aas_t aasworld
libvar_tsaveroutingcache


Function Documentation

void AAS_ContinueInit float  time  ) 
 

Definition at line 200 of file be_aas_main.c.

References AAS_ContinueInitReachability(), AAS_InitClustering(), AAS_InitRouting(), AAS_Optimize(), AAS_SetInitialized(), AAS_WriteAASFile(), aasworld, botimport, aas_s::filename, aas_s::initialized, LibVarGetValue(), LibVarValue(), aas_s::loaded, PRT_ERROR, PRT_MESSAGE, aas_s::savefile, and time().

Referenced by AAS_StartFrame().

00201 {
00202     //if no AAS file loaded
00203     if (!aasworld.loaded) return;
00204     //if AAS is already initialized
00205     if (aasworld.initialized) return;
00206     //calculate reachability, if not finished return
00207     if (AAS_ContinueInitReachability(time)) return;
00208     //initialize clustering for the new map
00209     AAS_InitClustering();
00210     //if reachability has been calculated and an AAS file should be written
00211     //or there is a forced data optimization
00212     if (aasworld.savefile || ((int)LibVarGetValue("forcewrite")))
00213     {
00214         //optimize the AAS data
00215         if ((int)LibVarValue("aasoptimize", "0")) AAS_Optimize();
00216         //save the AAS file
00217         if (AAS_WriteAASFile(aasworld.filename))
00218         {
00219             botimport.Print(PRT_MESSAGE, "%s written succesfully\n", aasworld.filename);
00220         } //end if
00221         else
00222         {
00223             botimport.Print(PRT_ERROR, "couldn't write %s\n", aasworld.filename);
00224         } //end else
00225     } //end if
00226     //initialize the routing
00227     AAS_InitRouting();
00228     //at this point AAS is initialized
00229     AAS_SetInitialized();
00230 } //end of the function AAS_ContinueInit

Here is the call graph for this function:

void QDECL AAS_Error char *  fmt,
  ...
 

Definition at line 57 of file be_aas_main.c.

References botimport, PRT_FATAL, QDECL, va_end, va_list, va_start, and vsprintf().

00058 {
00059     char str[1024];
00060     va_list arglist;
00061 
00062     va_start(arglist, fmt);
00063     vsprintf(str, fmt, arglist);
00064     va_end(arglist);
00065     botimport.Print(PRT_FATAL, str);
00066 } //end of the function AAS_Error

Here is the call graph for this function:

int AAS_IndexFromModel char *  modelname  ) 
 

Definition at line 132 of file be_aas_main.c.

References AAS_IndexFromString(), aasworld, aas_s::configstrings, CS_MODELS, and MAX_MODELS.

00133 {
00134     return AAS_IndexFromString("IndexFromModel", &aasworld.configstrings[CS_MODELS], MAX_MODELS, modelname);
00135 } //end of the function AAS_IndexFromModel

Here is the call graph for this function:

int AAS_IndexFromString char *  indexname,
char *  stringindex[],
int  numindexes,
char *  string
 

Definition at line 101 of file be_aas_main.c.

References aasworld, botimport, i, aas_s::indexessetup, PRT_ERROR, Q_stricmp(), and string().

Referenced by AAS_IndexFromModel().

00102 {
00103     int i;
00104     if (!aasworld.indexessetup)
00105     {
00106         botimport.Print(PRT_ERROR, "%s: index not setup \"%s\"\n", indexname, string);
00107         return 0;
00108     } //end if
00109     for (i = 0; i < numindexes; i++)
00110     {
00111         if (!stringindex[i]) continue;
00112         if (!Q_stricmp(stringindex[i], string)) return i;
00113     } //end for
00114     return 0;
00115 } //end of the function AAS_IndexFromString

Here is the call graph for this function:

int AAS_Initialized void   ) 
 

Definition at line 173 of file be_aas_main.c.

References aasworld, and aas_s::initialized.

00174 {
00175     return aasworld.initialized;
00176 } //end of the function AAS_Initialized

int AAS_Loaded void   ) 
 

Definition at line 163 of file be_aas_main.c.

References aasworld, and aas_s::loaded.

Referenced by BotInitLevelItems().

00164 {
00165     return aasworld.loaded;
00166 } //end of the function AAS_Loaded

int AAS_LoadFiles const char *  mapname  ) 
 

Definition at line 310 of file be_aas_main.c.

References AAS_LoadAASFile(), AAS_LoadBSPFile(), AAS_ResetEntityLinks(), aasworld, botimport, Com_sprintf(), aas_s::filename, aas_s::mapname, MAX_PATH, PRT_MESSAGE, strcpy(), and strncpy().

Referenced by AAS_LoadMap().

00311 {
00312     int errnum;
00313     char aasfile[MAX_PATH];
00314 //  char bspfile[MAX_PATH];
00315 
00316     strcpy(aasworld.mapname, mapname);
00317     //NOTE: first reset the entity links into the AAS areas and BSP leaves
00318     // the AAS link heap and BSP link heap are reset after respectively the
00319     // AAS file and BSP file are loaded
00320     AAS_ResetEntityLinks();
00321     // load bsp info
00322     AAS_LoadBSPFile();
00323 
00324     //load the aas file
00325     Com_sprintf(aasfile, MAX_PATH, "maps/%s.aas", mapname);
00326     errnum = AAS_LoadAASFile(aasfile);
00327     if (errnum != BLERR_NOERROR)
00328         return errnum;
00329 
00330     botimport.Print(PRT_MESSAGE, "loaded %s\n", aasfile);
00331     strncpy(aasworld.filename, aasfile, MAX_PATH);
00332     return BLERR_NOERROR;
00333 } //end of the function AAS_LoadFiles

Here is the call graph for this function:

int AAS_LoadMap const char *  mapname  ) 
 

Definition at line 341 of file be_aas_main.c.

References AAS_FreeRoutingCaches(), AAS_InitAASLinkedEntities(), AAS_InitAASLinkHeap(), AAS_InitAlternativeRouting(), AAS_InitReachability(), AAS_InitSettings(), AAS_LoadFiles(), aasworld, aas_s::initialized, and aas_s::loaded.

Referenced by Export_BotLibLoadMap().

00342 {
00343     int errnum;
00344 
00345     //if no mapname is provided then the string indexes are updated
00346     if (!mapname)
00347     {
00348         return 0;
00349     } //end if
00350     //
00351     aasworld.initialized = qfalse;
00352     //NOTE: free the routing caches before loading a new map because
00353     // to free the caches the old number of areas, number of clusters
00354     // and number of areas in a clusters must be available
00355     AAS_FreeRoutingCaches();
00356     //load the map
00357     errnum = AAS_LoadFiles(mapname);
00358     if (errnum != BLERR_NOERROR)
00359     {
00360         aasworld.loaded = qfalse;
00361         return errnum;
00362     } //end if
00363     //
00364     AAS_InitSettings();
00365     //initialize the AAS link heap for the new map
00366     AAS_InitAASLinkHeap();
00367     //initialize the AAS linked entities for the new map
00368     AAS_InitAASLinkedEntities();
00369     //initialize reachability for the new map
00370     AAS_InitReachability();
00371     //initialize the alternative routing
00372     AAS_InitAlternativeRouting();
00373     //everything went ok
00374     return 0;
00375 } //end of the function AAS_LoadMap

Here is the call graph for this function:

char* AAS_ModelFromIndex int  index  ) 
 

Definition at line 122 of file be_aas_main.c.

References AAS_StringFromIndex(), aasworld, aas_s::configstrings, CS_MODELS, and MAX_MODELS.

00123 {
00124     return AAS_StringFromIndex("ModelFromIndex", &aasworld.configstrings[CS_MODELS], MAX_MODELS, index);
00125 } //end of the function AAS_ModelFromIndex

Here is the call graph for this function:

void AAS_ProjectPointOntoVector vec3_t  point,
vec3_t  vStart,
vec3_t  vEnd,
vec3_t  vProj
 

Definition at line 294 of file be_aas_main.c.

References DotProduct, point, vec3_t, VectorMA, VectorNormalize(), and VectorSubtract.

Referenced by AAS_NearestHideArea(), DistanceFromLineSquared(), and DistancePointToLine().

00295 {
00296     vec3_t pVec, vec;
00297 
00298     VectorSubtract( point, vStart, pVec );
00299     VectorSubtract( vEnd, vStart, vec );
00300     VectorNormalize( vec );
00301     // project onto the directional vector for this segment
00302     VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
00303 } //end of the function AAS_ProjectPointOntoVector

Here is the call graph for this function:

void AAS_SetInitialized void   ) 
 

Definition at line 183 of file be_aas_main.c.

References aasworld, botimport, aas_s::initialized, and PRT_MESSAGE.

Referenced by AAS_ContinueInit().

00184 {
00185     aasworld.initialized = qtrue;
00186     botimport.Print(PRT_MESSAGE, "AAS initialized.\n");
00187 #ifdef DEBUG
00188     //create all the routing cache
00189     //AAS_CreateAllRoutingCache();
00190     //
00191     //AAS_RoutingInfo();
00192 #endif
00193 } //end of the function AAS_SetInitialized

int AAS_Setup void   ) 
 

Definition at line 383 of file be_aas_main.c.

References aas_entity_t, AAS_InvalidateEntities(), aasworld, aas_s::entities, FreeMemory(), GetClearedHunkMemory(), LibVar(), LibVarValue(), aas_s::maxclients, aas_s::maxentities, aas_s::numframes, and saveroutingcache.

Referenced by Export_BotLibSetup().

00384 {
00385     aasworld.maxclients = (int) LibVarValue("maxclients", "128");
00386     aasworld.maxentities = (int) LibVarValue("maxentities", "1024");
00387     // as soon as it's set to 1 the routing cache will be saved
00388     saveroutingcache = LibVar("saveroutingcache", "0");
00389     //allocate memory for the entities
00390     if (aasworld.entities) FreeMemory(aasworld.entities);
00391     aasworld.entities = (aas_entity_t *) GetClearedHunkMemory(aasworld.maxentities * sizeof(aas_entity_t));
00392     //invalidate all the entities
00393     AAS_InvalidateEntities();
00394     //force some recalculations
00395     //LibVarSet("forceclustering", "1");            //force clustering calculation
00396     //LibVarSet("forcereachability", "1");      //force reachability calculation
00397     aasworld.numframes = 0;
00398     return BLERR_NOERROR;
00399 } //end of the function AAS_Setup

Here is the call graph for this function:

void AAS_Shutdown void   ) 
 

Definition at line 406 of file be_aas_main.c.

References AAS_DumpAASData(), AAS_DumpBSPData(), AAS_FreeAASLinkedEntities(), AAS_FreeAASLinkHeap(), AAS_FreeRoutingCaches(), AAS_ShutdownAlternativeRouting(), aas_t, aasworld, botimport, Com_Memset(), aas_s::entities, FreeMemory(), aas_s::initialized, and PRT_MESSAGE.

Referenced by Export_BotLibShutdown().

00407 {
00408     AAS_ShutdownAlternativeRouting();
00409     //
00410     AAS_DumpBSPData();
00411     //free routing caches
00412     AAS_FreeRoutingCaches();
00413     //free aas link heap
00414     AAS_FreeAASLinkHeap();
00415     //free aas linked entities
00416     AAS_FreeAASLinkedEntities();
00417     //free the aas data
00418     AAS_DumpAASData();
00419     //free the entities
00420     if (aasworld.entities) FreeMemory(aasworld.entities);
00421     //clear the aasworld structure
00422     Com_Memset(&aasworld, 0, sizeof(aas_t));
00423     //aas has not been initialized
00424     aasworld.initialized = qfalse;
00425     //NOTE: as soon as a new .bsp file is loaded the .bsp file memory is
00426     // freed an reallocated, so there's no need to free that memory here
00427     //print shutdown
00428     botimport.Print(PRT_MESSAGE, "AAS shutdown.\n");
00429 } //end of the function AAS_Shutdown

Here is the call graph for this function:

int AAS_StartFrame float  time  ) 
 

Definition at line 238 of file be_aas_main.c.

References AAS_ContinueInit(), AAS_InvalidateEntities(), AAS_RoutingInfo(), AAS_UnlinkInvalidEntities(), AAS_WriteRouteCache(), aasworld, aas_s::frameroutingupdates, LibVarGetValue(), LibVarSet(), aas_s::numframes, PrintMemoryLabels(), PrintUsedMemorySize(), saveroutingcache, time(), aas_s::time, and libvar_s::value.

Referenced by Export_BotLibStartFrame().

00239 {
00240     aasworld.time = time;
00241     //unlink all entities that were not updated last frame
00242     AAS_UnlinkInvalidEntities();
00243     //invalidate the entities
00244     AAS_InvalidateEntities();
00245     //initialize AAS
00246     AAS_ContinueInit(time);
00247     //
00248     aasworld.frameroutingupdates = 0;
00249     //
00250     if (bot_developer)
00251     {
00252         if (LibVarGetValue("showcacheupdates"))
00253         {
00254             AAS_RoutingInfo();
00255             LibVarSet("showcacheupdates", "0");
00256         } //end if
00257         if (LibVarGetValue("showmemoryusage"))
00258         {
00259             PrintUsedMemorySize();
00260             LibVarSet("showmemoryusage", "0");
00261         } //end if
00262         if (LibVarGetValue("memorydump"))
00263         {
00264             PrintMemoryLabels();
00265             LibVarSet("memorydump", "0");
00266         } //end if
00267     } //end if
00268     //
00269     if (saveroutingcache->value)
00270     {
00271         AAS_WriteRouteCache();
00272         LibVarSet("saveroutingcache", "0");
00273     } //end if
00274     //
00275     aasworld.numframes++;
00276     return BLERR_NOERROR;
00277 } //end of the function AAS_StartFrame

Here is the call graph for this function:

char* AAS_StringFromIndex char *  indexname,
char *  stringindex[],
int  numindexes,
int  index
 

Definition at line 73 of file be_aas_main.c.

References aasworld, botimport, aas_s::indexessetup, and PRT_ERROR.

Referenced by AAS_ModelFromIndex().

00074 {
00075     if (!aasworld.indexessetup)
00076     {
00077         botimport.Print(PRT_ERROR, "%s: index %d not setup\n", indexname, index);
00078         return "";
00079     } //end if
00080     if (index < 0 || index >= numindexes)
00081     {
00082         botimport.Print(PRT_ERROR, "%s: index %d out of range\n", indexname, index);
00083         return "";
00084     } //end if
00085     if (!stringindex[index])
00086     {
00087         if (index)
00088         {
00089             botimport.Print(PRT_ERROR, "%s: reference to unused index %d\n", indexname, index);
00090         } //end if
00091         return "";
00092     } //end if
00093     return stringindex[index];
00094 } //end of the function AAS_StringFromIndex

float AAS_Time void   ) 
 

Definition at line 284 of file be_aas_main.c.

References aasworld, and aas_s::time.

Referenced by AAS_RoutingTime(), AAS_ShowReachableAreas(), AAS_UpdateEntity(), BotAddToAvoidGoals(), BotAddToAvoidReach(), BotAvoidGoalTime(), BotChooseInitialChatMessage(), BotDumpAvoidGoals(), BotGetReachabilityToGoal(), BotItemGoalInVisButNotVisible(), BotMoveToGoal(), BotQueueConsoleMessage(), BotRemoveFromAvoidGoals(), BotReplyChat(), BotTravel_Grapple(), and BotUpdateEntityItems().

00285 {
00286     return aasworld.time;
00287 } //end of the function AAS_Time

void AAS_UpdateStringIndexes int  numconfigstrings,
char *  configstrings[]
 

Definition at line 142 of file be_aas_main.c.

References aasworld, aas_s::configstrings, GetMemory(), i, aas_s::indexessetup, strcpy(), and strlen().

00143 {
00144     int i;
00145     //set string pointers and copy the strings
00146     for (i = 0; i < numconfigstrings; i++)
00147     {
00148         if (configstrings[i])
00149         {
00150             //if (aasworld.configstrings[i]) FreeMemory(aasworld.configstrings[i]);
00151             aasworld.configstrings[i] = (char *) GetMemory(strlen(configstrings[i]) + 1);
00152             strcpy(aasworld.configstrings[i], configstrings[i]);
00153         } //end if
00154     } //end for
00155     aasworld.indexessetup = qtrue;
00156 } //end of the function AAS_UpdateStringIndexes

Here is the call graph for this function:


Variable Documentation

aas_t aasworld
 

Definition at line 47 of file be_aas_main.c.

Referenced by AAS_AASLinkEntity(), AAS_AddEdgeToHash(), AAS_AddPlaneToHash(), AAS_AgainstLadder(), AAS_AllocAASLink(), AAS_AllocMaxAAS(), AAS_AlternativeRouteGoals(), AAS_AltRoutingFloodCluster_r(), AAS_AreaCluster(), AAS_AreaClusterPortal(), AAS_AreaContentsTravelFlags(), AAS_AreaContentsTravelFlags_inline(), AAS_AreaCrouch(), AAS_AreaDoNotEnter(), AAS_AreaEntityCollision(), AAS_AreaGrounded(), AAS_AreaGroundFace(), AAS_AreaGroundFaceArea(), AAS_AreaInfo(), AAS_AreaJumpPad(), AAS_AreaLadder(), AAS_AreaLava(), AAS_AreaLiquid(), AAS_AreaPresenceType(), AAS_AreaReachability(), AAS_AreaRouteToGoalArea(), AAS_AreaSlime(), AAS_AreaSwim(), AAS_AreaTeleporter(), AAS_AreaVolume(), AAS_BestReachableArea(), AAS_BestReachableEntityArea(), AAS_CalcReachAndClusters(), AAS_CalculateAreaTravelTimes(), AAS_CheckAreaForPossiblePortals(), AAS_ClearCluster(), AAS_ClientMovementPrediction(), AAS_ClusterAreaNum(), AAS_ConnectedAreas_r(), AAS_ContinueInit(), AAS_ContinueInitReachability(), AAS_CountForcedClusterPortals(), AAS_CreateAllRoutingCache(), AAS_CreatePortals(), AAS_CreateReversedReachability(), AAS_CreateViewPortals(), AAS_DeAllocAASLink(), AAS_DumpAASData(), AAS_EnableRoutingArea(), AAS_EntityBSPData(), AAS_EntityInfo(), AAS_EntityModelindex(), AAS_EntityModelNum(), AAS_EntityOrigin(), AAS_EntitySize(), AAS_EntityType(), AAS_FaceArea(), AAS_FaceCenter(), AAS_FacePlane(), AAS_FindClusters(), AAS_FindFaceReachabilities(), AAS_FindHashedEdge(), AAS_FindHashedPlane(), AAS_FindPlane(), AAS_FindPossiblePortals(), AAS_FloodAreas(), AAS_FloodAreas_r(), AAS_FloodClusterAreas_r(), AAS_FloodClusterAreasUsingReachabilities(), AAS_FreeAASLinkedEntities(), AAS_FreeAASLinkHeap(), AAS_FreeAllClusterAreaCache(), AAS_FreeAllPortalCache(), AAS_FreeMaxAAS(), AAS_FreeOldestCache(), AAS_FreeRoutingCaches(), AAS_GetAdjacentAreasWithLessPresenceTypes_r(), AAS_GetAreaContentsTravelFlags(), AAS_GetAreaRoutingCache(), AAS_GetEdge(), AAS_GetFace(), AAS_GetPlane(), AAS_GetPortalRoutingCache(), AAS_GetVertex(), AAS_IndexFromModel(), AAS_IndexFromString(), AAS_InitAASLinkedEntities(), AAS_InitAASLinkHeap(), AAS_InitAlternativeRouting(), AAS_InitAreaContentsTravelFlags(), AAS_InitClusterAreaCache(), AAS_InitClustering(), AAS_Initialized(), AAS_InitPortalCache(), AAS_InitPortalMaxTravelTimes(), AAS_InitReachability(), AAS_InitReachabilityAreas(), AAS_InitRoutingUpdate(), AAS_InitTravelFlagFromType(), AAS_InsideFace(), AAS_InvalidateEntities(), AAS_LinkCache(), AAS_LoadAASFile(), AAS_Loaded(), AAS_LoadFiles(), AAS_LoadMap(), AAS_ModelFromIndex(), AAS_NearestEntity(), AAS_NearestHideArea(), AAS_NextAreaReachability(), AAS_NextEntity(), AAS_NextModelReachability(), AAS_NumberClusterAreas(), AAS_NumberClusterPortals(), AAS_Optimize(), AAS_OptimizeAlloc(), AAS_OptimizeArea(), AAS_OptimizeEdge(), AAS_OptimizeFace(), AAS_OptimizeStore(), AAS_OriginOfMoverWithModelNum(), AAS_PlaneEqual(), AAS_PlaneFromNum(), AAS_PointAreaNum(), AAS_PointInsideFace(), AAS_PointPresenceType(), AAS_PointReachabilityAreaIndex(), AAS_PortalMaxTravelTime(), AAS_PredictRoute(), AAS_RandomGoalArea(), AAS_Reachability_EqualFloorHeight(), AAS_Reachability_Grapple(), AAS_Reachability_Jump(), AAS_Reachability_JumpPad(), AAS_Reachability_Ladder(), AAS_Reachability_Step_Barrier_WaterJump_WalkOffLedge(), AAS_Reachability_Swim(), AAS_Reachability_WalkOffLedge(), AAS_Reachability_WeaponJump(), AAS_ReachabilityFromNum(), AAS_ReadRouteCache(), AAS_RemoveAllPortals(), AAS_RemoveClusterAreas(), AAS_RemovePortalsClusterReference(), AAS_RemoveRoutingCacheInCluster(), AAS_RemoveRoutingCacheUsingArea(), AAS_ResetEntityLinks(), AAS_SetInitialized(), AAS_Setup(), AAS_SetViewPortalsAsClusterPortals(), AAS_SetWeaponJumpAreaFlags(), AAS_ShowArea(), AAS_ShowAreaPolygons(), AAS_ShowFace(), AAS_ShowFacePolygon(), AAS_ShowNumReachabilities(), AAS_ShowReachableAreas(), AAS_ShowTotals(), AAS_Shutdown(), AAS_StartFrame(), AAS_StoreArea(), AAS_StoreAreaSettings(), AAS_StoreBoundingBoxes(), AAS_StoreFile(), AAS_StoreReachability(), AAS_StoreTree_r(), AAS_StringFromIndex(), AAS_SwapAASData(), AAS_TestPortals(), AAS_Time(), AAS_TraceAreas(), AAS_TraceClientBBox(), AAS_TraceEndFace(), AAS_TravelFlagForType_inline(), AAS_UnlinkCache(), AAS_UnlinkFromAreas(), AAS_UnlinkInvalidEntities(), AAS_UpdateAreaRoutingCache(), AAS_UpdateEntity(), AAS_UpdatePortal(), AAS_UpdatePortalRoutingCache(), AAS_UpdateStringIndexes(), AAS_WriteAASFile(), AAS_WriteRouteCache(), BotExportTest(), main(), TH_AASFaceVertex(), TH_AASToTriangleMesh(), and TH_FaceCenter().

libvar_t* saveroutingcache
 

Definition at line 49 of file be_aas_main.c.

Referenced by AAS_Setup(), and AAS_StartFrame().


Generated on Thu Aug 25 12:39:27 2005 for Quake III Arena by  doxygen 1.3.9.1