Skip to content

Commit 5c82639

Browse files
committed
Fixed: Sector indexing issue
1 parent e74d51d commit 5c82639

File tree

10 files changed

+128
-96
lines changed

10 files changed

+128
-96
lines changed

Changelog.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4063,9 +4063,10 @@ When setting a property like MORE to the a spell or skill defname, trying to rea
40634063
30-09-2025, Mulambo
40644064
- Changed: Login rejection (packet `0x82`) is now sent to all clients trying to log in (used to be only to clients, that Sphere could identify).
40654065

4066-
30-10-2025, Nolok
4066+
03-11-2025, Nolok
40674067
- Fixed: Corner cases issues with number parsing from scripts.
40684068
- Fixed: Function call stack messed up ordering.
40694069
- Fixed: Wrong script line pointed to in console log messages.
40704070
- Fixed: Changing Char flags didn't always trigger a full update packet.
4071+
- Fixed: Sector indexing issue.
40714072
- Changed: Made both Windows and Linux load scripts in a folder in alphabetical order.

src/game/CRegion.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void CRegion::UnRealizeRegion()
5454
if ( pSector == nullptr )
5555
break;
5656
// Does the rect overlap ?
57-
if ( ! IsOverlapped( pSector->GetRect()))
57+
if ( ! IsOverlapped( pSector->GetRectWorldUnits()))
5858
continue;
5959
if ( pSector->UnLinkRegion( this ))
6060
--m_iLinkedSectors;
@@ -80,9 +80,9 @@ bool CRegion::RealizeRegion()
8080
{
8181
CSector *pSector = pSectors.GetSectorByIndexUnchecked(m_pt.m_map, i);
8282

83-
if ( pSector && IsOverlapped(pSector->GetRect()) )
83+
if ( pSector && IsOverlapped(pSector->GetRectWorldUnits()) )
8484
{
85-
// Yes, this sector overlapped, so add it to the sector list
85+
// Yes, this sector is overlapped, so add it to the sector list
8686
if ( !pSector->LinkRegion(this) )
8787
{
8888
g_Log.EventError("Linking sector #%d (map %d) for region %s failed (fatal for this region).\n", i, int(m_pt.m_map), GetName());
@@ -109,6 +109,12 @@ bool CRegion::AddRegionRect( const CRectMap & rect )
109109
return true;
110110
}
111111

112+
bool CRegion::SetRegionRect( const CRectMap & rect )
113+
{
114+
EmptyRegion();
115+
return AddRegionRect( rect );
116+
}
117+
112118
void CRegion::SetName( lpctstr pszName )
113119
{
114120
ADDTOCALLSTACK("CRegion::SetName");
@@ -692,6 +698,14 @@ void CRegion::r_Write( CScript &s )
692698
r_WriteBase( s );
693699
}
694700

701+
void CRegion::TogRegionFlags( dword dwFlags, bool fSet ) noexcept
702+
{
703+
if ( fSet )
704+
m_dwFlags |= dwFlags;
705+
else
706+
m_dwFlags &= ~dwFlags;
707+
SetModified( REGMOD_FLAGS );
708+
}
695709

696710
bool CRegion::IsGuarded() const
697711
{
@@ -841,7 +855,7 @@ bool CRegion::SendSectorsVerb( lpctstr pszVerb, lpctstr pszArgs, CTextConsole *
841855
break;
842856

843857
// Does the rect overlap ?
844-
if ( IsOverlapped( pSector->GetRect() ) )
858+
if ( IsOverlapped( pSector->GetRectWorldUnits() ) )
845859
{
846860
CScript script( pszVerb, pszArgs );
847861
fRet |= pSector->r_Verb( script, pSrc );

src/game/CRegion.h

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,17 @@ class CRegion : public CResourceDef, public CRegionBase
6262
public:
6363
static const char *m_sClassName;
6464
CPointMap m_pt; // safe point in the region. (for teleporting to)
65-
int m_iLinkedSectors; // just for statistics tracking. How many sectors are linked ?
65+
int m_iLinkedSectors; // just for statistics tracking. How many sectors are linked ?
6666
dword m_dwModifiedFlags;
67+
CItemMulti* _pMultiLink; // Does this region belong to a multi?
6768

6869
static lpctstr const sm_szLoadKeys[];
6970
static lpctstr const sm_szTrigName[RTRIG_QTY+1];
7071
static lpctstr const sm_szVerbKeys[];
7172

72-
CResourceRefArray m_Events; // trigger [REGION x] when entered or exited RES_REGIONTYPE
73-
CVarDefMap m_TagDefs; // attach extra tags here.
73+
CResourceRefArray m_Events; // trigger [REGION x] when entered or exited RES_REGIONTYPE
74+
CVarDefMap m_TagDefs; // attach extra tags here.
7475
CVarDefMap m_BaseDefs; // New Variable storage system
75-
CItemMulti* _pMultiLink; // Does this region belong to a multi?
7676

7777
TRIGRET_TYPE OnRegionTrigger( CTextConsole * pChar, RTRIG_TYPE trig );
7878

@@ -106,8 +106,6 @@ class CRegion : public CResourceDef, public CRegionBase
106106
bool SendSectorsVerb( lpctstr pszVerb, lpctstr pszArgs, CTextConsole * pSrc ); // distribute to the CSectors
107107

108108
public:
109-
virtual bool RealizeRegion();
110-
void UnRealizeRegion();
111109
#define REGMOD_FLAGS 0x0001
112110
#define REGMOD_EVENTS 0x0002
113111
#define REGMOD_TAGS 0x0004
@@ -134,39 +132,33 @@ class CRegion : public CResourceDef, public CRegionBase
134132
virtual bool r_Verb( CScript & s, CTextConsole * pSrc ) override; // Execute command from script
135133
virtual void r_Write( CScript & s );
136134

135+
virtual bool IsValid() const noexcept
136+
{
137+
return m_sName.IsValid();
138+
}
139+
140+
virtual bool RealizeRegion();
141+
void UnRealizeRegion();
142+
137143
virtual bool AddRegionRect( const CRectMap & rect ) override;
138-
bool SetRegionRect( const CRectMap & rect )
139-
{
140-
EmptyRegion();
141-
return AddRegionRect( rect );
142-
}
143-
inline dword GetRegionFlags() const noexcept
144+
bool SetRegionRect( const CRectMap & rect );
145+
146+
inline dword GetRegionFlags() const noexcept
144147
{
145148
return m_dwFlags;
146149
}
147-
bool IsFlag( dword dwFlags ) const noexcept
150+
inline bool IsFlag( dword dwFlags ) const noexcept
148151
{
149-
return (( m_dwFlags & dwFlags ) ? true : false );
152+
return (bool( m_dwFlags & dwFlags ));
150153
}
151-
bool IsGuarded() const;
152-
void SetRegionFlags( dword dwFlags ) noexcept
154+
inline void SetRegionFlags( dword dwFlags ) noexcept
153155
{
154156
m_dwFlags |= dwFlags;
155157
}
156-
void TogRegionFlags( dword dwFlags, bool fSet ) noexcept
157-
{
158-
if ( fSet )
159-
m_dwFlags |= dwFlags;
160-
else
161-
m_dwFlags &= ~dwFlags;
162-
SetModified( REGMOD_FLAGS );
163-
}
158+
void TogRegionFlags( dword dwFlags, bool fSet ) noexcept;
164159

165-
bool CheckAntiMagic( SPELL_TYPE spell ) const;
166-
virtual bool IsValid() const noexcept
167-
{
168-
return m_sName.IsValid();
169-
}
160+
bool IsGuarded() const;
161+
bool CheckAntiMagic( SPELL_TYPE spell ) const;
170162

171163
bool MakeRegionDefname();
172164

src/game/CRegionBase.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ CRegionBase::CRegionBase()
1010
m_rectUnion.SetRectEmpty();
1111
}
1212

13+
void CRegionBase::EmptyRegion()
14+
{
15+
m_rectUnion.SetRectEmpty();
16+
m_Rects.clear();
17+
}
18+
1319
size_t CRegionBase::GetRegionRectCount() const
1420
{
1521
ADDTOCALLSTACK("CRegionBase::GetRegionRectCount");

src/game/CRegionBase.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ class CRegionBase
2323
{
2424
return m_rectUnion.IsRectEmpty();
2525
}
26-
void EmptyRegion()
27-
{
28-
m_rectUnion.SetRectEmpty();
29-
m_Rects.clear();
30-
}
26+
void EmptyRegion();
3127
size_t GetRegionRectCount() const;
3228
CRectMap & GetRegionRect(size_t i);
3329
const CRectMap & GetRegionRect(size_t i) const;
@@ -52,9 +48,8 @@ class CRegionBase
5248
CRegionBase();
5349
virtual ~CRegionBase() = default;
5450

55-
private:
56-
CRegionBase(const CRegionBase& copy);
57-
CRegionBase& operator=(const CRegionBase& other);
51+
CRegionBase(const CRegionBase& copy) = delete;
52+
CRegionBase& operator=(const CRegionBase& other) = delete;
5853
};
5954

6055

src/game/CSector.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ void CSector::r_Write()
434434
if ( m_fSaveParity == g_World.m_fSaveParity )
435435
return; // already saved.
436436

437-
CPointMap const& pt = m_BasePoint;
437+
CPointMap const& pt = m_BasePointSectUnits;
438438

439439
m_fSaveParity = g_World.m_fSaveParity;
440440
bool fHeaderCreated = false;
@@ -615,23 +615,23 @@ int CSector::GetLocalTime() const
615615
{
616616
ADDTOCALLSTACK("CSector::GetLocalTime");
617617
// Get local time of the day (in minutes)
618+
const CPointMap& pt = m_BasePointSectUnits;
618619
const CSectorList& pSectors = CSectorList::Get();
619-
const CPointMap& pt = m_BasePoint;
620-
int64 iLocalTime = CWorldGameTime::GetCurrentTimeInGameMinutes();
620+
const MapSectorsData& sd = pSectors.GetMapSectorDataUnchecked(pt.m_map);
621+
int64 iLocalTime = CWorldGameTime::GetCurrentTimeInGameMinutes();
621622

622623
if ( !g_Cfg.m_fAllowLightOverride )
623624
{
624-
iLocalTime += ( pt.m_x * 24*60 ) / g_MapList.GetMapSizeX(pt.m_map);
625+
iLocalTime += ( pt.m_x * 24*60 ) / sd.iSectorColumns;
625626
}
626627
else
627628
{
628-
const MapSectorsData& sd = pSectors.GetMapSectorDataUnchecked(pt.m_map);
629-
630629
// Time difference between adjacent sectors in minutes
631630
const int iSectorTimeDiff = (24*60) / sd.iSectorColumns;
632631

633632
// Calculate the # of columns between here and Castle Britannia ( x = 1400 )
634-
const int iSectorOffset = ( pt.m_x / sd.iSectorSize);
633+
// TODO: This code doesn't actually do that...
634+
const int iSectorOffset = pt.m_x;
635635

636636
// Calculate the time offset from global time
637637
const int iTimeOffset = iSectorOffset * iSectorTimeDiff;
@@ -835,8 +835,9 @@ void CSector::SetLight( int light )
835835
void CSector::SetDefaultWeatherChance()
836836
{
837837
ADDTOCALLSTACK("CSector::SetDefaultWeatherChance");
838-
CPointMap const& pt = m_BasePoint;
839-
byte iPercent = (byte)(IMulDiv( pt.m_y, 100, g_MapList.GetMapSizeY(pt.m_map) )); // 100 = south
838+
const CSectorList& pSectors = CSectorList::Get();
839+
const MapSectorsData& sd = pSectors.GetMapSectorDataUnchecked(m_BasePointSectUnits.m_map);
840+
byte iPercent = (byte)(IMulDiv( m_BasePointSectUnits.m_y, 100, sd.iSectorRows )); // 100 = south
840841
if ( iPercent < 50 )
841842
{
842843
// Anywhere north of the Britain Moongate is a good candidate for snow
@@ -949,7 +950,7 @@ bool CSector::IsInDungeon() const
949950
ADDTOCALLSTACK("CSector::IsInDungeon");
950951
// What part of the maps are filled with dungeons.
951952
// Used for light / weather calcs.
952-
CRegion *pRegion = GetRegion(m_BasePoint, REGION_TYPE_AREA);
953+
CRegion *pRegion = GetRegion(GetBasePointMapUnits(), REGION_TYPE_AREA);
953954

954955
return ( pRegion && pRegion->IsFlag(REGION_FLAG_UNDERGROUND) );
955956
}
@@ -1122,7 +1123,7 @@ void CSector::RespawnDeadNPCs()
11221123
{
11231124
ADDTOCALLSTACK("CSector::RespawnDeadNPCs");
11241125
// skip sectors in unsupported maps
1125-
if ( !g_MapList.IsMapSupported(m_BasePoint.m_map) )
1126+
if ( !g_MapList.IsMapSupported(m_BasePointSectUnits.m_map) )
11261127
return;
11271128

11281129
// Respawn dead NPCs
@@ -1201,7 +1202,7 @@ bool CSector::_OnTick()
12011202
*/
12021203

12031204
// do not tick sectors on maps not supported by server
1204-
if ( !g_MapList.IsMapSupported(m_BasePoint.m_map) )
1205+
if ( !g_MapList.IsMapSupported(m_BasePointSectUnits.m_map) )
12051206
return true;
12061207

12071208
EXC_TRY("_OnTick");
@@ -1337,9 +1338,10 @@ bool CSector::_OnTick()
13371338
EXC_CATCHSUB("Sector");
13381339

13391340
EXC_DEBUGSUB_START;
1340-
CPointMap const& pt = m_BasePoint;
1341+
CPointMap const& pt = m_BasePointSectUnits;
13411342
g_Log.EventDebug("#0 char 0%x '%s'\n", (dword)(pChar->GetUID()), pChar->GetName());
13421343
g_Log.EventDebug("#0 sector #%d [%d,%d,%d,%d]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map);
1344+
// TODO: add rect cords?
13431345
EXC_DEBUGSUB_END;
13441346
}
13451347

@@ -1348,8 +1350,9 @@ bool CSector::_OnTick()
13481350
_SetTimeout(SECTOR_TICKING_PERIOD); // Sector is Awake, make it tick after 30 seconds.
13491351

13501352
EXC_DEBUG_START;
1351-
CPointMap const& pt = m_BasePoint;
1353+
CPointMap const& pt = m_BasePointSectUnits;
13521354
g_Log.EventError("#4 sector #%d [%hd,%hd,%hhd,%hhu]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map);
1355+
// TODO: add rect coords?
13531356
EXC_DEBUG_END;
13541357
return true;
13551358
}
@@ -1422,7 +1425,7 @@ bool CSector::CheckItemComplexity() const noexcept
14221425
const size_t uiCount = GetItemComplexity();
14231426
if (uiCount > g_Cfg.m_iMaxSectorComplexity)
14241427
{
1425-
g_Log.Event(LOGL_WARN, "%" PRIuSIZE_T " items at %s. Sector too complex!\n", uiCount, m_BasePoint.WriteUsed());
1428+
g_Log.Event(LOGL_WARN, "%" PRIuSIZE_T " items at %s. Sector too complex!\n", uiCount, GetBasePointMapUnits().WriteUsed());
14261429
return true;
14271430
}
14281431
return false;
@@ -1473,7 +1476,7 @@ bool CSector::CheckCharComplexity() const noexcept
14731476
const size_t uiCount = GetCharComplexity();
14741477
if (uiCount > g_Cfg.m_iMaxCharComplexity)
14751478
{
1476-
g_Log.Event(LOGL_WARN, "%" PRIuSIZE_T " chars at %s. Sector too complex!\n", uiCount, m_BasePoint.WriteUsed());
1479+
g_Log.Event(LOGL_WARN, "%" PRIuSIZE_T " chars at %s. Sector too complex!\n", uiCount, GetBasePointMapUnits().WriteUsed());
14771480
return true;
14781481
}
14791482
return false;

src/game/CSectorList.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ void CSectorList::Init()
3131

3232
for (int iMap = 0; iMap < MAP_SUPPORTED_QTY; ++iMap)
3333
{
34-
/*
35-
Before iSectorIndex was declared and set to 0 outside the FOR, so I moved it inside because
36-
we need to (re)set iSectorIndex to 0 when Sphere finish to initialize every sectors in a map, otherwise
37-
iSectorIndex will have the same value of iSectorQty when Sphere finish loading map0.
38-
*/
39-
int iSectorIndex = 0;
40-
4134
MapSectorsData& sd = _SectorData[iMap];
4235
sd.iSectorSize = sd.iSectorColumns = sd.iSectorRows = sd.iSectorQty = 0;
4336
sd._pSectors.reset();
@@ -69,9 +62,9 @@ void CSectorList::Init()
6962

7063

7164
short iSectorX = 0, iSectorY = 0;
72-
for (; iSectorIndex < iSectorQty; ++iSectorIndex)
65+
for (int iSectorIndex = 0; iSectorIndex < iSectorQty; ++iSectorIndex)
7366
{
74-
// Map sectors are added in row-major order (fill a column, then increment row count and fill columns at that row, and so on).
67+
// Map sectors are added in row-major order (fill every row for a column, then increment column index and fill its rows, and so on).
7568
if (iSectorY >= iMaxY)
7669
{
7770
iSectorY = 0;
@@ -179,11 +172,11 @@ CSector* CSectorList::GetSectorByCoordsUnchecked(int map, short x, short y) cons
179172
if ((xSect >= sd.iSectorColumns) || (ySect >= sd.iSectorRows))
180173
return nullptr;
181174
182-
const int index = ((ySect * sd.iSectorColumns) + xSect);
175+
const int index = ((xSect * sd.iSectorRows) + ySect);
183176
return (index < sd.iSectorQty) ? &(sd._pSectors[index]) : nullptr;
184177
#else
185178
*/
186-
const int index = ((ySect * sd.iSectorColumns) + xSect);
179+
const int index = ((xSect * sd.iSectorRows) + ySect);
187180
DEBUG_ASSERT(index < sd.iSectorQty);
188181
return &(sd._pSectors[index]);
189182
//#endif

0 commit comments

Comments
 (0)