aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-05-26 01:44:13 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-05-26 01:44:13 -0300
commitfbb392953c5af29b6a0924590c24a05befb72e56 (patch)
treed999d2cdb92824f1dbbb93111164696fba607328
parentc2f41059c71a0c7bfc0b64a7f53334d3bfd0ee76 (diff)
downloadgame-fbb392953c5af29b6a0924590c24a05befb72e56.tar.gz
game-fbb392953c5af29b6a0924590c24a05befb72e56.zip
more object functions
-rw-r--r--Makefile2
-rw-r--r--reference/game.c962
-rw-r--r--src/map.cc394
-rw-r--r--src/map.hh78
-rw-r--r--src/objects.hh8
-rw-r--r--src/stubs.hh2
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 <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;
+}
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);