Beco: Difference between revisions
no edit summary
imported>Leoetlino No edit summary |
imported>Leoetlino No edit summary |
||
Line 42: | Line 42: | ||
== Operations == | == Operations == | ||
=== Getting | === Getting data for a given coordinate === | ||
The algorithm that returns the custom data that is associated with a coordinate is very simple. It consists of determining the correct row index in the table, then iterating over segments in that row and returning the segment data when the X coordinate is within its bounds. | |||
For the reference, here is the official, mostly unreversed function<ref>0x7100E41C40 in Switch 1.5.0</ref> that implements the aforementioned algorithm: | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
Line 127: | Line 127: | ||
} | } | ||
return _entry->value; | return _entry->value; | ||
} | |||
</syntaxhighlight> | |||
A cleaner version of this algorithm is given below: | |||
<syntaxhighlight lang="c++"> | |||
unsigned int eco::getCurrentAreaNum(float posX, float posZ, Ecosystem* unused, EcoMapInfo* info) | |||
{ | |||
posX = std::clamp(posX, -5000.0, 4999.0); | |||
posZ = std::clamp(posZ, -4000.0, 4000.0); | |||
float epsilon1 = (posX + 5000.0 < 0.0) ? -0.5 : 0.5; | |||
float epsilon2 = (posZ + 4000.0 < 0.0) ? -0.5 : 0.5; | |||
int x = posX + 5000.0 + epsilon1; | |||
int z = (posZ + 4000.0 + epsilon2) / info->header->divisor; | |||
uint row = std::clamp(z, 0, info->header->numRows - 2); | |||
if (divisor == 10) | |||
x = x / 10 + ((0x66666667LL * x) >> 0x3F); | |||
uint* offsets = &info->rowOffsets[row]; | |||
if ( offsets[0] >= offsets[1] ) | |||
return 0xFFFFFFFF; | |||
Segment* segment = reinterpret_cast<Segment*>((char *)info->rows + 2 * offsets[0]); | |||
Segment* segmentEnd = reinterpret_cast<Segment*>((char *)info->rows + 2 * offsets[1]); | |||
uint totalLength = 0; | |||
while (true) | |||
{ | |||
totalLength += segment->length; | |||
if (x < totalLength) | |||
break; | |||
++segment; | |||
if (segment >= segmentEnd) | |||
return 0xFFFFFFFF; | |||
} | |||
return segment->value; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |