impl Cron and most map.cc functions

This commit is contained in:
fusion32 2025-05-26 17:53:28 -03:00
parent fbb392953c
commit ad1f181454
5 changed files with 402 additions and 904 deletions

View File

@ -10,7 +10,7 @@
The decompiled file has ~115K lines of C. If we take ~15K lines to be rubbish, this can be round to ~100K. Considering a low estimate of 200 lines per day, the whole process could take up to 500 days which is quite a bit but not impossible. Now considering a high estimate of 1K lines per day, it could take 100 days which is also quite a bit.
## TODO AFTER FIRST PASS
- Trim some rough edges.
- Trim rough edges.
- Avoid unsafe libc functions like `strcpy`, `strncpy`, `strcat`, `sprintf` etc...
- Handle connections inline with `poll`/`epoll` (probably?).
- Remove exceptions.

View File

@ -5192,887 +5192,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
void CronMove(int Destination,int Source)
{
int iVar1;
uint uVar2;
TCronEntry *pTVar3;
TCronEntry *pTVar4;
TCronEntry *Entry;
undefined8 local_34;
int iStack_30;
pTVar3 = vector<TCronEntry>::operator()(&CronEntry,Destination);
pTVar4 = vector<TCronEntry>::operator()(&CronEntry,Source);
(pTVar3->Obj).ObjectID = (pTVar4->Obj).ObjectID;
pTVar3->RoundNr = pTVar4->RoundNr;
iVar1 = pTVar4->Next;
pTVar3->Previous = pTVar4->Previous;
pTVar3->Next = iVar1;
pTVar3 = vector<TCronEntry>::operator()(&CronEntry,Destination);
if (pTVar3->Next != -1) {
pTVar4 = vector<TCronEntry>::operator()(&CronEntry,pTVar3->Next);
pTVar4->Previous = Destination;
}
if (pTVar3->Previous != -1) {
pTVar4 = vector<TCronEntry>::operator()(&CronEntry,pTVar3->Previous);
iVar1 = pTVar3->Previous;
pTVar4->Next = Destination;
if (iVar1 != -1) {
return;
}
}
uVar2 = (pTVar3->Obj).ObjectID;
CronHashTable
[uVar2 + ((uVar2 - (int)((ulonglong)uVar2 * 0x200401 >> 0x20) >> 1) + iStack_30 >> 10) * -0x7ff]
= Destination;
return;
}
void CronHeapify(int Position)
{
int i;
TCronEntry *pTVar1;
TCronEntry *pTVar2;
int Father;
int iVar3;
while (Position != 1) {
pTVar1 = vector<TCronEntry>::operator()(&CronEntry,Position);
iVar3 = Position / 2;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,iVar3);
if (pTVar2->RoundNr <= pTVar1->RoundNr) break;
CronMove(0,Position);
CronMove(Position,iVar3);
CronMove(iVar3,0);
Position = iVar3;
}
while( true ) {
iVar3 = Position * 2;
if (CronEntries < iVar3) {
return;
}
i = iVar3 + 1;
if (i <= CronEntries) {
pTVar1 = vector<TCronEntry>::operator()(&CronEntry,i);
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,iVar3);
if (pTVar1->RoundNr < pTVar2->RoundNr) {
iVar3 = i;
}
}
pTVar1 = vector<TCronEntry>::operator()(&CronEntry,Position);
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,iVar3);
if (pTVar1->RoundNr <= pTVar2->RoundNr) break;
CronMove(0,Position);
CronMove(Position,iVar3);
CronMove(iVar3,0);
Position = iVar3;
}
return;
}
void CronSet(Object *Obj,ulong Delay)
{
bool bVar1;
int i;
TCronEntry *pTVar2;
ulong Position;
uint uVar3;
bVar1 = false;
if (Obj->ObjectID != 0) {
uVar3 = Obj->ObjectID & HashTableMask;
if (HashTableType[uVar3] == '\x02') {
UnswapSector(HashTableData[uVar3]);
}
if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
CronEntries = CronEntries + 1;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,CronEntries);
(pTVar2->Obj).ObjectID = Obj->ObjectID;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,CronEntries);
pTVar2->RoundNr = Delay + RoundNr;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,CronEntries);
pTVar2->Previous = -1;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,CronEntries);
pTVar2->Next = CronHashTable[Obj->ObjectID % 0x7ff];
i = CronEntries;
CronHashTable[Obj->ObjectID % 0x7ff] = CronEntries;
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
if (pTVar2->Next != -1) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,CronEntries);
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,pTVar2->Next);
pTVar2->Previous = CronEntries;
}
CronHeapify(CronEntries);
}
else {
error(&DAT_080f1480);
}
return;
}
void CronDelete(int Position)
{
uint uVar1;
int iVar2;
bool bVar3;
TCronEntry *pTVar4;
TCronEntry *pTVar5;
TCronEntry *Entry;
undefined8 local_1c;
int iStack_18;
bVar3 = false;
if ((0 < Position) && (Position <= CronEntries)) {
bVar3 = true;
}
if (!bVar3) {
error(&DAT_080f14c0,Position);
return;
}
pTVar4 = vector<TCronEntry>::operator()(&CronEntry,Position);
if (pTVar4->Next != -1) {
pTVar5 = vector<TCronEntry>::operator()(&CronEntry,pTVar4->Next);
pTVar5->Previous = pTVar4->Previous;
}
if (pTVar4->Previous != -1) {
pTVar5 = vector<TCronEntry>::operator()(&CronEntry,pTVar4->Previous);
iVar2 = pTVar4->Previous;
pTVar5->Next = pTVar4->Next;
if (iVar2 != -1) goto LAB_08057e24;
}
uVar1 = (pTVar4->Obj).ObjectID;
CronHashTable
[uVar1 + ((uVar1 - (int)((ulonglong)uVar1 * 0x200401 >> 0x20) >> 1) + iStack_18 >> 10) * -0x7ff]
= pTVar4->Next;
LAB_08057e24:
iVar2 = CronEntries;
CronEntries = CronEntries + -1;
if (CronEntries < Position) {
return;
}
CronMove(Position,iVar2);
CronHeapify(Position);
return;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
Object CronCheck(void)
{
Object OVar1;
TCronEntry *pTVar2;
ulong *in_stack_00000004;
OVar1.ObjectID = NONE.ObjectID;
if ((CronEntries != 0) &&
(pTVar2 = vector<TCronEntry>::operator()(&CronEntry,1), OVar1 = NONE,
pTVar2->RoundNr <= RoundNr)) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,1);
OVar1.ObjectID = (pTVar2->Obj).ObjectID;
}
*in_stack_00000004 = OVar1.ObjectID;
return (Object)(ulong)in_stack_00000004;
}
ulong CronInfo(Object *Obj,bool Delete)
{
bool bVar1;
TCronEntry *pTVar2;
int Position;
uint uVar3;
int i;
ulong uVar4;
char *Text;
undefined8 local_44;
int iStack_40;
bool Delete_local;
bVar1 = false;
if (Obj->ObjectID != 0) {
uVar3 = Obj->ObjectID & HashTableMask;
if (HashTableType[uVar3] == '\x02') {
UnswapSector(HashTableData[uVar3]);
}
if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
uVar3 = Obj->ObjectID;
i = CronHashTable
[uVar3 + ((uVar3 - (int)((ulonglong)uVar3 * 0x200401 >> 0x20) >> 1) + iStack_40 >> 10) *
-0x7ff];
while (i != -1) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
if ((pTVar2->Obj).ObjectID == Obj->ObjectID) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
uVar4 = pTVar2->RoundNr - RoundNr;
if ((int)uVar4 < 1) {
uVar4 = 1;
}
if (!Delete) {
return uVar4;
}
CronDelete(i);
return uVar4;
}
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
i = pTVar2->Next;
}
Text = "CronInfo: Objekt ist nicht im Cron-System eingetragen.\n";
}
else {
Text = &DAT_080f1540;
}
error(Text);
return 0;
}
ulong CronStop(Object *Obj)
{
bool bVar1;
ulong uVar2;
ulong Position;
uint uVar3;
Object local_1c [4];
bVar1 = false;
if (Obj->ObjectID != 0) {
uVar3 = Obj->ObjectID & HashTableMask;
if (HashTableType[uVar3] == '\x02') {
UnswapSector(HashTableData[uVar3]);
}
if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
local_1c[0] = (Object)Obj->ObjectID;
uVar2 = CronInfo(local_1c,true);
}
else {
error(&DAT_080f1580);
uVar2 = 0;
}
return uVar2;
}
void CronExpire(Object *Obj,int Delay)
{
bool bVar1;
TObject *pTVar2;
ulong Position;
uint uVar3;
Object local_3c [4];
Object local_2c [7];
bVar1 = false;
if (Obj->ObjectID != 0) {
uVar3 = Obj->ObjectID & HashTableMask;
if (HashTableType[uVar3] == '\x02') {
UnswapSector(HashTableData[uVar3]);
}
if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
local_3c[0] = (Object)Obj->ObjectID;
pTVar2 = AccessObject(local_3c);
ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
bVar1 = ObjectType::getFlag((ObjectType *)local_2c,EXPIRE);
if (bVar1) {
if (Delay == -1) {
local_2c[0] = (Object)Obj->ObjectID;
pTVar2 = AccessObject(local_2c);
ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
Delay = ObjectType::getAttribute((ObjectType *)local_3c,TOTALEXPIRETIME);
}
local_3c[0] = (Object)Obj->ObjectID;
CronSet(local_3c,Delay);
}
}
else {
error(&DAT_080f15c0);
}
return;
}
void CronChange(Object *Obj,int NewDelay)
{
bool bVar1;
TCronEntry *pTVar2;
int Position;
uint uVar3;
int i;
char *Text;
bVar1 = false;
if (Obj->ObjectID != 0) {
uVar3 = Obj->ObjectID & HashTableMask;
if (HashTableType[uVar3] == '\x02') {
UnswapSector(HashTableData[uVar3]);
}
if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
i = CronHashTable[Obj->ObjectID % 0x7ff];
while (i != -1) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
if ((pTVar2->Obj).ObjectID == Obj->ObjectID) {
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
pTVar2->RoundNr = NewDelay + RoundNr;
CronHeapify(i);
return;
}
pTVar2 = vector<TCronEntry>::operator()(&CronEntry,i);
i = pTVar2->Next;
}
Text = "CronChange: Objekt ist nicht im Cron-System eingetragen.\n";
}
else {
Text = &DAT_080f1640;
}
error(Text);
return;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
Object GetFirstSpecObject(void)
{
TObject *pTVar1;
ulong *in_stack_00000004;
int *in_stack_00000014;
Object local_5c [4];
ObjectType local_4c [4];
Object local_3c [4];
ulong local_2c;
Object Obj;
GetFirstObject();
if (local_2c != NONE.ObjectID) {
do {
local_4c[0].TypeID = NONE.ObjectID;
local_3c[0].ObjectID = local_2c;
pTVar1 = AccessObject(local_3c);
ObjectType::setTypeID(local_4c,(pTVar1->Type).TypeID);
ObjectType::setTypeID((ObjectType *)local_3c,*in_stack_00000014);
if (local_4c[0].TypeID == local_3c[0].ObjectID) {
*in_stack_00000004 = local_2c;
return (Object)(ulong)in_stack_00000004;
}
local_5c[0].ObjectID = local_2c;
pTVar1 = AccessObject(local_5c);
local_2c = (pTVar1->NextObject).ObjectID;
} while (local_2c != NONE.ObjectID);
}
*in_stack_00000004 = NONE.ObjectID;
return (Object)(ulong)in_stack_00000004;
}
bool IsOnMap(int x,int y,int z)
{
bool bVar1;
int sx;
int iVar2;
bool bVar3;
iVar2 = x + 0x1f;
if (-1 < x) {
iVar2 = x;
}
if (0x7fffffff < (uint)y) {
y = y + 0x1f;
}
bVar1 = false;
bVar3 = false;
if ((SectorXMin <= iVar2 >> 5) && (bVar1 = true, SectorXMax < iVar2 >> 5)) {
bVar1 = false;
}
if (bVar1) {
bVar1 = false;
if ((SectorYMin <= y >> 5) && (bVar1 = true, SectorYMax < y >> 5)) {
bVar1 = false;
}
if (bVar1) {
bVar1 = false;
if ((SectorZMin <= z) && (bVar1 = true, SectorZMax < z)) {
bVar1 = bVar3;
}
if (bVar1 != false) {
bVar3 = true;
}
}
}
return bVar3;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
bool CoordinateFlag(void)
{
bool bVar1;
TObject *pTVar2;
FLAG in_stack_00000010;
Object local_5c [4];
ObjectType local_4c [4];
Object local_3c [4];
ulong local_2c;
Object Obj;
GetFirstObject();
if (local_2c != NONE.ObjectID) {
do {
local_4c[0].TypeID = NONE.ObjectID;
local_3c[0].ObjectID = local_2c;
pTVar2 = AccessObject(local_3c);
ObjectType::setTypeID(local_4c,(pTVar2->Type).TypeID);
bVar1 = ObjectType::getFlag(local_4c,in_stack_00000010);
if (bVar1) {
return true;
}
local_5c[0].ObjectID = local_2c;
pTVar2 = AccessObject(local_5c);
local_2c = (pTVar2->NextObject).ObjectID;
} while (local_2c != NONE.ObjectID);
}
return false;
}
bool IsPremiumArea(int x,int y,int param_3)
{
bool bVar1;
int iVar2;
int iVar3;
iVar2 = x + 0x1f;
if (-1 < x) {
iVar2 = x;
}
iVar2 = iVar2 >> 5;
if (0x7fffffff < (uint)y) {
y = y + 0x1f;
}
bVar1 = true;
iVar3 = y >> 5;
if ((((iVar2 < 0x40c) && ((iVar2 < 0x408 || (bVar1 = true, 0x3e6 < iVar3)))) &&
((iVar2 < 0x406 || (bVar1 = true, iVar3 < 0x3f0)))) &&
(((iVar2 < 0x405 || (bVar1 = true, iVar3 < 0x3f1)) &&
((iVar2 < 0x3fe || (bVar1 = true, iVar3 < 0x3f6)))))) {
bVar1 = 0x3f7 < iVar3;
}
return bVar1;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
bool IsProtectionZone(void)
{
byte bVar1;
bool bVar2;
int in_stack_00000004;
int in_stack_00000008;
Object local_2c [4];
ulong local_1c;
Object Con;
GetMapContainer((int)&local_1c,in_stack_00000004,in_stack_00000008);
bVar2 = false;
if (local_1c != NONE.ObjectID) {
local_2c[0].ObjectID = local_1c;
bVar1 = GetMapContainerFlags(local_2c);
bVar2 = (bool)(bVar1 >> 2 & 1);
}
return bVar2;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
bool IsNoLogoutField(void)
{
byte bVar1;
bool bVar2;
int in_stack_00000004;
int in_stack_00000008;
Object local_2c [4];
ulong local_1c;
Object Con;
GetMapContainer((int)&local_1c,in_stack_00000004,in_stack_00000008);
bVar2 = false;
if (local_1c != NONE.ObjectID) {
local_2c[0].ObjectID = local_1c;
bVar1 = GetMapContainerFlags(local_2c);
bVar2 = (bool)(bVar1 >> 1 & 1);
}
return bVar2;
}
bool IsHouse(int x,int y,int z)
{
bool bVar1;
short sVar2;
TObject *pTVar3;
Object local_3c [4];
Object local_2c;
Object Con;
GetMapContainer((int)&local_2c,x,y);
local_3c[0].ObjectID = NONE.ObjectID;
if (local_2c.ObjectID != NONE.ObjectID) {
bVar1 = Object::exists(&local_2c);
if (bVar1) {
local_3c[0].ObjectID = local_2c.ObjectID;
pTVar3 = AccessObject(local_3c);
sVar2 = *(short *)((int)pTVar3->Attributes + 0xe);
goto LAB_0805b121;
}
error(&DAT_080f20a0,x,y,z);
}
sVar2 = 0;
LAB_0805b121:
return sVar2 != 0;
}
ushort GetHouseID(int x,int y,int z)
{
bool bVar1;
TObject *pTVar2;
ushort uVar3;
ulong Position;
uint uVar4;
Object local_3c [4];
uint local_2c;
Object Con;
GetMapContainer((int)&local_2c,x,y);
uVar3 = 0;
local_3c[0].ObjectID = NONE.ObjectID;
if (local_2c != NONE.ObjectID) {
bVar1 = false;
if (local_2c != 0) {
uVar4 = local_2c & HashTableMask;
if (HashTableType[uVar4] == '\x02') {
UnswapSector(HashTableData[uVar4]);
}
if ((HashTableType[uVar4] == '\x01') && (*(uint *)HashTableData[uVar4] == local_2c)) {
bVar1 = true;
}
else {
bVar1 = false;
}
}
if (bVar1) {
local_3c[0].ObjectID = local_2c;
pTVar2 = AccessObject(local_3c);
uVar3 = *(ushort *)((int)pTVar2->Attributes + 0xe);
}
else {
error(&DAT_080f20a0,x,y,z);
uVar3 = 0;
}
}
return uVar3;
}
void SetHouseID(int x,int y,int z,ushort ID)
{
bool bVar1;
bool bVar2;
ushort uVar3;
TObject *pTVar4;
int sy;
int iVar5;
int sx;
int iVar6;
ulong Position;
uint uVar7;
ushort ID_local;
uint local_2c;
Object Con;
iVar6 = x;
if (0x7fffffff < (uint)x) {
iVar6 = x + 0x1f;
}
iVar5 = y;
if (0x7fffffff < (uint)y) {
iVar5 = y + 0x1f;
}
bVar1 = false;
bVar2 = false;
if ((SectorXMin <= iVar6 >> 5) && (bVar1 = true, SectorXMax < iVar6 >> 5)) {
bVar1 = false;
}
if (bVar1) {
bVar1 = false;
if ((SectorYMin <= iVar5 >> 5) && (bVar1 = true, SectorYMax < iVar5 >> 5)) {
bVar1 = false;
}
if (bVar1) {
bVar1 = false;
if ((SectorZMin <= z) && (bVar1 = true, SectorZMax < z)) {
bVar1 = bVar2;
}
if (bVar1) {
bVar2 = true;
}
}
}
if (!bVar2) {
return;
}
iVar6 = z;
GetMapContainer((int)&local_2c,x,y);
bVar1 = false;
_ID_local = NONE.ObjectID;
if (local_2c != NONE.ObjectID) {
bVar2 = false;
if (local_2c != 0) {
uVar7 = local_2c & HashTableMask;
if (HashTableType[uVar7] == '\x02') {
UnswapSector(HashTableData[uVar7]);
}
if ((HashTableType[uVar7] == '\x01') && (*(uint *)HashTableData[uVar7] == local_2c)) {
bVar2 = true;
}
else {
bVar2 = false;
}
}
if (bVar2) goto LAB_0805b36c;
}
bVar1 = true;
LAB_0805b36c:
if (bVar1) {
print();
}
else {
uVar3 = GetHouseID(x,y,z);
if (uVar3 == 0) {
_ID_local = local_2c;
pTVar4 = AccessObject((Object *)&ID_local);
pTVar4->Attributes[3] = pTVar4->Attributes[3] + (uint)ID * 0x10000;
}
else {
error(&DAT_080f2160,y,z,iVar6);
}
}
return;
}
int GetDepotNumber(char *Town)
{
TDepotInfo *s1;
int iVar1;
int i;
int i_00;
if (Town == (char *)0x0) {
error("GetDepotNumber: Town ist NULL.\n");
}
else if ((*Town != '\0') && (i_00 = DepotInfo.min, DepotInfo.min <= DepotInfo.max)) {
do {
s1 = vector<TDepotInfo>::operator()(&DepotInfo,i_00);
iVar1 = stricmp(s1->Town,Town,-1);
if (iVar1 == 0) {
return i_00;
}
i_00 = i_00 + 1;
} while (i_00 <= DepotInfo.max);
}
return -1;
}
char * GetDepotName(int DepotNumber)
{
TDepotInfo *pTVar1;
char *Text;
if ((DepotNumber < DepotInfo.min) || (DepotInfo.max < DepotNumber)) {
Text = &DAT_080f21c0;
}
else {
pTVar1 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
if (pTVar1 != (TDepotInfo *)0x0) {
pTVar1 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
return pTVar1->Town;
}
Text = &DAT_080f2200;
}
error(Text,DepotNumber);
return "unknown";
}
// WARNING: Variable defined which should be unmapped: PremiumAccount_local
int GetDepotSize(int DepotNumber,bool PremiumAccount)
{
int iVar1;
TDepotInfo *pTVar2;
bool PremiumAccount_local;
if ((DepotNumber < DepotInfo.min) || (DepotInfo.max < DepotNumber)) {
error(&DAT_080f2240,DepotNumber);
iVar1 = 1;
}
else {
pTVar2 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
if (pTVar2->Size < 1) {
pTVar2 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
error(&DAT_080f2280,pTVar2->Size,DepotNumber);
pTVar2 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
pTVar2->Size = 1;
}
if (PremiumAccount) {
pTVar2 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
iVar1 = pTVar2->Size * 2;
}
else {
pTVar2 = vector<TDepotInfo>::operator()(&DepotInfo,DepotNumber);
iVar1 = pTVar2->Size;
}
}
return iVar1;
}
void GetStartPosition(int *x,int *y,int *z,bool Newbie)
{
int iVar1;
if (Newbie) {
*x = NewbieStartPositionX;
*y = NewbieStartPositionY;
iVar1 = NewbieStartPositionZ;
}
else {
*x = VeteranStartPositionX;
*y = VeteranStartPositionY;
iVar1 = VeteranStartPositionZ;
}
*z = iVar1;
return;
}
// WARNING: Unknown calling convention -- yet parameter storage is locked
bool GetMarkPosition(void)
{
TMark *pTVar1;
int iVar2;
int i;
int i_00;
char *in_stack_00000004;
int *in_stack_00000008;
int *in_stack_0000000c;
int *in_stack_00000010;
i_00 = 0;
if (0 < Marks) {
do {
pTVar1 = vector<TMark>::operator()(&Mark,i_00);
iVar2 = stricmp(pTVar1->Name,in_stack_00000004,-1);
if (iVar2 == 0) {
pTVar1 = vector<TMark>::operator()(&Mark,i_00);
*in_stack_00000008 = pTVar1->x;
pTVar1 = vector<TMark>::operator()(&Mark,i_00);
*in_stack_0000000c = pTVar1->y;
pTVar1 = vector<TMark>::operator()(&Mark,i_00);
*in_stack_00000010 = pTVar1->z;
return true;
}
i_00 = i_00 + 1;
} while (i_00 < Marks);
}
return false;
}
void RefreshSector(int x,int y,int z,TReadStream *Stream)
{

View File

@ -38,8 +38,6 @@ static int CronHashTable[2047];
static int CronEntries;
static vector<TDepotInfo> DepotInfo(0, 4, 5);
static int Depots;
static vector<TMark> Mark(0, 4, 5);
static int Marks;
@ -142,6 +140,204 @@ void Object::setAttribute(INSTANCEATTRIBUTE Attribute, uint32 Value){
AccessObject(*this)->Attributes[AttributeOffset] = Value;
}
// Cron Management
// =============================================================================
static void CronMove(int Destination, int Source){
TCronEntry *DestEntry = CronEntry.at(Destination);
*DestEntry = *CronEntry.at(Source);
if(DestEntry->Next != -1){
CronEntry.at(DestEntry->Next)->Previous = Destination;
}
if(DestEntry->Previous != -1){
CronEntry.at(DestEntry->Previous)->Next = Destination;
}else{
CronHashTable[DestEntry->Obj.ObjectID % NARRAY(CronHashTable)] = Destination;
}
}
static void CronHeapify(int Position){
while(Position > 1){
int Parent = Position / 2;
TCronEntry *CurrentEntry = CronEntry.at(Position);
TCronEntry *ParentEntry = CronEntry.at(Parent);
if(ParentEntry->RoundNr <= CurrentEntry->RoundNr){
break;
}
// NOTE(fusion): This is emulating a swap, using position 0 as the
// temporary value. It is needed to maintain hash table links valid.
CronMove(0, Position);
CronMove(Position, Parent);
CronMove(Parent, 0);
Position = Parent;
}
// IMPORTANT(fusion): This is different from `priority_queue::deleteMin` as
// the last element is still in the heap and needs to be considered.
int Last = CronEntries;
while(true){
int Smallest = Position * 2;
if(Smallest > Last){
break;
}
TCronEntry *SmallestEntry = CronEntry.at(Smallest);
if((Smallest + 1) <= Last){
TCronEntry *OtherEntry = CronEntry.at(Smallest + 1);
if(OtherEntry->RoundNr < SmallestEntry->RoundNr){
SmallestEntry = OtherEntry;
Smallest += 1;
}
}
TCronEntry *CurrentEntry = CronEntry.at(Position);
if(CurrentEntry->RoundNr <= SmallestEntry->RoundNr){
break;
}
// NOTE(fusion): Same in the first loop.
CronMove(0, Position);
CronMove(Position, Smallest);
CronMove(Smallest, 0);
Position = Smallest;
}
}
static void CronSet(Object Obj, uint32 Delay){
if(!Obj.exists()){
error("CronSet: Übergebenes Objekt existiert nicht.\n");
return;
}
// TODO(fusion): We don't check if the object is already in the table.
CronEntries += 1;
int Position = CronEntries;
TCronEntry *Entry = CronEntry.at(Position);
Entry->Obj = Obj;
Entry->RoundNr = RoundNr + Delay;
Entry->Previous = -1;
Entry->Next = CronHashTable[Obj.ObjectID % NARRAY(CronHashTable)];
if(Entry->Next != -1){
CronEntry.at(Entry->Next)->Previous = Position;
}
CronHeapify(Position);
}
static void CronDelete(int Position){
if(Position < 1 || Position > CronEntries){
error("CronDelete: Ungültige Position %d.\n", Position);
return;
}
TCronEntry *Entry = CronEntry.at(Position);
if(Entry->Next != -1){
CronEntry.at(Entry->Next)->Previous = Entry->Previous;
}
if(Entry->Previous != -1){
CronEntry.at(Entry->Previous)->Next = Entry->Next;
}else{
CronHashTable[Entry->Obj.ObjectID % NARRAY(CronHashTable)] = Entry->Next;
}
int Last = CronEntries;
CronEntries -= 1;
if(Position != Last){
CronMove(Position, Last);
CronHeapify(Position);
}
}
Object CronCheck(void){
Object Obj = NONE;
if(CronEntries != 0){
TCronEntry *Entry = CronEntry.at(1);
if(Entry->RoundNr <= RoundNr){
Obj = Entry->Obj;
}
}
return Obj;
}
void CronExpire(Object Obj, int Delay){
if(!Obj.exists()){
error("CronExpire: Übergebenes Objekt existiert nicht.\n");
return;
}
ObjectType ObjType = Obj.getObjectType();
if(ObjType.getFlag(EXPIRE)){
if(Delay == -1){
CronSet(Obj, ObjType.getAttribute(TOTALEXPIRETIME));
}else{
CronSet(Obj, (uint32)Delay);
}
}
}
void CronChange(Object Obj, int NewDelay){
if(!Obj.exists()){
error("CronChange: Übergebenes Objekt existiert nicht.\n");
return;
}
int Position = CronHashTable[Obj.ObjectID % NARRAY(CronHashTable)];
while(Position != -1){
TCronEntry *Entry = CronEntry.at(Position);
if(Entry->Obj == Obj){
Entry->RoundNr = RoundNr + NewDelay;
CronHeapify(Position);
return;
}
Position = Entry->Next;
}
error("CronChange: Objekt ist nicht im Cron-System eingetragen.\n");
}
uint32 CronInfo(Object Obj, bool Delete){
if(!Obj.exists()){
error("CronInfo: Übergebenes Objekt existiert nicht.\n");
return 0;
}
int Position = CronHashTable[Obj.ObjectID % NARRAY(CronHashTable)];
while(Position != -1){
TCronEntry *Entry = CronEntry.at(Position);
if(Entry->Obj == Obj){
uint32 Remaining = 1;
if(Entry->RoundNr < RoundNr){
Remaining = Entry->RoundNr - RoundNr;
}
if(Delete){
CronDelete(Position);
}
return Remaining;
}
Position = Entry->Next;
}
error("CronInfo: Objekt ist nicht im Cron-System eingetragen.\n");
return 0;
}
uint32 CronStop(Object Obj){
if(!Obj.exists()){
error("CronStop: Übergebenes Objekt existiert nicht.\n");
return 0;
}
return CronInfo(Obj, true);
}
// Map Management
// =============================================================================
static void ReadMapConfig(void){
@ -161,7 +357,6 @@ static void ReadMapConfig(void){
VeteranStartPositionZ = 0;
HashTableSize = 0x100000;
Marks = 0;
Depots = 0;
char FileName[4096];
snprintf(FileName, sizeof(FileName), "%s/map.dat", DATAPATH);
@ -1772,6 +1967,17 @@ Object GetFirstObject(int x, int y, int z){
}
}
Object GetFirstSpecObject(int x, int y, int z, ObjectType Type){
Object Obj = GetFirstObject(x, y, z);
while(Obj != NONE){
if(Obj.getObjectType() == Type){
break;
}
Obj = Obj.getNextObject();
}
return NONE;
}
uint8 GetMapContainerFlags(Object Obj){
if(!Obj.exists() || !Obj.getObjectType().isMapContainer()){
error("GetMapContainerFlags: Objekt ist kein MapContainer.\n");
@ -1810,3 +2016,174 @@ void GetObjectCoordinates(Object Obj, int *x, int *y, int *z){
// holds its house id.
*z = AccessObject(Obj)->Attributes[3] & 0xFF;
}
bool CoordinateFlag(int x, int y, int z, FLAG Flag){
bool Result = false;
Object Obj = GetFirstObject(x, y, z);
while(Obj != NONE){
if(Obj.getObjectType().getFlag(Flag)){
Result = true;
break;
}
Obj = Obj.getNextObject();
}
return Result;
}
bool IsOnMap(int x, int y, int z){
int SectorX = x / 32;
int SectorY = y / 32;
int SectorZ = z;
return SectorXMin <= SectorX && SectorX <= SectorXMax
&& SectorYMin <= SectorY && SectorY <= SectorYMax
&& SectorZMin <= SectorZ && SectorZ <= SectorZMax;
}
bool IsPremiumArea(int x, int y, int z){
int SectorX = x / 32;
int SectorY = y / 32;
// TODO(fusion): This is checking if the position lies within certain bounding
// boxes but it is difficult to unwind the condition due to optimizations. The
// best way to understand the outline of the region is to plot this function.
bool Result = true;
if(SectorX < 0x40C
&& (SectorX < 0x408 || SectorY > 0x3E6)
&& (SectorX < 0x406 || SectorY < 0x3F0)
&& (SectorX < 0x405 || SectorY < 0x3F1)
&& (SectorX < 0x3FE || SectorY < 0x3F6)){
Result = SectorY > 0x3F7;
}
return Result;
}
bool IsNoLogoutField(int x, int y, int z){
bool Result = false;
Object Con = GetMapContainer(x, y, z);
if(Con != NONE){
Result = (GetMapContainerFlags(Con) & 0x02) != 0;
}
return Result;
}
bool IsProtectionZone(int x, int y, int z){
bool Result = false;
Object Con = GetMapContainer(x, y, z);
if(Con != NONE){
Result = (GetMapContainerFlags(Con) & 0x04) != 0;
}
return Result;
}
bool IsHouse(int x, int y, int z){
return GetHouseID(x, y, z) != 0;
}
uint16 GetHouseID(int x, int y, int z){
Object Con = GetMapContainer(x, y, z);
if(Con == NONE){
return 0;
}
if(!Con.exists()){
error("GetHouseID: Kartencontainer für Punkt [%d,%d,%d] existiert nicht.\n", x, y, z);
return 0;
}
// NOTE(fusion): See note in `GetObjectCoordinates`.
return (uint16)(AccessObject(Con)->Attributes[3] >> 16);
}
void SetHouseID(int x, int y, int z, uint16 ID){
if(!IsOnMap(x, y, z)){
return;
}
Object Con = GetMapContainer(x, y, z);
if(Con == NONE || !Con.exists()){
error("SetHouseID: Kartencontainer für Punkt [%d,%d,%d] existiert nicht.\n", x, y, z);
return;
}
// NOTE(fusion): See note in `GetObjectCoordinates`.
uint16 PrevID = (uint16)(AccessObject(Con)->Attributes[3] >> 16);
if(PrevID != 0){
error("SetHouseID: Feld [%d,%d,%d] gehört schon zu einem Haus.\n", x, y, z);
return;
}
AccessObject(Con)->Attributes[3] |= ((uint32)ID << 16);
}
int GetDepotNumber(const char *Town){
if(Town == NULL){
error("GetDepotNumber: Town ist NULL.\n");
return -1;
}
for(int DepotNumber = DepotInfo.min;
DepotNumber <= DepotInfo.max;
DepotNumber += 1){
if(stricmp(DepotInfo.at(DepotNumber)->Town, Town) == 0){
return DepotNumber;
}
}
return -1;
}
const char *GetDepotName(int DepotNumber){
if(DepotNumber < DepotInfo.min || DepotNumber > DepotInfo.max){
error("GetDepotName: Ungültiger Name für Depot %d.\n", DepotNumber);
return "unknown";
}
return DepotInfo.at(DepotNumber)->Town;
}
int GetDepotSize(int DepotNumber, bool PremiumAccount){
if(DepotNumber < DepotInfo.min || DepotNumber > DepotInfo.max){
error("GetDepotSize: Ungültige Depotnummer %d.\n", DepotNumber);
return 1;
}
TDepotInfo *Info = DepotInfo.at(DepotNumber);
if(Info->Size < 1){
error("GetDepotSize: Ungültige Depotgröße %d für Depot %d.\n", Info->Size, DepotNumber);
Info->Size = 1;
}
int Size = Info->Size;
if(PremiumAccount){
Size *= 2;
}
return Size;
}
bool GetMarkPosition(const char *Name, int *x, int *y, int *z){
bool Result = false;
for(int i = 0; i < Marks; i += 1){
TMark *MarkPointer = Mark.at(i);
if(stricmp(MarkPointer->Name, Name) == 0){
*x = MarkPointer->x;
*y = MarkPointer->y;
*z = MarkPointer->z;
Result = true;
break;
}
}
return Result;
}
void GetStartPosition(int *x, int *y, int *z, bool Newbie){
if(Newbie){
*x = NewbieStartPositionX;
*y = NewbieStartPositionY;
*z = NewbieStartPositionZ;
}else{
*x = VeteranStartPositionX;
*y = VeteranStartPositionY;
*z = VeteranStartPositionZ;
}
}

View File

@ -99,6 +99,13 @@ struct TCronEntry {
int Next;
};
// NOTE(fusion): Cron management functions. Most for internal use.
Object CronCheck(void);
void CronExpire(Object Obj, int Delay);
void CronChange(Object Obj, int NewDelay);
uint32 CronInfo(Object Obj, bool Delete);
uint32 CronStop(Object Obj);
// NOTE(fusion): Map management functions. Most for internal use.
void SwapObject(TWriteBinaryFile *File, Object Obj, uint32 FileNumber);
void SwapSector(void);
@ -140,21 +147,21 @@ Object GetContainerObject(Object Con, int Index);
Object GetMapContainer(int x, int y, int z);
Object GetMapContainer(Object Obj);
Object GetFirstObject(int x, int y, int z);
//GetFirstSpecObject
Object GetFirstSpecObject(int x, int y, int z, ObjectType Type);
uint8 GetMapContainerFlags(Object Obj);
//CoordinateFlag
void GetObjectCoordinates(Object Obj, int *x, int *y, int *z);
//IsOnMap
//IsPremiumArea
//IsProtectionZone
//IsNoLogoutField
//IsHouse
//GetHouseID
//SetHouseID
//GetDepotNumber
//GetDepotName
//GetDepotSize
//GetStartPosition
//GetMarkPosition
bool CoordinateFlag(int x, int y, int z, FLAG Flag);
bool IsOnMap(int x, int y, int z);
bool IsPremiumArea(int x, int y, int z);
bool IsNoLogoutField(int x, int y, int z);
bool IsProtectionZone(int x, int y, int z);
bool IsHouse(int x, int y, int z);
uint16 GetHouseID(int x, int y, int z);
void SetHouseID(int x, int y, int z, uint16 ID);
int GetDepotNumber(const char *Town);
const char *GetDepotName(int DepotNumber);
int GetDepotSize(int DepotNumber, bool PremiumAccount);
bool GetMarkPosition(const char *Name, int *x, int *y, int *z);
void GetStartPosition(int *x, int *y, int *z, bool Newbie);
#endif //TIBIA_MAP_HH_

View File

@ -22,16 +22,11 @@ extern void Change(Object Obj, ObjectType NewType, uint32 Value);
extern bool CheckRight(uint32 CreatureID, RIGHT Right);
extern void CleanupDynamicStrings(void);
extern void CreatePlayerList(bool Online);
extern void CronChange(Object Obj, int NewDelay);
extern void CronExpire(Object Obj, int Delay);
extern uint32 CronInfo(Object Obj, bool Delete);
extern uint32 CronStop(Object Obj);
extern void DeleteDynamicString(uint32 Number);
extern TCreature *GetCreature(uint32 CreatureID);
extern const char *GetDynamicString(uint32 Number);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
extern bool IsProtectionZone(int x, int y, int z);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void LogoutAllPlayers(void);
extern void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Object Ignore);