#include "MW4Headers.hpp" #include "adept\application.hpp" #include "rail_move.hpp" #include "move_rect.hpp" #include "ai.hpp" #pragma warning (push) #include #include #pragma warning (pop) namespace MW4AI { extern Stuff::Scalar MinZ, MaxZ, MinX, MaxX; extern __int64 tPathTime,tGridPathTime; extern __int64 tNodeToPathTime; }; using namespace MW4AI; using namespace MechWarrior4; void CRailPath::AddStartPoint (Stuff::Point3D& loc,bool& startbrid,stlport::vector::iterator& iter) { Stuff::Point3D extra,destloc1,destloc2,center; Stuff::Point3D d1vec,d2vec,third; int nodeto; AutoHeap local_heap (g_RailHeap); const OBRect *brid; brid = m_Graph->RectList ()->Inside (m_Start); if (brid) { CRailNode *destnode1,*destnode2; Verify (m_NodePath.size () >= 2); destnode1 = m_NodePath[0].destnode; destnode2 = m_NodePath[1].destnode; startbrid = true; const OBRect *crossbrid; crossbrid = m_Graph->RectList ()->Collide (destnode1->Location (),destnode2->Location ()); m_Path.push_back (PathElement (m_Start,BRIDGEFLAG,true,-1)); if (brid == crossbrid) { iter++; nodeto = 1; } else { nodeto = 0; } if (brid->vertical) { destloc2 = brid->BottomPoint (); destloc1 = brid->TopPoint (); if (m_NodePath[nodeto].destnode->Location ().z < destloc1.z) { m_Path.push_back (PathElement (destloc1,BRIDGEFLAG,true,-1)); loc = destloc1; } else { m_Path.push_back (PathElement (destloc2,BRIDGEFLAG,true,-1)); loc = destloc2; } } else { destloc2 = brid->RightPoint (); destloc1 = brid->LeftPoint (); if (m_NodePath[nodeto].destnode->Location ().x < destloc1.x) { m_Path.push_back (PathElement (destloc1,BRIDGEFLAG,true,-1)); loc = destloc1; } else { m_Path.push_back (PathElement (destloc2,BRIDGEFLAG,true,-1)); loc = destloc2; } } loc.y = 0; } else { // m_Path.push_back (PathElement (m_Start,m_NodePath[0].usage,false,-1)); loc = m_Start; loc.y = 0; } iter++; } void CRailPath::AddBridgeToPath (stlport::vector::iterator iter,Stuff::Point3D& loc,const OBRect *bridge,bool startbrid) { AutoHeap local_heap (g_RailHeap); Stuff::Point3D destloc1,destloc2; if (bridge->vertical) { if (loc.z >= bridge->bottom) { destloc2 = bridge->BottomPoint (); destloc1 = bridge->TopPoint (); } else { destloc2 = bridge->TopPoint (); destloc1 = bridge->BottomPoint (); } } else { if (loc.x >= bridge->right) { destloc2 = bridge->RightPoint (); destloc1 = bridge->LeftPoint (); } else { destloc2 = bridge->LeftPoint (); destloc1 = bridge->RightPoint (); } } Verify (!startbrid); if (!startbrid) m_Path.push_back (PathElement (destloc2,iter->usage + BRIDGEFLAG,false,iter->link->ID ())); m_Path.push_back (PathElement (destloc1,BRIDGEFLAG,true,iter->link->ID ())); loc = destloc1; } void CRailPath::AddPointToPath (stlport::vector::iterator iter,Stuff::Point3D& loc) { Stuff::Point3D extra,destloc1,destloc2,center; Stuff::Point3D d1vec,d2vec,third; CRailNode *destnode; CRailLink *destlink; Stuff::Scalar distnode; Stuff::Scalar slope,intercept,rad,a,b,c,inner,root,x1,x2,t1,t2,y,w; AutoHeap local_heap (g_RailHeap); destnode = iter->destnode; destlink = iter->link; Verify (destnode); Verify (destlink); destloc1 = destnode->SubNode (destlink).location; destloc2 = destlink->OtherLocation (destnode)->SubNode (destlink).location; center = destnode->Location (); center.y = 0; destloc1.y = destloc2.y = 0; extra.Subtract (center,loc); distnode = extra.GetLengthSquared (); rad = destnode->RadiusSquared(); if (destloc2.x == loc.x) slope = 100000.0f; else slope = (destloc2.z-loc.z)/(destloc2.x-loc.x); intercept = destloc2.z-(slope*destloc2.x); w = intercept-center.z; a = (slope*slope)+1.0f; b = (2.0f*slope*w)-(2.0f*center.x); c = (w*w)-(rad)+(center.x*center.x); // b = (2.0f*slope*intercept)-(2.0f*center.x)-(2.0f*slope*center.z); // c = (center.x*center.x)+(intercept*intercept)-(2.0*center.z*intercept)+(center.y*center.y)-(rad); inner = (b*b) - (4.0f*a*c); if (inner < 0) { Stuff::Point3D temppt; temppt = m_Graph->PullPointElement (loc,destloc2,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } temppt = m_Graph->PullPointElement (loc,destloc1,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } loc = temppt; } else { root = (float) sqrt (inner); x1 = (-b+root)/(2*a); x2 = (-b-root)/(2*a); if (destloc2.x == loc.x) { t1 = (x1-loc.x)/(0.00001f); t2 = (x2-loc.x)/(0.00001f); } else { t1 = (x1-loc.x)/(destloc2.x-loc.x); t2 = (x2-loc.x)/(destloc2.x-loc.x); } if ((t1>=0) && (t1<=1.0)) { y= slope*x1 + intercept; Stuff::Point3D temppt; temppt.x = x1; temppt.y = 0; temppt.z = y; temppt = m_Graph->PullPointElement (loc,temppt,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } loc = temppt; } else if ((t2>=0) && (t2<=1.0)) { y= slope*x2 + intercept; Stuff::Point3D temppt; temppt.x = x2; temppt.y = 0; temppt.z = y; temppt = m_Graph->PullPointElement (loc,temppt,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } loc = temppt; } else { Stuff::Point3D temppt; temppt = m_Graph->PullPointElement (loc,destloc2,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } temppt = m_Graph->PullPointElement (loc,destloc1,iter->usage); if (temppt != Stuff::Point3D (-1,-1,-1)) { m_Path.push_back (PathElement (temppt,iter->usage,false,iter->link->ID ())); Verify (!(CheckCanPass(m_Graph->Passable (temppt.x,temppt.z) , ConvertUsagetoMovePass (iter->usage)))); } loc = temppt; } } } void CRailPath::AddEndPoint (Stuff::Point3D& loc) { Stuff::Point3D extra,destloc1,destloc2,center; Stuff::Point3D d1vec,d2vec,third; const OBRect *brid; AutoHeap local_heap (g_RailHeap); brid = m_Graph->RectList ()->Inside (m_End); if (brid) { Stuff::Point3D temppt,where; where.y = 0; if (brid->vertical) { destloc2 = brid->BottomPoint (); destloc1 = brid->TopPoint (); if (loc.z < destloc1.z) { where.x = destloc1.x; where.z = destloc1.z; } else { where.x = destloc2.x; where.z = destloc2.z; } temppt = m_Graph->PullPointElement (loc,where,m_UsageAllowed); if (temppt != Stuff::Point3D (-1,-1,-1)) m_Path.push_back (PathElement (temppt,m_UsageAllowed,false,-1)); } else { destloc2 = brid->RightPoint (); destloc1 = brid->LeftPoint (); if (loc.x < destloc1.x) { where.x = destloc1.x; where.z = destloc1.z; } else { where.x = destloc2.x; where.z = destloc2.z; } temppt = m_Graph->PullPointElement (loc,where,m_UsageAllowed); if (temppt != Stuff::Point3D (-1,-1,-1)) m_Path.push_back (PathElement (temppt,m_UsageAllowed,false,-1)); } m_Path.push_back (PathElement (m_End,BRIDGEFLAG,true,-1)); } else { Stuff::Point3D temppt; temppt.x = m_End.x; temppt.y = 0; temppt.z = m_End.z; temppt = m_Graph->PullPointElement (loc,temppt,m_UsageAllowed); if (temppt != Stuff::Point3D (-1,-1,-1)) m_Path.push_back (PathElement (temppt,m_UsageAllowed,false,-1)); } } void CRailPath::HandleOneNodePath (void) { Stuff::Point3D loc,extra,destloc1,destloc2,center; Stuff::Point3D d1vec,d2vec,third; Stuff::Point3D temppt; AutoHeap local_heap (g_RailHeap); const OBRect *brid1,*brid2; brid1 = m_Graph->RectList ()->Inside (m_Start); brid2 = m_Graph->RectList ()->Inside (m_End); if ((brid1 == brid2) && (brid1 != NULL)) // start and stop on the same bridge { m_Path.push_back (PathElement (m_Start,BRIDGE_FLAG,true,-1)); m_Path.push_back (PathElement (m_End,BRIDGE_FLAG,true,-1)); } else if (brid1 != brid2 && (brid1 != NULL) && (brid2 != NULL)) // start and stop on two different bridges { m_Path.push_back (PathElement (m_Start,BRIDGE_FLAG,true,-1)); if (brid1->vertical) // calc point on edge of bridge to get off { destloc2 = brid1->BottomPoint (); destloc1 = brid1->TopPoint (); if (m_End.z < destloc1.z) m_Path.push_back (PathElement (destloc1,BRIDGE_FLAG,true,-1)); else m_Path.push_back (PathElement (destloc2,BRIDGE_FLAG,true,-1)); } else { destloc2 = brid1->RightPoint (); destloc1 = brid1->LeftPoint (); if (m_End.x < destloc1.x) m_Path.push_back (PathElement (destloc1,BRIDGE_FLAG,true,-1)); else m_Path.push_back (PathElement (destloc2,BRIDGE_FLAG,true,-1)); } if (brid2->vertical) // calc point on edge of bridge to get onto { destloc2 = brid2->BottomPoint (); destloc1 = brid2->TopPoint (); if (m_Start.z < destloc1.z) m_Path.push_back (PathElement (destloc1,m_NodePath[0].usage,false,-1)); else m_Path.push_back (PathElement (destloc2,m_NodePath[0].usage,false,-1)); } else { destloc2 = brid2->RightPoint (); destloc1 = brid2->LeftPoint (); if (m_Start.x < destloc1.x) m_Path.push_back (PathElement (destloc1,m_NodePath[0].usage,false,-1)); else m_Path.push_back (PathElement (destloc2,m_NodePath[0].usage,false,-1)); } m_Path.push_back (PathElement (m_End,BRIDGE_FLAG,true,-1)); } else if ((brid1) && (m_Graph->RectList ()->Collide (m_Start,m_End))) // start on a bridge and stop off a bridge { m_Path.push_back (PathElement (m_Start,BRIDGE_FLAG,true,-1)); if (brid1->vertical) // calc point on edge of bridge to get off { destloc2 = brid1->BottomPoint (); destloc1 = brid1->TopPoint (); if (m_End.z < destloc1.z) m_Path.push_back (PathElement (destloc1,BRIDGE_FLAG,true,-1)); else m_Path.push_back (PathElement (destloc2,BRIDGE_FLAG,true,-1)); } else { destloc2 = brid1->RightPoint (); destloc1 = brid1->LeftPoint (); if (m_End.x < destloc1.x) m_Path.push_back (PathElement (destloc1,BRIDGE_FLAG,true,-1)); else m_Path.push_back (PathElement (destloc2,BRIDGE_FLAG,true,-1)); } m_Path.push_back (PathElement (m_End,m_NodePath[0].usage,false,-1)); } else if ((brid2) && (m_Graph->RectList ()->Collide (m_Start,m_End))) // start off a bridge and stop on a bridge { m_Path.push_back (PathElement (m_Start,m_NodePath[0].usage,false,-1)); if (brid2->vertical) // calc point on edge of bridge to get onto { destloc2 = brid2->BottomPoint (); destloc1 = brid2->TopPoint (); if (m_Start.z < destloc1.z) m_Path.push_back (PathElement (destloc1,m_NodePath[0].usage,false,-1)); else m_Path.push_back (PathElement (destloc2,m_NodePath[0].usage,false,-1)); } else { destloc2 = brid2->RightPoint (); destloc1 = brid2->LeftPoint (); if (m_Start.x < destloc1.x) m_Path.push_back (PathElement (destloc1,m_NodePath[0].usage,false,-1)); else m_Path.push_back (PathElement (destloc2,m_NodePath[0].usage,false,-1)); } m_Path.push_back (PathElement (m_End,BRIDGE_FLAG,true,-1)); } else // normal one node path, could be under bridge { m_Path.push_back (PathElement (m_Start,m_NodePath[0].usage,false,-1)); temppt = m_Graph->PullPointElement (m_Start,m_End,m_NodePath[0].usage); if (temppt == Stuff::Point3D (-1,-1,-1)) { m_Calced = false; return; } m_Path.push_back (PathElement (temppt,m_NodePath[0].usage,false,-1)); } m_InPath = m_Path.begin (); } void CRailPath::AddJumpPoint (stlport::vector::iterator iter,Stuff::Point3D& loc) { Stuff::Point3D destloc; CRailNode *destnode,*srcnode; CRailLink *destlink; AutoHeap local_heap (g_RailHeap); destnode = iter->destnode; destlink = iter->link; srcnode = destlink->OtherLocation (destnode); Verify (destnode); Verify (destlink); destloc = srcnode->Location (); // move to center of current node to get speed up m_Path.push_back (PathElement (destloc,LEGFLAG,false,iter->link->ID ())); destloc = srcnode->SubNode (destlink).location; // move to edge of current node m_Path.push_back (PathElement (destloc,LEGFLAG,true,iter->link->ID ())); destloc = destnode->SubNode (destlink).location; // jump to edge of next node m_Path.push_back (PathElement (destloc,iter->usage,true,iter->link->ID ())); } void CRailPath::ConvertNodeToPath (void) { PATH_LOGIC("Convert Node"); TIME_FUNCTION(tNodeToPathTime); stlport::vector::iterator iter; Stuff::Point3D loc,extra,destloc1,destloc2,center; Stuff::Point3D d1vec,d2vec,third; CRailNode *destnode; CRailLink *destlink; bool startbrid=false; Stuff::Scalar distnode; Stuff::Scalar rad; AutoHeap local_heap (g_RailHeap); m_Path.clear (); m_InPath = m_Path.begin (); if (m_NodePath.size () == 0) { Verify (false); return; } if (m_NodePath.size () == 1) { HandleOneNodePath (); return; } iter = m_NodePath.begin (); AddStartPoint (loc,startbrid,iter); while (iter != m_NodePath.end ()) { destnode = iter->destnode; destlink = iter->link; Verify (destnode); Verify (destlink); center = destnode->Location (); center.y = 0; destloc1.y = destloc2.y = 0; extra.Subtract (center,loc); distnode = extra.GetLengthSquared (); rad = destnode->RadiusSquared(); const OBRect *brid; brid = m_Graph->RectList ()->Collide (destnode->Location (),destlink->OtherLocation (destnode)->Location ()); if (brid) { AddBridgeToPath (iter,loc,brid,startbrid); } else if (iter->usage & JUMPFLAG) { AddJumpPoint (iter,loc); } else if (distnode > rad) // if not already in the next node { AddPointToPath (iter,loc); } startbrid = false; iter++; } AddEndPoint (loc); m_InPath = m_Path.begin (); }