From fbb392953c5af29b6a0924590c24a05befb72e56 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Mon, 26 May 2025 01:44:13 -0300 Subject: more object functions --- Makefile | 2 +- reference/game.c | 962 ------------------------------------------------------- src/map.cc | 394 ++++++++++++++++++----- src/map.hh | 78 ++++- src/objects.hh | 8 + src/stubs.hh | 2 + 6 files changed, 388 insertions(+), 1058 deletions(-) diff --git a/Makefile b/Makefile index 18037c1..f5bc488 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ BUILDDIR = build OUTPUTEXE = game CC = g++ -CFLAGS = -m64 -fno-strict-aliasing -Wall -Wextra -Wno-unused-parameter -Wno-format-truncation -std=c++11 -DOS_LINUX=1 -DARCH_X64=1 -D_CRT_SECURE_NO_WARNINGS=1 +CFLAGS = -m64 -fno-strict-aliasing -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-format-truncation -std=c++11 -DOS_LINUX=1 -DARCH_X64=1 -D_CRT_SECURE_NO_WARNINGS=1 LFLAGS = -Wl,-t DEBUG ?= 0 diff --git a/reference/game.c b/reference/game.c index 1a48631..63100e0 100644 --- a/reference/game.c +++ b/reference/game.c @@ -5584,713 +5584,6 @@ void CronChange(Object *Obj,int NewDelay) return; } - - -Object SplitObject(Object *Obj,int Count) - -{ - bool bVar1; - TObject *pTVar2; - ulong uVar3; - ulong Position; - uint uVar4; - ulong in_stack_0000000c; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c; - Object Copy; - ObjectType local_2c [7]; - - bVar1 = false; - if (*(uint *)Count != 0) { - uVar4 = *(uint *)Count & HashTableMask; - if (HashTableType[uVar4] == '\x02') { - UnswapSector(HashTableData[uVar4]); - } - if ((HashTableType[uVar4] == '\x01') && (*(int *)HashTableData[uVar4] == *(int *)Count)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (!bVar1) { - error(&DAT_080f1680); - local_3c = NONE; - goto LAB_08058380; - } - local_3c.ObjectID = *(ulong *)Count; - pTVar2 = AccessObject(&local_3c); - ObjectType::setTypeID(local_2c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag(local_2c,CUMULATIVE); - if (bVar1) { - if (0 < (int)in_stack_0000000c) { - uVar3 = Object::getAttribute((Object *)Count,AMOUNT); - if ((int)in_stack_0000000c <= (int)uVar3) { - uVar3 = Object::getAttribute((Object *)Count,AMOUNT); - if (in_stack_0000000c != uVar3) { - local_5c[0].ObjectID = *(ulong *)Count; - local_2c[0].TypeID = local_5c[0].ObjectID; - pTVar2 = AccessObject(local_5c); - local_4c[0].ObjectID = (pTVar2->Container).ObjectID; - CopyObject(&local_3c,local_4c); - uVar3 = Object::getAttribute((Object *)Count,AMOUNT); - Object::setAttribute((Object *)Count,AMOUNT,uVar3 - in_stack_0000000c); - Object::setAttribute(&local_3c,AMOUNT,in_stack_0000000c); - goto LAB_08058380; - } - goto LAB_080583fc; - } - } - error(&DAT_080f16c0,in_stack_0000000c); - } - else { - error("SplitObject: Objekt ist nicht kumulierbar.\n"); - } -LAB_080583fc: - local_3c.ObjectID = *(ulong *)Count; -LAB_08058380: - Obj->ObjectID = (ulong)local_3c; - return (Object)(ulong)Obj; -} - - - -void MergeObjects(Object *Obj,Object *Dest) - -{ - Object OVar1; - bool bVar2; - TObject *pTVar3; - ulong uVar4; - ulong uVar5; - ulong Position; - uint uVar6; - char *Text; - Object local_6c [4]; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - ObjectType local_2c [7]; - - bVar2 = false; - if (Obj->ObjectID != 0) { - uVar6 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar6] == '\x02') { - UnswapSector(HashTableData[uVar6]); - } - if ((HashTableType[uVar6] == '\x01') && (*(ulong *)HashTableData[uVar6] == Obj->ObjectID)) { - bVar2 = true; - } - else { - bVar2 = false; - } - } - if (bVar2) { - bVar2 = false; - if (Dest->ObjectID != 0) { - uVar6 = Dest->ObjectID & HashTableMask; - if (HashTableType[uVar6] == '\x02') { - UnswapSector(HashTableData[uVar6]); - } - if ((HashTableType[uVar6] == '\x01') && - (*(ulong *)HashTableData[uVar6] == Dest->ObjectID)) { - bVar2 = true; - } - else { - bVar2 = false; - } - } - if (bVar2) { - local_3c[0] = (Object)Obj->ObjectID; - pTVar3 = AccessObject(local_3c); - ObjectType::setTypeID(local_2c,(pTVar3->Type).TypeID); - local_4c[0] = (Object)Dest->ObjectID; - pTVar3 = AccessObject(local_4c); - ObjectType::setTypeID((ObjectType *)local_3c,(pTVar3->Type).TypeID); - ObjectType::setTypeID((ObjectType *)local_4c,local_3c[0].ObjectID); - if (local_2c[0].TypeID != local_4c[0].ObjectID) { - local_5c[0] = (Object)Dest->ObjectID; - pTVar3 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar3->Type).TypeID); - OVar1.ObjectID = local_4c[0].ObjectID; - local_6c[0] = (Object)Obj->ObjectID; - pTVar3 = AccessObject(local_6c); - ObjectType::setTypeID((ObjectType *)local_5c,(pTVar3->Type).TypeID); - error("MergeObjects: Objekttypen %d und %d sind nicht identisch.\n", - local_5c[0].ObjectID,OVar1.ObjectID); - return; - } - local_5c[0] = (Object)Obj->ObjectID; - pTVar3 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)local_6c,(pTVar3->Type).TypeID); - bVar2 = ObjectType::getFlag((ObjectType *)local_6c,CUMULATIVE); - if (!bVar2) { - local_5c[0] = (Object)Obj->ObjectID; - pTVar3 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)local_6c,(pTVar3->Type).TypeID); - error("MergeObjects: Objekttyp %d/%d ist nicht kumulierbar.\n",local_6c[0].ObjectID) - ; - return; - } - uVar4 = Object::getAttribute(Obj,AMOUNT); - if (uVar4 == 0) { - error(&DAT_080f18c0); - Object::setAttribute(Obj,AMOUNT,1); - } - uVar4 = Object::getAttribute(Dest,AMOUNT); - if (uVar4 == 0) { - error(&DAT_080f1880); - Object::setAttribute(Dest,AMOUNT,1); - } - uVar4 = Object::getAttribute(Obj,AMOUNT); - uVar5 = Object::getAttribute(Dest,AMOUNT); - Object::setAttribute(Dest,AMOUNT,uVar5 + uVar4); - uVar4 = Object::getAttribute(Dest,AMOUNT); - if (100 < uVar4) { - error(&DAT_080f1840); - Object::setAttribute(Dest,AMOUNT,100); - } - local_6c[0] = (Object)Obj->ObjectID; - bVar2 = false; - if (local_6c[0].ObjectID != 0) { - uVar6 = local_6c[0].ObjectID & HashTableMask; - if (HashTableType[uVar6] == '\x02') { - UnswapSector(HashTableData[uVar6]); - } - if ((HashTableType[uVar6] == '\x01') && - (*(uint *)HashTableData[uVar6] == local_6c[0].ObjectID)) { - bVar2 = true; - } - else { - bVar2 = false; - } - } - if (bVar2) { - local_5c[0].ObjectID = local_6c[0].ObjectID; - CutObject(local_5c); - local_5c[0].ObjectID = local_6c[0].ObjectID; - DestroyObject(local_5c); - return; - } - Text = &DAT_080f1800; - } - else { - Text = &DAT_080f1740; - } - } - else { - Text = &DAT_080f1900; - } - error(Text); - return; -} - - - -void MoveObject(Object *Obj,Object *Con) - -{ - bool bVar1; - ulong Position; - uint uVar2; - char *Text; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = false; - if (Obj->ObjectID != 0) { - uVar2 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar2] == '\x02') { - UnswapSector(HashTableData[uVar2]); - } - if ((HashTableType[uVar2] == '\x01') && (*(ulong *)HashTableData[uVar2] == Obj->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - bVar1 = false; - if (Con->ObjectID != 0) { - uVar2 = Con->ObjectID & HashTableMask; - if (HashTableType[uVar2] == '\x02') { - UnswapSector(HashTableData[uVar2]); - } - if ((HashTableType[uVar2] == '\x01') && - (*(ulong *)HashTableData[uVar2] == Con->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - local_2c[0] = (Object)Obj->ObjectID; - CutObject(local_2c); - local_2c[0] = (Object)Con->ObjectID; - local_3c[0] = (Object)Obj->ObjectID; - PlaceObject(local_3c,local_2c,false); - return; - } - Text = &DAT_080f1940; - } - else { - Text = &DAT_080f1980; - } - error(Text); - return; -} - - -// WARNING: Variable defined which should be unmapped: Attribute_local - -void ChangeObject(Object *Obj,INSTANCEATTRIBUTE Attribute,ulong Value) - -{ - bool bVar1; - ulong Position; - uint uVar2; - INSTANCEATTRIBUTE Attribute_local; - - bVar1 = false; - if (Obj->ObjectID != 0) { - uVar2 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar2] == '\x02') { - UnswapSector(HashTableData[uVar2]); - } - if ((HashTableType[uVar2] == '\x01') && (*(ulong *)HashTableData[uVar2] == Obj->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (!bVar1) { - error(&DAT_080f19c0); - return; - } - Object::setAttribute(Obj,Attribute,Value); - return; -} - -Object SetObject(Object *Con,ObjectType *Type,ulong CreatureID) - -{ - bool bVar1; - TObject *pTVar2; - ulong Position; - uint uVar3; - ulong in_stack_00000010; - Object local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - bVar1 = false; - if (Type->TypeID != 0) { - uVar3 = Type->TypeID & HashTableMask; - if (HashTableType[uVar3] == '\x02') { - UnswapSector(HashTableData[uVar3]); - } - if ((HashTableType[uVar3] == '\x01') && (*(int *)HashTableData[uVar3] == Type->TypeID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - CreateObject(); - ObjectType::setTypeID((ObjectType *)local_3c,*(int *)CreatureID); - local_4c[0].ObjectID = local_2c; - ChangeObject(local_4c,(ObjectType *)local_3c); - local_4c[0].ObjectID = Type->TypeID; - local_3c[0].ObjectID = local_2c; - PlaceObject(local_3c,local_4c,false); - local_3c[0].ObjectID = local_2c; - pTVar2 = AccessObject(local_3c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID); - if (local_4c[0].ObjectID == 99) { - if (in_stack_00000010 == 0) { - error(&DAT_080f1d60); - } - local_4c[0].ObjectID = local_2c; - pTVar2 = AccessObject(local_4c); - pTVar2->Attributes[1] = in_stack_00000010; - } - } - else { - error(&DAT_080f1d20); - local_2c = NONE.ObjectID; - } - Con->ObjectID = local_2c; - return (Object)(ulong)Con; -} - - - -Object CopyObject(Object *Con,Object *Source) - -{ - bool bVar1; - TObject *pTVar2; - TObject *pTVar3; - ulong uVar4; - ulong Position; - uint uVar5; - int iVar6; - uint *in_stack_0000000c; - char *pcVar7; - Object local_4c [4]; - Object local_3c; - Object Obj; - Object local_2c [7]; - - bVar1 = false; - if (*in_stack_0000000c != 0) { - uVar5 = *in_stack_0000000c & HashTableMask; - if (HashTableType[uVar5] == '\x02') { - UnswapSector(HashTableData[uVar5]); - } - if ((HashTableType[uVar5] == '\x01') && - (*(uint *)HashTableData[uVar5] == *in_stack_0000000c)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - bVar1 = false; - if (Source->ObjectID != 0) { - uVar5 = Source->ObjectID & HashTableMask; - if (HashTableType[uVar5] == '\x02') { - UnswapSector(HashTableData[uVar5]); - } - if ((HashTableType[uVar5] == '\x01') && - (*(ulong *)HashTableData[uVar5] == Source->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - local_3c.ObjectID = *in_stack_0000000c; - pTVar2 = AccessObject(&local_3c); - ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID); - if (local_2c[0].ObjectID != 99) { - local_4c[0].ObjectID = *in_stack_0000000c; - pTVar2 = AccessObject(local_4c); - ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID); - local_4c[0] = (Object)Source->ObjectID; - iVar6 = 0; - SetObject(&local_3c,(ObjectType *)local_4c,(ulong)local_2c); - do { - local_4c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_4c); - local_2c[0].ObjectID = *in_stack_0000000c; - pTVar3 = AccessObject(local_2c); - pTVar2->Attributes[iVar6] = pTVar3->Attributes[iVar6]; - iVar6 = iVar6 + 1; - } while (iVar6 < 4); - local_2c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CONTAINER); - if (bVar1) { -LAB_08059ea9: - Object::setAttribute(&local_3c,CONTENT,0); - } - else { - local_2c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CHEST); - if (bVar1) goto LAB_08059ea9; - } - local_2c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,TEXT); - if ((bVar1) && (uVar4 = Object::getAttribute(&local_3c,TEXTSTRING), uVar4 != 0)) { - uVar4 = Object::getAttribute(&local_3c,TEXTSTRING); - pcVar7 = GetDynamicString(uVar4); - uVar4 = AddDynamicString(pcVar7); - Object::setAttribute(&local_3c,TEXTSTRING,uVar4); - } - local_2c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,TEXT); - if ((bVar1) && (uVar4 = Object::getAttribute(&local_3c,EDITOR), uVar4 != 0)) { - uVar4 = Object::getAttribute(&local_3c,EDITOR); - pcVar7 = GetDynamicString(uVar4); - uVar4 = AddDynamicString(pcVar7); - Object::setAttribute(&local_3c,EDITOR,uVar4); - } - goto LAB_08059d74; - } - pcVar7 = &DAT_080f1de0; - } - else { - pcVar7 = "CopyObject: Zielcontainer existiert nicht.\n"; - } - } - else { - pcVar7 = "CopyObject: Vorlage existiert nicht.\n"; - } - error(pcVar7); - local_3c = NONE; -LAB_08059d74: - Con->ObjectID = (ulong)local_3c; - return (Object)(ulong)Con; -} - -void CutObject(Object *Obj) - -{ - bool bVar1; - TObject *pTVar2; - TObject *pTVar3; - ulong Position; - uint uVar4; - Object local_8c [4]; - Object local_7c [4]; - Object local_6c [4]; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c; - Object Search; - Object local_2c; - Object Con; - - bVar1 = false; - if (Obj->ObjectID != 0) { - uVar4 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar4] == '\x02') { - UnswapSector(HashTableData[uVar4]); - } - if ((HashTableType[uVar4] == '\x01') && (*(ulong *)HashTableData[uVar4] == Obj->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (!bVar1) { - error(&DAT_080f1ea0); - return; - } - local_3c = (Object)Obj->ObjectID; - pTVar2 = AccessObject(&local_3c); - local_4c[0].ObjectID = (pTVar2->Container).ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - local_2c.ObjectID = local_4c[0].ObjectID; - if (local_4c[0].ObjectID == NONE.ObjectID) { - error(&DAT_080f1b80); - local_3c = NONE; - } - else { - Object::getObjectType(local_5c); - bVar1 = ObjectType::getFlag((ObjectType *)local_5c,CONTAINER); - if (!bVar1) { - Object::getObjectType(local_5c); - bVar1 = ObjectType::getFlag((ObjectType *)local_5c,CHEST); - if (!bVar1) { - Object::getObjectType(local_5c); - error("GetFirstContainerObject: Con (%d) ist kein Container.\n",local_5c[0].ObjectID - ); - local_3c = NONE; - goto LAB_0805a144; - } - } - local_3c.ObjectID = Object::getAttribute(local_4c,CONTENT); - } -LAB_0805a144: - local_5c[0] = (Object)Obj->ObjectID; - if (local_3c.ObjectID == local_5c[0].ObjectID) { - local_6c[0].ObjectID = local_5c[0].ObjectID; - pTVar2 = AccessObject(local_6c); - local_4c[0].ObjectID = (pTVar2->NextObject).ObjectID; - Object::setAttribute(&local_2c,CONTENT,local_4c[0].ObjectID); - } - else { - while( true ) { - local_4c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_4c); - local_6c[0].ObjectID = (pTVar2->NextObject).ObjectID; - local_7c[0] = (Object)Obj->ObjectID; - if (local_6c[0].ObjectID == local_7c[0].ObjectID) break; - local_4c[0].ObjectID = local_3c.ObjectID; - pTVar2 = AccessObject(local_4c); - local_3c.ObjectID = (pTVar2->NextObject).ObjectID; - local_7c[0].ObjectID = local_3c.ObjectID; - local_6c[0].ObjectID = local_3c.ObjectID; - } - local_6c[0].ObjectID = local_3c.ObjectID; - local_4c[0].ObjectID = local_7c[0].ObjectID; - pTVar2 = AccessObject(local_6c); - local_8c[0] = (Object)Obj->ObjectID; - pTVar3 = AccessObject(local_8c); - local_4c[0].ObjectID = (pTVar3->NextObject).ObjectID; - (pTVar2->NextObject).ObjectID = local_4c[0].ObjectID; - } - local_7c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_7c); - local_8c[0] = NONE; - local_6c[0].ObjectID = NONE.ObjectID; - (pTVar2->NextObject).ObjectID = NONE.ObjectID; - local_7c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_7c); - (pTVar2->Container).ObjectID = NONE.ObjectID; - return; -} - - - -void DestroyObject(Object *Obj) - -{ - bool bVar1; - TObject *pTVar2; - ulong uVar3; - ulong nr; - uint uVar4; - char *Text; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = false; - if (Obj->ObjectID != 0) { - uVar4 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar4] == '\x02') { - UnswapSector(HashTableData[uVar4]); - } - if ((HashTableType[uVar4] == '\x01') && (*(ulong *)HashTableData[uVar4] == Obj->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (!bVar1) { - Text = &DAT_080f1ee0; - goto LAB_0805a343; - } - local_3c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_3c); - ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,TEXT); - if (bVar1) { - uVar3 = Object::getAttribute(Obj,TEXTSTRING); - DeleteDynamicString(uVar3); - uVar3 = Object::getAttribute(Obj,EDITOR); - DeleteDynamicString(uVar3); - } - local_2c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER); - if (bVar1) { -LAB_0805a400: - while (uVar3 = Object::getAttribute(Obj,CONTENT), uVar3 != 0) { - local_3c[0].ObjectID = Object::getAttribute(Obj,CONTENT); - bVar1 = false; - if (local_3c[0].ObjectID != 0) { - uVar4 = local_3c[0].ObjectID & HashTableMask; - if (HashTableType[uVar4] == '\x02') { - UnswapSector(HashTableData[uVar4]); - } - if ((HashTableType[uVar4] == '\x01') && - (*(ulong *)HashTableData[uVar4] == local_3c[0].ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - local_2c[0].ObjectID = local_3c[0].ObjectID; - CutObject(local_2c); - local_2c[0].ObjectID = local_3c[0].ObjectID; - DestroyObject(local_2c); - } - else { - error(&DAT_080f1800); - } - } - } - else { - local_2c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CHEST); - if (bVar1) goto LAB_0805a400; - } - local_2c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_2c); - ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,EXPIRE); - if (bVar1) { - local_3c[0] = (Object)Obj->ObjectID; - CronStop(local_3c); - } - if (Obj->ObjectID == 0) { - error(&DAT_080f1f60,0); - return; - } - uVar4 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar4] == '\x01') { - PutFreeObjectSlot((TObject *)HashTableData[uVar4]); - HashTableType[uVar4] = '\0'; - HashTableFree = HashTableFree + 1; - DecrementObjectCounter(); - return; - } - Text = "DestroyObject: Objekt steht nicht im Speicher.\n"; -LAB_0805a343: - error(Text); - return; -} - - - -void DeleteObject(Object *Obj) - -{ - bool bVar1; - ulong Position; - uint uVar2; - Object local_1c [4]; - - bVar1 = false; - if (Obj->ObjectID != 0) { - uVar2 = Obj->ObjectID & HashTableMask; - if (HashTableType[uVar2] == '\x02') { - UnswapSector(HashTableData[uVar2]); - } - if ((HashTableType[uVar2] == '\x01') && (*(ulong *)HashTableData[uVar2] == Obj->ObjectID)) { - bVar1 = true; - } - else { - bVar1 = false; - } - } - if (bVar1) { - local_1c[0] = (Object)Obj->ObjectID; - CutObject(local_1c); - local_1c[0] = (Object)Obj->ObjectID; - DestroyObject(local_1c); - } - else { - error(&DAT_080f1800); - } - return; -} - // WARNING: Unknown calling convention -- yet parameter storage is locked Object GetFirstSpecObject(void) @@ -6780,261 +6073,6 @@ bool GetMarkPosition(void) return false; } - -int GetInstanceAttributeByName(char *Name) - -{ - int iVar1; - int i; - int iVar2; - char (*s1) [30]; - - iVar2 = 0; - s1 = InstanceAttributeNames; - do { - iVar1 = stricmp(*s1,Name,-1); - if (iVar1 == 0) { - return iVar2; - } - iVar2 = iVar2 + 1; - s1 = s1 + 1; - } while (iVar2 < 0x12); - return -1; -} - -void SaveObjects(Object *Obj,TWriteStream *Stream,bool Stop) - -{ - bool bVar1; - TObject *pTVar2; - int iVar3; - ulong uVar4; - char *pcVar5; - bool ProcessObjects; - INSTANCEATTRIBUTE Attribute; - ulong Value; - int Depth; - Object OStack_6c; - bool Stop_local; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object LastObj; - - bVar1 = true; - Value = 1; - local_2c = NONE.ObjectID; - do { - if (bVar1) { - uVar4 = Obj->ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - if (uVar4 == NONE.ObjectID) { - (*Stream->_vptr_TWriteStream[2])(Stream,0xffff); - Value = Value - 1; - if ((int)Value < 1) { - return; - } - (*Stream->_vptr_TWriteStream[1])(Stream,0xff); - ObjectCounter = ObjectCounter + 1; - if ((Stop) && (Value == 1)) { - return; - } - local_4c[0].ObjectID = NONE.ObjectID; - if (local_2c == NONE.ObjectID) { - error("LastObj ist NONE (1)\n"); - } - OStack_6c.ObjectID = local_2c; - pTVar2 = AccessObject(&stack0xffffff94); - local_5c[0].ObjectID = (pTVar2->Container).ObjectID; - OStack_6c.ObjectID = NONE.ObjectID; - local_2c = local_5c[0].ObjectID; - if (local_5c[0].ObjectID == NONE.ObjectID) { - local_4c[0].ObjectID = local_5c[0].ObjectID; - error("LastObj ist NONE (2)\n"); - } - } - else { - OStack_6c.ObjectID = NONE.ObjectID; - if (uVar4 == NONE.ObjectID) { - error("Obj ist NONE (1)\n"); - uVar4 = Obj->ObjectID; - } - local_5c[0].ObjectID = uVar4; - // try { // try from 0805d023 to 0805d34b has its CatchHandler @ 0805d353 - pTVar2 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)&stack0xffffff94,(pTVar2->Type).TypeID); - if (OStack_6c.ObjectID != 99) { - local_5c[0] = (Object)Obj->ObjectID; - pTVar2 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)&stack0xffffff94,(pTVar2->Type).TypeID); - (*Stream->_vptr_TWriteStream[2])(Stream,OStack_6c.ObjectID & 0xffff); - bVar1 = false; - goto LAB_0805d072; - } - if ((Stop) && (Value == 1)) { - return; - } - OStack_6c = (Object)Obj->ObjectID; - local_5c[0].ObjectID = OStack_6c.ObjectID; - local_2c = OStack_6c.ObjectID; - } - local_4c[0].ObjectID = local_2c; - pTVar2 = AccessObject(local_4c); - OStack_6c.ObjectID = (pTVar2->NextObject).ObjectID; - Obj->ObjectID = (ulong)OStack_6c; - local_5c[0].ObjectID = OStack_6c.ObjectID; - } - else { - uVar4 = Obj->ObjectID; - OStack_6c.ObjectID = NONE.ObjectID; - if (uVar4 == NONE.ObjectID) { - error("Obj ist NONE (2)\n"); - uVar4 = Obj->ObjectID; - } - Attribute = CONTENT; - do { - if (Attribute != CONTENT) { - local_5c[0].ObjectID = uVar4; - pTVar2 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)&stack0xffffff94,(pTVar2->Type).TypeID); - iVar3 = ObjectType::getAttributeOffset((ObjectType *)&stack0xffffff94,Attribute) - ; - if (iVar3 != -1) { - if (Attribute == REMAININGEXPIRETIME) { - OStack_6c = (Object)Obj->ObjectID; - uVar4 = CronInfo(&stack0xffffff94,false); - } - else { - uVar4 = Object::getAttribute(Obj,Attribute); - } - if (uVar4 != 0) { - (*Stream->_vptr_TWriteStream[1])(Stream,Attribute & 0xff); - if (Attribute - TEXTSTRING < 2) { - pcVar5 = GetDynamicString(uVar4); - (*Stream->_vptr_TWriteStream[4])(Stream,pcVar5); - } - else { - (*Stream->_vptr_TWriteStream[3])(Stream,uVar4); - } - } - } - uVar4 = Obj->ObjectID; - } - Attribute = Attribute + CHESTQUESTNUMBER; - } while ((int)Attribute < 0x12); - bVar1 = false; - local_5c[0].ObjectID = uVar4; - pTVar2 = AccessObject(local_5c); - ObjectType::setTypeID((ObjectType *)&stack0xffffff94,(pTVar2->Type).TypeID); - iVar3 = ObjectType::getAttributeOffset((ObjectType *)&stack0xffffff94,CONTENT); - if ((iVar3 != -1) && (uVar4 = Object::getAttribute(Obj,CONTENT), uVar4 != 0)) { - bVar1 = true; - } - if (bVar1) { - Value = Value + 1; - local_4c[0].ObjectID = NONE.ObjectID; - local_2c = NONE.ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - local_3c[0] = (Object)Obj->ObjectID; - GetFirstContainerObject(local_4c); - Obj->ObjectID = (ulong)local_4c[0]; - local_5c[0].ObjectID = local_4c[0].ObjectID; - (*Stream->_vptr_TWriteStream[1])(Stream,0); - } - else { - (*Stream->_vptr_TWriteStream[1])(Stream,0xff); - ObjectCounter = ObjectCounter + 1; - if ((Stop) && (Value == 1)) { - return; - } - local_5c[0] = (Object)Obj->ObjectID; - local_4c[0].ObjectID = local_5c[0].ObjectID; - local_3c[0].ObjectID = local_5c[0].ObjectID; - local_2c = local_5c[0].ObjectID; - pTVar2 = AccessObject(local_3c); - local_5c[0].ObjectID = (pTVar2->NextObject).ObjectID; - Obj->ObjectID = (ulong)local_5c[0]; - local_4c[0].ObjectID = local_5c[0].ObjectID; - } - bVar1 = true; - } -LAB_0805d072: - if ((int)Value < 1) { - return; - } - } while( true ); -} - - - -void SaveObjects(TReadStream *Stream,TWriteScriptFile *Script) - -{ - bool bVar1; - bool bVar2; - char cVar3; - uint uVar4; - int Number; - ushort TypeID; - bool FirstObject; - int iStack_1020; - bool ProcessObjects; - int Depth; - char Help [4096]; - - iStack_1020 = 1; - bVar1 = true; - // try { // try from 0805d3a5 to 0805d4f1 has its CatchHandler @ 0805d513 - TWriteScriptFile::writeText(Script,"{"); - bVar2 = true; - do { - if (bVar1) { - uVar4 = (*Stream->_vptr_TReadStream[2])(Stream); - if ((short)uVar4 == -1) { - iStack_1020 = iStack_1020 + -1; - bVar1 = false; - TWriteScriptFile::writeText(Script,"}"); - } - else { - if (!bVar2) { - TWriteScriptFile::writeText(Script,", "); - } - TWriteScriptFile::writeNumber(Script,uVar4 & 0xffff); - bVar1 = false; - } - } - else { - uVar4 = (*Stream->_vptr_TReadStream[1])(Stream); - cVar3 = (char)uVar4; - if (cVar3 == -1) { - bVar1 = true; - bVar2 = false; - } - else { - TWriteScriptFile::writeText(Script," "); - TWriteScriptFile::writeText(Script,InstanceAttributeNames[uVar4 & 0xff]); - TWriteScriptFile::writeText(Script,"="); - if (cVar3 == '\0') { - iStack_1020 = iStack_1020 + 1; - bVar1 = true; - TWriteScriptFile::writeText(Script,"{"); - bVar2 = true; - } - else if ((byte)(cVar3 - 9U) < 2) { - (*Stream->_vptr_TReadStream[4])(Stream,&Depth,0x1000); - TWriteScriptFile::writeString(Script,(char *)&Depth); - } - else { - Number = (*Stream->_vptr_TReadStream[3])(Stream); - TWriteScriptFile::writeNumber(Script,Number); - } - } - } - } while (0 < iStack_1020); - return; -} - void RefreshSector(int x,int y,int z,TReadStream *Stream) { diff --git a/src/map.cc b/src/map.cc index 20dae79..0930083 100644 --- a/src/map.cc +++ b/src/map.cc @@ -8,30 +8,6 @@ #include -// NOTE(fusion): This is used by hash table entries and sectors to tell whether -// they're currently loaded or swapped out to disk. -enum : uint8 { - STATUS_FREE = 0, - STATUS_LOADED = 1, - STATUS_SWAPPED = 2, - - // TODO(fusion): It seems this is only used with the `NONE` entry in the - // hash table. I haven't seen it used **yet** but It may have a purpose - // aside from preventing swap outs. - STATUS_PERMANENT = 255, -}; - -// NOTE(fusion): This is used to determine precedence order of different objects -// in a tile. -enum : int { - PRIORITY_BANK = 0, - PRIORITY_CLIP = 1, - PRIORITY_BOTTOM = 2, - PRIORITY_TOP = 3, - PRIORITY_CREATURE = 4, - PRIORITY_OTHER = 5, -}; - static int OBCount; static int SectorXMin; static int SectorXMax; @@ -1207,6 +1183,24 @@ void ExitMap(bool Save){ // Object Functions // ============================================================================= +TObject *AccessObject(Object Obj){ + if(Obj == NONE){ + error("AccessObject: Ungültige Objektnummer Null.\n"); + return HashTableData[0]; + } + + uint32 EntryIndex = Obj.ObjectID & HashTableMask; + if(HashTableType[EntryIndex] == STATUS_SWAPPED){ + UnswapSector((uint32)((uintptr)HashTableData[EntryIndex])); + } + + if(HashTableType[EntryIndex] == STATUS_LOADED && HashTableData[EntryIndex]->ObjectID == Obj.ObjectID){ + return HashTableData[EntryIndex]; + }else{ + return HashTableData[0]; + } +} + Object CreateObject(void){ static uint32 NextObjectID = 1; @@ -1240,25 +1234,58 @@ Object CreateObject(void){ return Object(NextObjectID); } -// DestroyObject -// DeleteObject +void DestroyObject(Object Obj){ + if(!Obj.exists()){ + error("DestroyObject: Übergebenes Objekt existiert nicht.\n"); + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(TEXT)){ + DeleteDynamicString(Obj.getAttribute(TEXTSTRING)); + DeleteDynamicString(Obj.getAttribute(EDITOR)); + } -TObject *AccessObject(Object Obj){ + if(ObjType.getFlag(CONTAINER) || ObjType.getFlag(CHEST)){ + while(true){ + Object Inner = Obj.getAttribute(CONTENT); + if(Inner == NONE){ + break; + } + DeleteObject(Inner); + } + } + + if(ObjType.getFlag(EXPIRE)){ + CronStop(Obj); + } + + // TODO(fusion): I feel this should be checked up front? if(Obj == NONE){ - error("AccessObject: Ungültige Objektnummer Null.\n"); - return HashTableData[0]; + error("DestroyObject: Ungültige Objektnummer %d.\n", NONE.ObjectID); + return; } uint32 EntryIndex = Obj.ObjectID & HashTableMask; - if(HashTableType[EntryIndex] == STATUS_SWAPPED){ - UnswapSector((uint32)((uintptr)HashTableData[EntryIndex])); + if(HashTableType[EntryIndex] != STATUS_LOADED){ + error("DestroyObject: Objekt steht nicht im Speicher.\n"); + return; } - if(HashTableType[EntryIndex] == STATUS_LOADED && HashTableData[EntryIndex]->ObjectID == Obj.ObjectID){ - return HashTableData[EntryIndex]; - }else{ - return HashTableData[0]; + PutFreeObjectSlot(HashTableData[EntryIndex]); + HashTableType[EntryIndex] = STATUS_FREE; + HashTableFree += 1; + DecrementObjectCounter(); +} + +void DeleteObject(Object Obj){ + if(!Obj.exists()){ + error("DeleteObject: Übergebenes Objekt existiert nicht.\n"); + return; } + + CutObject(Obj); + DestroyObject(Obj); } void ChangeObject(Object Obj, ObjectType NewType){ @@ -1338,6 +1365,41 @@ void ChangeObject(Object Obj, ObjectType NewType){ CronExpire(Obj, Delay); } +void ChangeObject(Object Obj, INSTANCEATTRIBUTE Attribute, uint32 Value){ + if(!Obj.exists()){ + error("ChangeObject: Übergebenes Objekt existiert nicht.\n"); + return; + } + + Obj.setAttribute(Attribute, Value); +} + +void ChangeObject(Object Obj, ObjectType NewType, uint32 Value){ + if(!Obj.exists()){ + error("ChangeObject: Übergebenes Objekt existiert nicht (1, NewType=%d).\n", NewType.TypeID); + return; + } + + // TODO(fusion): Why are we checking if `Obj` exists a second time? There is + // no reason to assume `Obj.getContainer()` would change anything since the + // first call. + Object Con = Obj.getContainer(); + if(!Obj.exists()){ + error("ChangeObject: Übergebenes Objekt existiert nicht (2, NewType=%d).\n", NewType.TypeID); + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CUMULATIVE)){ + uint32 Amount = Obj.getAttribute(AMOUNT); + if(Amount > 1){ + Move(0, Obj, Con, Amount - 1, true, NONE); + } + } + + Change(Obj, NewType, Value); +} + int GetObjectPriority(Object Obj){ if(!Obj.exists()){ error("GetObjectPriority: Übergebenes Objekt existiert nicht.\n"); @@ -1439,6 +1501,46 @@ void PlaceObject(Object Obj, Object Con, bool Append){ Obj.setContainer(Con); } +// NOTE(fusion): This is the opposite of `PlaceObject`. +void CutObject(Object Obj){ + if(!Obj.exists()){ + error("CutObject: Übergebenes Objekt existiert nicht.\n"); + return; + } + + Object Con = Obj.getContainer(); + Object Cur = GetFirstContainerObject(Con); + if(Cur == Obj){ + Object Next = Obj.getNextObject(); + Con.setAttribute(CONTENT, Next.ObjectID); + }else{ + Object Prev; + do{ + Prev = Cur; + Cur = Cur.getNextObject(); + }while(Cur != Obj); + Prev.setNextObject(Cur.getNextObject()); + } + + Obj.setNextObject(NONE); + Obj.setContainer(NONE); +} + +void MoveObject(Object Obj, Object Con){ + if(!Obj.exists()){ + error("MoveObject: Übergebenes Objekt existiert nicht.\n"); + return; + } + + if(!Con.exists()){ + error("MoveObject: Übergebener Zielcontainer existiert nicht.\n"); + return; + } + + CutObject(Obj); + PlaceObject(Obj, Con, false); +} + Object AppendObject(Object Con, ObjectType Type){ if(!Con.exists()){ error("AppendObject: Übergebener Container existiert nicht.\n"); @@ -1451,6 +1553,143 @@ Object AppendObject(Object Con, ObjectType Type){ return Obj; } +Object SetObject(Object Con, ObjectType Type, uint32 CreatureID){ + if(!Con.exists()){ + error("SetObject: Übergebener Container existiert nicht.\n"); + return NONE; + } + + Object Obj = CreateObject(); + ChangeObject(Obj, Type); + PlaceObject(Obj, Con, false); + if(Type.isCreatureContainer()){ + if(CreatureID == 0){ + error("SetObject: Ungültige Kreatur-ID.\n"); + } + AccessObject(Obj)->Attributes[1] = CreatureID; + } + return Obj; +} + +Object CopyObject(Object Con, Object Source){ + if(!Source.exists()){ + error("CopyObject: Vorlage existiert nicht.\n"); + return NONE; + } + + if(!Con.exists()){ + error("CopyObject: Zielcontainer existiert nicht.\n"); + return NONE; + } + + ObjectType SourceType = Source.getObjectType(); + if(SourceType.isCreatureContainer()){ + error("CopyObject: Kreaturen dürfen nicht kopiert werden.\n"); + return NONE; + } + + Object NewObj = SetObject(Con, SourceType, 0); + for(int i = 0; i < NARRAY(TObject::Attributes); i += 1){ + AccessObject(NewObj)->Attributes[i] = AccessObject(Source)->Attributes[i]; + } + + if(SourceType.getFlag(CONTAINER) || SourceType.getFlag(CHEST)){ + NewObj.setAttribute(CONTENT, NONE.ObjectID); + } + + if(SourceType.getFlag(TEXT)){ + // NOTE(fusion): Both `NewObj` and `Source` share the same strings. We + // need to duplicate them so both objects can "own" and manage their own + // strings separately. + uint32 TextString = NewObj.getAttribute(TEXTSTRING); + if(TextString != 0){ + TextString = AddDynamicString(GetDynamicString(TextString)); + NewObj.setAttribute(TEXTSTRING, TextString); + } + + uint32 Editor = NewObj.getAttribute(EDITOR); + if(Editor != 0){ + Editor = AddDynamicString(GetDynamicString(TextString)); + NewObj.setAttribute(EDITOR, Editor); + } + } + + return NewObj; +} + +Object SplitObject(Object Obj, int Count){ + if(!Obj.exists()){ + error("SplitObject: Übergebenes Objekt existiert nicht.\n"); + return NONE; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.getFlag(CUMULATIVE)){ + error("SplitObject: Objekt ist nicht kumulierbar.\n"); + return Obj; // TODO(fusion): Probably return NONE? + } + + uint32 Amount = Obj.getAttribute(AMOUNT); + if(Count <= 0 || (uint32)Count > Amount){ + error("SplitObject: Ungültiger Zähler %d.\n", Count); + return Obj; // TODO(fusion): Probably return NONE? + } + + Object Res = Obj; + if((uint32)Count != Amount){ + Res = CopyObject(Obj.getContainer(), Obj); + Res.setAttribute(AMOUNT, (uint32)Count); + Obj.setAttribute(AMOUNT, Amount - (uint32)Count); + } + return Res; +} + +void MergeObjects(Object Obj, Object Dest){ + if(!Obj.exists()){ + error("MergeObjects: Übergebenes Objekt existiert nicht.\n"); + return; + } + + if(!Dest.exists()){ + error("MergeObjects: Übergebenes Ziel existiert nicht.\n"); + return; + } + + ObjectType ObjType = Obj.getObjectType(); + ObjectType DestType = Dest.getObjectType(); + if(ObjType != DestType){ + error("MergeObjects: Objekttypen %d und %d sind nicht identisch.\n", + ObjType.TypeID, DestType.TypeID); + return; + } + + if(!ObjType.getFlag(CUMULATIVE)){ + error("MergeObjects: Objekttyp %d ist nicht kumulierbar.\n", ObjType.TypeID); + return; + } + + uint32 ObjAmount = Obj.getAttribute(AMOUNT); + if(ObjAmount == 0){ + error("MergeObjects: Objekt enthält 0 Teile.\n"); + ObjAmount = 1; + } + + uint32 DestAmount = Dest.getAttribute(AMOUNT); + if(DestAmount == 0){ + error("MergeObjects: Zielobjekt enthält 0 Teile.\n"); + DestAmount = 1; + } + + DestAmount += ObjAmount; + if(DestAmount > 100){ + error("MergeObjects: Neues Objekt enthält mehr als 100 Teile.\n"); + DestAmount = 100; + } + + Dest.setAttribute(AMOUNT, DestAmount); + DeleteObject(Obj); +} + Object GetFirstContainerObject(Object Con){ if(Con == NONE){ error("GetFirstContainerObject: Übergebener Container existiert nicht.\n"); @@ -1478,53 +1717,14 @@ Object GetContainerObject(Object Con, int Index){ } Object Obj = GetFirstContainerObject(Con); - while(Obj != NONE && Index > 0){ + while(Index > 0 && Obj != NONE){ + Index -= 1; Obj = Obj.getNextObject(); } return Obj; } -void GetObjectCoordinates(Object Obj, int *x, int *y, int *z){ - if(!Obj.exists()){ - error("GetObjectCoordinates: Übergebenes Objekt existiert nicht.\n"); - *x = 0; - *y = 0; - *z = 0; - return; - } - - // TODO(fusion): I'm not sure I like this approach with calling `AccessObject` - // multiple times for the same object. Furthermore, using `Object::getObjectType` - // (at least until now) is very weird when we could just get the same information - // from the `TObject` which we'll access ANYWAYS. - - while(true){ - if(Obj.getObjectType().isMapContainer()) - break; - Obj = Obj.getContainer(); - } - - *x = AccessObject(Obj)->Attributes[1]; - *y = AccessObject(Obj)->Attributes[2]; - - // NOTE(fusion): The first 8 bits of `Attributes[3]` holds the Z coordinate - // of a map container. The next 8 bits holds the flags of a map container. - *z = AccessObject(Obj)->Attributes[3] & 0xFF; - - return; -} - -uint8 GetMapContainerFlags(Object Obj){ - if(!Obj.exists() || !Obj.getObjectType().isMapContainer()){ - error("GetMapContainerFlags: Objekt ist kein MapContainer.\n"); - return 0; - } - - // NOTE(fusion): See note in `GetObjectCoordinates` just above. - return (uint8)(AccessObject(Obj)->Attributes[3] >> 8); -} - Object GetMapContainer(int x, int y, int z){ int SectorX = x / 32; int SectorY = y / 32; @@ -1542,7 +1742,6 @@ Object GetMapContainer(int x, int y, int z){ return NONE; } - int OffsetX = x % 32; int OffsetY = y % 32; ConSector->TimeStamp = RoundNr; @@ -1555,7 +1754,7 @@ Object GetMapContainer(Object Obj){ return NONE; } - while(true){ + while(Obj != NONE){ if(Obj.getObjectType().isMapContainer()) break; Obj = Obj.getContainer(); @@ -1572,3 +1771,42 @@ Object GetFirstObject(int x, int y, int z){ return NONE; } } + +uint8 GetMapContainerFlags(Object Obj){ + if(!Obj.exists() || !Obj.getObjectType().isMapContainer()){ + error("GetMapContainerFlags: Objekt ist kein MapContainer.\n"); + return 0; + } + + // NOTE(fusion): See note in `GetObjectCoordinates`. + return (uint8)(AccessObject(Obj)->Attributes[3] >> 8); +} + +void GetObjectCoordinates(Object Obj, int *x, int *y, int *z){ + if(!Obj.exists()){ + error("GetObjectCoordinates: Übergebenes Objekt existiert nicht.\n"); + *x = 0; + *y = 0; + *z = 0; + return; + } + + // TODO(fusion): I'm not sure I like this approach with calling `AccessObject` + // multiple times for the same object. Furthermore, using `Object::getObjectType` + // (at least until now) is very weird when we could just get the same information + // from the `TObject` which we'll access ANYWAYS. + + while(true){ + if(Obj.getObjectType().isMapContainer()) + break; + Obj = Obj.getContainer(); + } + + *x = AccessObject(Obj)->Attributes[1]; + *y = AccessObject(Obj)->Attributes[2]; + + // NOTE(fusion): The first 8 bits of `Attributes[3]` holds the Z coordinate + // of a map container. The next 8 bits holds its flags and the last 16 bits + // holds its house id. + *z = AccessObject(Obj)->Attributes[3] & 0xFF; +} diff --git a/src/map.hh b/src/map.hh index 3c92fff..ac58b98 100644 --- a/src/map.hh +++ b/src/map.hh @@ -5,37 +5,55 @@ #include "objects.hh" #include "script.hh" +// NOTE(fusion): This is used by hash table entries and sectors to tell whether +// they're currently loaded or swapped out to disk. +enum : uint8 { + STATUS_FREE = 0, + STATUS_LOADED = 1, + STATUS_SWAPPED = 2, + + // TODO(fusion): It seems this is only used with the `NONE` entry in the + // hash table. I haven't seen it used **yet** but It may have a purpose + // aside from preventing swap outs. + STATUS_PERMANENT = 255, +}; + +// NOTE(fusion): This is used to determine precedence order of different objects +// in a map container. +enum : int { + PRIORITY_BANK = 0, + PRIORITY_CLIP = 1, + PRIORITY_BOTTOM = 2, + PRIORITY_TOP = 3, + PRIORITY_CREATURE = 4, + PRIORITY_OTHER = 5, +}; + struct Object { // REGULAR FUNCTIONS // ========================================================================= constexpr Object(void) : ObjectID(0) {} constexpr Object(uint32 ObjectID): ObjectID(ObjectID) {} - constexpr bool operator==(const Object &other) const { - return this->ObjectID == other.ObjectID; - } - - constexpr bool operator!=(const Object &other) const { - return this->ObjectID != other.ObjectID; - } - bool exists(void); - ObjectType getObjectType(void); void setObjectType(ObjectType Type); - Object getNextObject(void); void setNextObject(Object NextObject); - Object getContainer(void); void setContainer(Object Con); - uint32 getCreatureID(void); - //void setCreatureID(uint32 CreatureID); //?? - uint32 getAttribute(INSTANCEATTRIBUTE Attribute); void setAttribute(INSTANCEATTRIBUTE Attribute, uint32 Value); + constexpr bool operator==(const Object &Other) const { + return this->ObjectID == Other.ObjectID; + } + + constexpr bool operator!=(const Object &Other) const { + return this->ObjectID != Other.ObjectID; + } + // DATA // ========================================================================= uint32 ObjectID; @@ -95,22 +113,48 @@ void SaveObjects(Object Obj, TWriteStream *Stream, bool Stop); void SaveObjects(TReadStream *Stream, TWriteScriptFile *Script); void SaveSector(char *FileName, int SectorX, int SectorY, int SectorZ); void SaveMap(void); +//RefreshSector +//PatchSector void InitMap(void); void ExitMap(bool Save); // NOTE(fusion): Object related functions. -Object CreateObject(void); TObject *AccessObject(Object Obj); +Object CreateObject(void); +void DestroyObject(Object Obj); +void DeleteObject(Object Obj); void ChangeObject(Object Obj, ObjectType NewType); +void ChangeObject(Object Obj, INSTANCEATTRIBUTE Attribute, uint32 Value); +void ChangeObject(Object Obj, ObjectType NewType, uint32 Value); int GetObjectPriority(Object Obj); void PlaceObject(Object Obj, Object Con, bool Append); +void CutObject(Object Obj); +void MoveObject(Object Obj, Object Con); Object AppendObject(Object Con, ObjectType Type); +Object SetObject(Object Con, ObjectType Type, uint32 CreatureID); +Object CopyObject(Object Con, Object Source); +Object SplitObject(Object Obj, int Count); +void MergeObjects(Object Obj, Object Dest); Object GetFirstContainerObject(Object Con); Object GetContainerObject(Object Con, int Index); -void GetObjectCoordinates(Object Obj, int *x, int *y, int *z); -uint8 GetMapContainerFlags(Object Obj); Object GetMapContainer(int x, int y, int z); Object GetMapContainer(Object Obj); Object GetFirstObject(int x, int y, int z); +//GetFirstSpecObject +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 #endif //TIBIA_MAP_HH_ diff --git a/src/objects.hh b/src/objects.hh index 61a0185..eec0565 100644 --- a/src/objects.hh +++ b/src/objects.hh @@ -52,6 +52,14 @@ struct ObjectType { return this->TypeID == TYPEID_CREATURE_CONTAINER; } + bool operator==(const ObjectType &Other) const { + return this->TypeID == Other.TypeID; + } + + bool operator!=(const ObjectType &Other) const { + return this->TypeID != Other.TypeID; + } + // DATA // ========================================================================= int TypeID; diff --git a/src/stubs.hh b/src/stubs.hh index bc89d12..0926a52 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -18,6 +18,7 @@ extern void AbortWriter(void); extern uint32 AddDynamicString(const char *Text); extern void AnnounceChangedCreature(uint32 CreatureID, int Type); extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3); +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); @@ -33,6 +34,7 @@ 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); extern void MoveCreatures(int Delay); extern void NetLoadCheck(void); extern void NetLoadSummary(void); -- cgit v1.2.3