#include "MW4Headers.hpp" #include "Adept\AdeptHeaders.hpp" #include #include #include "moverai.hpp" #include "obstacle.hpp" #include "bridge.hpp" #include "cultural.hpp" #include "airplane.hpp" #include "building.hpp" #include "mwplayer.hpp" namespace MW4AI { struct LineData { LockData *root; }; const int MAXLINES = 1024; LineData *g_Obstacles; Rect4DHashTable *g_Rect4DHash,*g_AirRect4DHash; Stuff::Scalar g_MaxBuildingHeight = 0; Stuff::Scalar g_MaxAirHeight = 0; Stuff::MemoryBlockOf *Rect4D::m_EmptyRect=NULL; Stuff::MemoryBlockOf *LockData::m_EmptyData = NULL; DWORD Obstacle_Size = 0; void InitObstacle (void) { int i; Rect4D::m_EmptyRect = new MemoryBlockOf (1000,100,"Temporal Rects"); LockData::m_EmptyData = new MemoryBlockOf (1000,100,"Path lock Data"); g_Rect4DHash = new Rect4DHashTable (200); g_AirRect4DHash = new Rect4DHashTable(200); g_Obstacles = new LineData[MAXLINES]; Check_Pointer (g_Obstacles); for (i=0;inext; delete temp; } } delete g_Obstacles; g_Obstacles = NULL; delete g_Rect4DHash; g_Rect4DHash = NULL; delete g_AirRect4DHash; g_AirRect4DHash = NULL; delete Rect4D::m_EmptyRect; Rect4D::m_EmptyRect = NULL; delete LockData::m_EmptyData; LockData::m_EmptyData = NULL; } void MW4AI::KillPermRects (void) { g_Rect4DHash->KillRectList (); } void SetupPermRects (void) { Verify (g_Rect4DHash); int tablescan[] = { NameTable::BuildingArray, NameTable::TurretArray, NameTable::VehicleArray }; g_MaxBuildingHeight = 0; g_MaxAirHeight = 0; int size,i,j; NameTable *table = NameTable::GetInstance(); Check_Object (table); for (i=0;inameTableArray[tablescan[i]].GetLength (); for (j=0;jnameTableArray [tablescan[i]][j]; if (data->objectName && !strnicmp (data->objectName,"water",5)) { continue; } who = data->dataPointer->GetCurrent (); if (!who) continue; if ((!who->GetHierarchicalVolume ()) && (!who->GetSolidVolume ())) continue; MWObject *obj=NULL; OBB *obb; CollisionVolume *col; col = who->GetHierarchicalVolume (); if (!col) col = who->GetSolidVolume (); OBB world_bounds; world_bounds.Multiply(col->m_localSpaceBounds, who->GetLocalToWorld()); obb = &(world_bounds); ExtentBox box (*obb); if (who->IsDerivedFrom (Vehicle::DefaultData)) { if ((box.maxY - box.minY) > g_MaxAirHeight) { g_MaxAirHeight = box.maxY - box.minY; } } else // must be a building { if ((box.maxY - box.minY) > g_MaxBuildingHeight) { g_MaxBuildingHeight = box.maxY - box.minY; } } if (!who->IsDerivedFrom (MechWarrior4::Cultural::DefaultData)) { obj = Cast_Object (MWObject *,who); AI *ai; ai = obj->GetAI (); if (ai && ai->IsDerivedFrom (MoverAI::DefaultData)) continue; } if (who->IsDerivedFrom (Bridge::DefaultData)) continue; // if ((obj->GetAI ()) && (tablescan[i] != NameTable::BuildingArray)) // continue; Point3D loc = (Point3D) obb->localToParent; Rect4D temprect; temprect.left = box.minX; temprect.right = box.maxX; temprect.top = box.minZ; temprect.bottom = box.maxZ; temprect.who = who; g_Rect4DHash->AddPermRect (temprect); } } g_MaxAirHeight += 5.0f; g_MaxBuildingHeight += 10.0f; if (g_MaxBuildingHeight < 20.0f) { g_MaxBuildingHeight = 20.0f; } Check_Object (table); size = table->nameTableArray[NameTable::VehicleArray].GetLength (); for (j=0;jnameTableArray [NameTable::VehicleArray][j]; who = data->dataPointer->GetCurrent (); if (!who) continue; if (!who->IsDerivedFrom (Airplane::DefaultData)) { continue; } air = Cast_Object (Airplane *,who); air->AdjustAltitude (); } } MWObject *BlockerLocal (int x,int z) { LockData *temp; x -= (int) (MinX/BLOCK_GRID_RES); z -= (int) (MinZ/BLOCK_GRID_RES); Clamp (x,0,(int) (2*(MaxX/BLOCK_GRID_RES))); Clamp (z,0,MAXLINES-1); Verify (z>=0); Verify (zlocx == x) && (temp->locz == z)) return temp->who; temp = temp->next; } return NULL; } bool AddBlockLocal (int x,int z,MWObject *who) { if (BlockerLocal (x,z)) { return false; } x -= (int) (MinX/BLOCK_GRID_RES); z -= (int) (MinZ/BLOCK_GRID_RES); Verify (z>=0); Verify (znext = g_Obstacles[z].root; g_Obstacles[z].root = temp; Set_Statistic(Obstacle_Size, Obstacle_Size+1); return true; } void RemoveBlockLocal (int x,int z,MWObject *who) { x -= (int) (MinX/BLOCK_GRID_RES); z -= (int) (MinZ/BLOCK_GRID_RES); Verify (z>=0); Verify (zlocx == x) && (temp->locz == z) && (temp->who == who)) { g_Obstacles[z].root = temp->next; if (g_Obstacles[z].root) Check_Pointer (g_Obstacles[z].root); delete temp; Set_Statistic(Obstacle_Size, Obstacle_Size-1); return; } while (temp->next) { LockData *fred; fred = temp->next; if ((fred->locx == x) && (fred->locz == z) && (fred->who == who)) { temp->next = fred->next; if (temp->next) Check_Pointer (temp->next); delete fred; Set_Statistic(Obstacle_Size, Obstacle_Size-1); return; } temp = temp->next; } Verify (false); } void Rect4DHashTable::KillHashLine (int i) { ablREPORT (i>=0,""); ablREPORT (i < m_ListSize,""); m_List[i] = NULL; // everybody else is responsible for freeing themselvs } void Rect4DHashTable::KillRectList (void) { Rect4D *current,*temp; current = m_PermList; while (current) { temp = current; current = current->next; temp->next = temp->prev = NULL; delete temp; } m_PermList = NULL; } void Rect4DHashTable::AddRect (Rect4D* p1) { Verify (false); int loc; ablREPORT (p1,""); ablREPORT (p1->who,""); ablREPORT (p1->who->IsDerivedFrom (Entity::DefaultData),""); // Verify (p1->who->IsDerivedFrom (MWObject::DefaultData)); ablREPORT (p1->who->IsDerivedFrom (MechWarrior4::MWPlayer::DefaultData) || p1->who->IsDerivedFrom (AI::DefaultData) || p1->who->IsDerivedFrom (Vehicle::DefaultData) || p1->who->IsDerivedFrom (Building::DefaultData),""); if (p1->left < MinX) p1->left = MinX; if (p1->top < MinZ) p1->top = MinZ; if (p1->right < MinX) p1->right = MinX; if (p1->bottom < MinZ) p1->bottom = MinZ; if (p1->top >= (MaxZ-1)) p1->top = MaxZ-1; if (p1->left >= (MaxX-1)) p1->left = MaxX-1; if (p1->bottom >= (MaxZ-1)) p1->bottom = MaxZ-1; if (p1->right >= (MaxX-1)) p1->right = MaxX-1; ablREPORT (p1->left <= p1->right,""); ablREPORT (p1->top <= p1->bottom,""); loc = FindHashLine (*p1); if (loc==-1) return; ablREPORT (loc>=0,""); ablREPORT (loc < m_ListSize,""); ablREPORT (p1->prev == NULL,""); ablREPORT (p1->next == NULL,""); p1->prev = NULL; p1->next = m_List[loc]; if (m_List[loc]) { ablREPORT (m_List[loc],""); m_List[loc]->prev = p1; } m_List[loc] = p1; } Rect4DHashTable::Rect4DHashTable (int size) { int i; m_List = (Rect4D **) gos_Malloc (sizeof (Rect4D *) * size); for (i=0;inext; delete temp; } } void Rect4DHashTable::UpdateTime (Stuff::Time curtime) { int temptime; curtime *= Rect4DTimeDelta; temptime = (int) ((float) curtime); // temptime = Truncate_Float_To_Word ((float) curtime); while (m_CurrentTime < temptime) { IncrementTime (); } } void Rect4DHashTable::IncrementTime (void) { KillHashLine (m_TopList); m_TopList++; m_CurrentTime += 1; if (m_TopList == m_ListSize) m_TopList = 0; } void Rect4DHashTable::RemovePermRect (Entity *who) { Rect4D *current; current = m_PermList; while (current) { if (current->who == who) { RemovePermRect (current); return; } current = current->next; } } Rect4D *Rect4DHashTable::Collide (const Rect4D& p1) const { Verify (false); int loc; Rect4D *current; // Stuff::Scalar left,right,top,bottom; current = m_PermList; for (current=m_PermList;current;current = current->next) { if (p1.who != current->who) { if (p1.right < current->left) continue; if (p1.left > current->right) continue; if (p1.bottom < current->top) continue; if (p1.top > current->bottom) continue; return current; } } if (p1.time < m_CurrentTime) return NULL; if (p1.time >= (m_CurrentTime + m_ListSize)) return NULL; loc = FindHashLine (p1); if (loc==-1) return NULL; Verify (loc>=0); Verify (loc < m_ListSize); current = m_List[loc]; for (current=m_List[loc];current;current = current->next) { if (p1.who != current->who) { if (p1.right < current->left) continue; if (p1.left > current->right) continue; if (p1.bottom < current->top) continue; if (p1.top > current->bottom) continue; return current; } } return NULL; } #ifdef _ARMOR void Rect4DHashTable::VerifyRectGone (Rect4D *p1) { int i; Rect4D *current; for (i=0;inext; } } } #endif };