Ticket #788: SameTurnMovesPatch.patch

File SameTurnMovesPatch.patch, 8.8 KB (added by Kenny Long, 13 years ago)

Patch to reduce movement time from command to actual movement

  • binaries/data/mods/public/simulation/data/pathfinder.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Pathfinder>
    33
     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 
    423  <PassabilityClasses>
    524
    625    <!-- 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
     
    5858    CParamNode externalParamNode;
    5959    CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml");
    6060
     61    const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder");
     62    m_MaxSameTurnMoves = pathingSettings.GetChild("MaxSameTurnMoves").ToInt();
    6163
     64
    6265    const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren();
    6366    for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it)
    6467    {
     
    199202        m_TerrainDirty = true;
    200203        break;
    201204    }
     205    case MT_TurnStart:
     206    {
     207        m_SameTurnMovesCount = 0;
     208        break;
    202209    }
     210    }
    203211}
    204212
    205213void CCmpPathfinder::RenderSubmit(SceneCollector& collector)
     
    435443    // TODO: this computation should be done incrementally, spread
    436444    // across multiple frames (or even multiple turns)
    437445
     446    ProcessLongRequests(longRequests);
     447    ProcessShortRequests(shortRequests);
     448}
     449
     450void CCmpPathfinder::ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests)
     451{
    438452    for (size_t i = 0; i < longRequests.size(); ++i)
    439453    {
    440454        const AsyncLongPathRequest& req = longRequests[i];
     
    443457        CMessagePathResult msg(req.ticket, path);
    444458        GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
    445459    }
     460}
    446461
     462void CCmpPathfinder::ProcessShortRequests(const std::vector<AsyncShortPathRequest>& shortRequests)
     463{
    447464    for (size_t i = 0; i < shortRequests.size(); ++i)
    448465    {
    449466        const AsyncShortPathRequest& req = shortRequests[i];
     
    454471        GetSimContext().GetComponentManager().PostMessage(req.notify, msg);
    455472    }
    456473}
     474
     475void 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

     
    161161        componentManager.SubscribeToMessageType(MT_Update);
    162162        componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays
    163163        componentManager.SubscribeToMessageType(MT_TerrainChanged);
     164        componentManager.SubscribeToMessageType(MT_TurnStart);
    164165    }
    165166
    166167    DEFAULT_COMPONENT_ALLOCATOR(Pathfinder)
     
    187188    Grid<TerrainTile>* m_Grid; // terrain/passability information
    188189    Grid<u8>* m_ObstructionGrid; // cached obstruction information (TODO: we shouldn't bother storing this, it's redundant with LSBs of m_Grid)
    189190    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
    190196
    191197    // Debugging - output from last pathfind operation:
     198
    192199    PathfindTileGrid* m_DebugGrid;
    193200    u32 m_DebugSteps;
    194201    Path* m_DebugPath;
     
    242249
    243250    virtual void FinishAsyncRequests();
    244251
     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
    245258    /**
    246259     * Returns the tile containing the given position
    247260     */
  • source/simulation2/components/ICmpPathfinder.h

     
    159159     */
    160160    virtual void FinishAsyncRequests() = 0;
    161161
     162    /**
     163     * Process moves during the same turn they were created in to improve responsiveness.
     164     */
     165    virtual void ProcessSameTurnMoves() = 0;
     166
    162167    DECLARE_INTERFACE_TYPE(Pathfinder)
    163168};
    164169
  • source/simulation2/Simulation2.cpp

     
    229229    if (!cmpCommandQueue.null())
    230230        cmpCommandQueue->FlushTurn(commands);
    231231
     232    // Process newly generated move commands so the UI feels snappy
     233    if (!cmpPathfinder.null())
     234        cmpPathfinder->ProcessSameTurnMoves();
     235
    232236    // Send all the update phases
    233237    {
    234238        CMessageUpdate msgUpdate(turnLengthFixed);
     
    238242        CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
    239243        m_ComponentManager.BroadcastMessage(msgUpdate);
    240244    }
     245
     246    // Process move commands for formations (group proxy)
     247    if (!cmpPathfinder.null())
     248        cmpPathfinder->ProcessSameTurnMoves();
     249
    241250    {
    242251        CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
    243252        m_ComponentManager.BroadcastMessage(msgUpdate);
     
    247256        m_ComponentManager.BroadcastMessage(msgUpdate);
    248257    }
    249258
     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
    250264    // Clean up any entities destroyed during the simulation update
    251265    m_ComponentManager.FlushDestroyedComponents();
    252266