diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-05-26 01:44:13 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-05-26 01:44:13 -0300 |
| commit | fbb392953c5af29b6a0924590c24a05befb72e56 (patch) | |
| tree | d999d2cdb92824f1dbbb93111164696fba607328 | |
| parent | c2f41059c71a0c7bfc0b64a7f53334d3bfd0ee76 (diff) | |
| download | game-fbb392953c5af29b6a0924590c24a05befb72e56.tar.gz game-fbb392953c5af29b6a0924590c24a05befb72e56.zip | |
more object functions
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | reference/game.c | 962 | ||||
| -rw-r--r-- | src/map.cc | 394 | ||||
| -rw-r--r-- | src/map.hh | 78 | ||||
| -rw-r--r-- | src/objects.hh | 8 | ||||
| -rw-r--r-- | src/stubs.hh | 2 |
6 files changed, 388 insertions, 1058 deletions
@@ -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)
{
@@ -8,30 +8,6 @@ #include <dirent.h> -// 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; +} @@ -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); |
