Ticket #788: SameTurnMovesPatch.patch
File SameTurnMovesPatch.patch, 8.8 KB (added by , 13 years ago) |
---|
-
binaries/data/mods/public/simulation/data/pathfinder.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Pathfinder> 3 3 4 <!-- 5 Previously all move commands during a turn were 6 queued up and processed asynchronously at the start 7 of the next turn. Now we are processing queued up 8 events several times duing the turn. This improves 9 responsiveness and units move more smoothly especially. 10 when in formation. There is still a call at the 11 beginning of a turn to process all outstanding moves - 12 this will handle any moves above the MaxSameTurnMoves 13 threshold. 14 15 TODO - The moves processed at the beginning of the 16 turn do not count against the maximum moves per turn 17 currently. The thinking is that this will eventually 18 happen in another thread. Either way this probably 19 will require some adjustment and rethinking. 20 --> 21 <MaxSameTurnMoves>16</MaxSameTurnMoves> 22 4 23 <PassabilityClasses> 5 24 6 25 <!-- Unit pathfinding classes: --> -
source/simulation2/components/CCmpPathfinder.cpp
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
58 58 CParamNode externalParamNode; 59 59 CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml"); 60 60 61 const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder"); 62 m_MaxSameTurnMoves = pathingSettings.GetChild("MaxSameTurnMoves").ToInt(); 61 63 64 62 65 const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren(); 63 66 for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it) 64 67 { … … 199 202 m_TerrainDirty = true; 200 203 break; 201 204 } 205 case MT_TurnStart: 206 { 207 m_SameTurnMovesCount = 0; 208 break; 202 209 } 210 } 203 211 } 204 212 205 213 void CCmpPathfinder::RenderSubmit(SceneCollector& collector) … … 435 443 // TODO: this computation should be done incrementally, spread 436 444 // across multiple frames (or even multiple turns) 437 445 446 ProcessLongRequests(longRequests); 447 ProcessShortRequests(shortRequests); 448 } 449 450 void CCmpPathfinder::ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests) 451 { 438 452 for (size_t i = 0; i < longRequests.size(); ++i) 439 453 { 440 454 const AsyncLongPathRequest& req = longRequests[i]; … … 443 457 CMessagePathResult msg(req.ticket, path); 444 458 GetSimContext().GetComponentManager().PostMessage(req.notify, msg); 445 459 } 460 } 446 461 462 void CCmpPathfinder::ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests) 463 { 447 464 for (size_t i = 0; i < shortRequests.size(); ++i) 448 465 { 449 466 const AsyncShortPathRequest& req = shortRequests[i]; … … 454 471 GetSimContext().GetComponentManager().PostMessage(req.notify, msg); 455 472 } 456 473 } 474 475 void CCmpPathfinder::ProcessSameTurnMoves() 476 { 477 u32 moveCount; 478 479 if (m_AsyncLongPathRequests.size() > 0) 480 { 481 // Figure out how many moves we can do this time 482 moveCount = m_MaxSameTurnMoves - m_SameTurnMovesCount; 483 484 if (moveCount <= 0) 485 return; 486 487 // Copy the long request elements we are going to process into a new array 488 std::vector<AsyncLongPathRequest> longRequests; 489 if (m_AsyncLongPathRequests.size() <= moveCount) 490 { 491 m_AsyncLongPathRequests.swap(longRequests); 492 moveCount = longRequests.size(); 493 } 494 else 495 { 496 longRequests.resize(moveCount); 497 copy(m_AsyncLongPathRequests.begin(), m_AsyncLongPathRequests.begin() + moveCount, longRequests.begin()); 498 m_AsyncLongPathRequests.erase(m_AsyncLongPathRequests.begin(), m_AsyncLongPathRequests.begin() + moveCount); 499 } 500 501 ProcessLongRequests(longRequests); 502 503 m_SameTurnMovesCount += moveCount; 504 } 505 506 if (m_AsyncShortPathRequests.size() > 0) 507 { 508 // Figure out how many moves we can do now 509 moveCount = m_MaxSameTurnMoves - m_SameTurnMovesCount; 510 511 if (moveCount <= 0) 512 return; 513 514 // Copy the short request elements we are going to process into a new array 515 std::vector<AsyncShortPathRequest> shortRequests; 516 if (m_AsyncShortPathRequests.size() <= moveCount) 517 { 518 m_AsyncShortPathRequests.swap(shortRequests); 519 moveCount = shortRequests.size(); 520 } 521 else 522 { 523 shortRequests.resize(moveCount); 524 copy(m_AsyncShortPathRequests.begin(), m_AsyncShortPathRequests.begin() + moveCount, shortRequests.begin()); 525 m_AsyncShortPathRequests.erase(m_AsyncShortPathRequests.begin(), m_AsyncShortPathRequests.begin() + moveCount); 526 } 527 528 ProcessShortRequests(shortRequests); 529 530 m_SameTurnMovesCount += moveCount; 531 } 532 } 533 -
source/simulation2/components/CCmpPathfinder_Common.h
161 161 componentManager.SubscribeToMessageType(MT_Update); 162 162 componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays 163 163 componentManager.SubscribeToMessageType(MT_TerrainChanged); 164 componentManager.SubscribeToMessageType(MT_TurnStart); 164 165 } 165 166 166 167 DEFAULT_COMPONENT_ALLOCATOR(Pathfinder) … … 187 188 Grid<TerrainTile>* m_Grid; // terrain/passability information 188 189 Grid<u8>* m_ObstructionGrid; // cached obstruction information (TODO: we shouldn't bother storing this, it's redundant with LSBs of m_Grid) 189 190 bool m_TerrainDirty; // indicates if m_Grid has been updated since terrain changed 191 192 // For responsiveness we will procees some moves in the same turn they were generated in 193 194 u16 m_MaxSameTurnMoves; // max number of moves that can be created and processed in the same turn 195 u16 m_SameTurnMovesCount; // current number of same turn moves we have processed this turn 190 196 191 197 // Debugging - output from last pathfind operation: 198 192 199 PathfindTileGrid* m_DebugGrid; 193 200 u32 m_DebugSteps; 194 201 Path* m_DebugPath; … … 242 249 243 250 virtual void FinishAsyncRequests(); 244 251 252 virtual void ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests); 253 254 virtual void ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests); 255 256 virtual void ProcessSameTurnMoves(); 257 245 258 /** 246 259 * Returns the tile containing the given position 247 260 */ -
source/simulation2/components/ICmpPathfinder.h
159 159 */ 160 160 virtual void FinishAsyncRequests() = 0; 161 161 162 /** 163 * Process moves during the same turn they were created in to improve responsiveness. 164 */ 165 virtual void ProcessSameTurnMoves() = 0; 166 162 167 DECLARE_INTERFACE_TYPE(Pathfinder) 163 168 }; 164 169 -
source/simulation2/Simulation2.cpp
229 229 if (!cmpCommandQueue.null()) 230 230 cmpCommandQueue->FlushTurn(commands); 231 231 232 // Process newly generated move commands so the UI feels snappy 233 if (!cmpPathfinder.null()) 234 cmpPathfinder->ProcessSameTurnMoves(); 235 232 236 // Send all the update phases 233 237 { 234 238 CMessageUpdate msgUpdate(turnLengthFixed); … … 238 242 CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed); 239 243 m_ComponentManager.BroadcastMessage(msgUpdate); 240 244 } 245 246 // Process move commands for formations (group proxy) 247 if (!cmpPathfinder.null()) 248 cmpPathfinder->ProcessSameTurnMoves(); 249 241 250 { 242 251 CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed); 243 252 m_ComponentManager.BroadcastMessage(msgUpdate); … … 247 256 m_ComponentManager.BroadcastMessage(msgUpdate); 248 257 } 249 258 259 // Process moves resulting from group proxy movement (unit needs to catch up or realign) and any others 260 if (!cmpPathfinder.null()) 261 cmpPathfinder->ProcessSameTurnMoves(); 262 263 250 264 // Clean up any entities destroyed during the simulation update 251 265 m_ComponentManager.FlushDestroyedComponents(); 252 266