Ticket #3334: t3334_precise_territory_radius_v3.patch

File t3334_precise_territory_radius_v3.patch, 4.0 KB (added by elexis, 9 years ago)

Uses u16 for radius as that value should be smaller than 1000. Thus we can safely multiply it 28 without causing overflows.

  • source/simulation2/components/CCmpTerritoryInfluence.cpp

     
    1818#include "precompiled.h"
    1919
    2020#include "simulation2/system/Component.h"
    2121#include "ICmpTerritoryInfluence.h"
    2222
     23#include "ps/CLogger.h"
    2324#include "simulation2/components/ICmpOwnership.h"
    2425#include "simulation2/components/ICmpPlayerManager.h"
    2526#include "simulation2/components/ICmpValueModificationManager.h"
    2627
    2728class CCmpTerritoryInfluence : public ICmpTerritoryInfluence
    public:  
    3334
    3435    DEFAULT_COMPONENT_ALLOCATOR(TerritoryInfluence)
    3536
    3637    bool m_Root;
    3738    u16 m_Weight;
    38     u32 m_Radius;
     39    u16 m_Radius;
    3940
    4041    static std::string GetSchema()
    4142    {
    4243        return
    4344            "<element name='Root'>"
    public:  
    4748                "<data type='nonNegativeInteger'>"
    4849                    "<param name='maxInclusive'>65535</param>" // Max u16 value
    4950                "</data>"
    5051            "</element>"
    5152            "<element name='Radius'>"
    52                 "<data type='nonNegativeInteger'/>"
     53                "<data type='nonNegativeInteger'>"
     54                    "<param name='maxInclusive'>65535</param>" // Max u16 value
     55                "</data>"
    5356            "</element>";
    5457    }
    5558
    5659    virtual void Init(const CParamNode& paramNode)
    5760    {
    5861        m_Root = paramNode.GetChild("Root").ToBool();
    5962        m_Weight = (u16)paramNode.GetChild("Weight").ToInt();
    60         m_Radius = paramNode.GetChild("Radius").ToInt();
     63        m_Radius = (u16)paramNode.GetChild("Radius").ToInt();
    6164    }
    6265
    6366    virtual void Deinit()
    6467    {
    6568    }
    public:  
    8184    virtual u16 GetWeight()
    8285    {
    8386        return m_Weight;
    8487    }
    8588
    86     virtual u32 GetRadius()
     89    virtual u16 GetRadius()
    8790    {
    8891        CmpPtr<ICmpValueModificationManager> cmpValueModificationManager(GetSystemEntity());
    8992        if (!cmpValueModificationManager)
    9093            return m_Radius;
    9194
    9295        u32 newRadius = cmpValueModificationManager->ApplyModifications(L"TerritoryInfluence/Radius", m_Radius, GetEntityId());
    93         return newRadius;
     96
     97        // should be < 1000
     98        if (newRadius > std::numeric_limits<u16>::max())
     99        {
     100            newRadius = std::numeric_limits<u16>::max();
     101            LOGWARNING("Territory radius overflow for entity ID %d", GetEntityId());
     102        }
     103
     104        return (u16) newRadius;
    94105    }
    95106};
    96107
    97108REGISTER_COMPONENT_TYPE(TerritoryInfluence)
  • source/simulation2/components/CCmpTerritoryManager.cpp

    void CCmpTerritoryManager::CalculateTerr  
    438438        {
    439439            CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), ent);
    440440            if (!cmpPosition || !cmpPosition->IsInWorld())
    441441                continue;
    442442
     443            // Multiply with 2^8 to improve precision
    443444            CmpPtr<ICmpTerritoryInfluence> cmpTerritoryInfluence(GetSimContext(), ent);
    444445            u32 weight = cmpTerritoryInfluence->GetWeight();
    445             u32 radius = cmpTerritoryInfluence->GetRadius() / (Pathfinding::NAVCELL_SIZE * NAVCELLS_PER_TERRITORY_TILE).ToInt_RoundToNegInfinity();
     446            u32 radius = ((u32) cmpTerritoryInfluence->GetRadius() << 8) / (Pathfinding::NAVCELL_SIZE * NAVCELLS_PER_TERRITORY_TILE).ToInt_RoundToNegInfinity();
     447
    446448            if (weight == 0 || radius == 0)
    447449                continue;
    448             u32 falloff = weight / radius;
     450
     451            u32 falloff = (weight << 8) / radius;
    449452
    450453            CFixedVector2D pos = cmpPosition->GetPosition2D();
    451454            u16 i, j;
    452455            NearestTerritoryTile(pos.X, pos.Y, i, j, tilesW, tilesH);
    453456
  • source/simulation2/components/ICmpTerritoryInfluence.h

    class ICmpTerritoryInfluence : public IC  
    2525public:
    2626    virtual bool IsRoot() = 0;
    2727
    2828    virtual u16 GetWeight() = 0;
    2929
    30     virtual u32 GetRadius() = 0;
     30    virtual u16 GetRadius() = 0;
    3131
    3232    DECLARE_INTERFACE_TYPE(TerritoryInfluence)
    3333};
    3434
    3535#endif // INCLUDED_ICMPTERRITORYINFLUENCE