Beco: Difference between revisions

1,486 bytes added ,  5 years ago
no edit summary
imported>Leoetlino
No edit summary
imported>Leoetlino
No edit summary
Line 42: Line 42:
== Operations ==
== Operations ==


=== Getting the custom data for a given coordinate ===
=== Getting data for a given coordinate ===
{{expand section}}
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.


At 0x7100E41C40 in Switch 1.5.0:
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>
Anonymous user