aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-13 03:35:56 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-13 03:35:56 -0300
commit15b40c7915fca14e537534ae9ba03f3add965943 (patch)
treede3ee3c61962b300bd7457cc81845e7891c4b896
parent7d298e5a4119df0910daa070af1d23567a83e90c (diff)
downloadgame-15b40c7915fca14e537534ae9ba03f3add965943.tar.gz
game-15b40c7915fca14e537534ae9ba03f3add965943.zip
more work on `operate.cc`
-rw-r--r--Makefile6
-rw-r--r--TODO.md4
-rw-r--r--reference/game.c1806
-rw-r--r--src/cr.hh1
-rw-r--r--src/crcombat.cc1
-rw-r--r--src/crmain.cc5
-rw-r--r--src/crskill.cc2
-rw-r--r--src/info.cc11
-rw-r--r--src/info.hh1
-rw-r--r--src/magic.cc2
-rw-r--r--src/map.cc27
-rw-r--r--src/map.hh1
-rw-r--r--src/moveuse.cc56
-rw-r--r--src/moveuse.hh9
-rw-r--r--src/operate.cc974
-rw-r--r--src/operate.hh40
-rw-r--r--src/stubs.hh16
17 files changed, 1069 insertions, 1893 deletions
diff --git a/Makefile b/Makefile
index 3569eba..c937038 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ endif
HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/config.hh $(SRCDIR)/connection.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/enums.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/thread.hh
-$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/config.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj
+$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/config.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj
echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
$(BUILDDIR)/config.obj: $(SRCDIR)/config.cc $(HEADERS)
@@ -58,6 +58,10 @@ $(BUILDDIR)/map.obj: $(SRCDIR)/map.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
+$(BUILDDIR)/moveuse.obj: $(SRCDIR)/moveuse.cc $(HEADERS)
+ @mkdir -p $(@D)
+ $(CC) -c $(CFLAGS) -o $@ $<
+
$(BUILDDIR)/objects.obj: $(SRCDIR)/objects.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
diff --git a/TODO.md b/TODO.md
index 2d28ca4..51efb7f 100644
--- a/TODO.md
+++ b/TODO.md
@@ -28,5 +28,9 @@ The decompiled file has ~115K lines of C. If we take ~15K lines to be rubbish, t
- Replace unsafe libc functions like `strcpy`, `strncpy`, `strcat`, `sprintf` etc...
- Handle connections inline with `poll`/`epoll` (probably?).
- Remove exceptions.
+ - Would be desirable but I feel it could change too much of the original code flow while also
+ littering functions with early return checks like `if(err != NOERROR) { return err }` although
+ we could also have some macros to simplify this since we know we only use `RESULT` for errors.
+ But then would we be in a better place?
- Review signal usage for timing (SIGALRM, etc...).
- Support Windows.
diff --git a/reference/game.c b/reference/game.c
index b68c771..9a9762d 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -18375,1812 +18375,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-void CheckMapPlace(ulong CreatureID,ObjectType *Type,Object *MapCon)
-
-{
- bool bVar1;
- bool bVar2;
- undefined4 *puVar3;
- int iVar4;
- int iVar5;
- int iVar6;
- int iVar7;
- undefined4 uVar8;
- int local_38;
- int x;
- int y;
- int z;
-
- z = MapCon->ObjectID;
- // try { // try from 0808fec5 to 08090120 has its CatchHandler @ 08090127
- GetObjectCoordinates((Object *)&z,&local_38,&x,&y);
- bVar1 = ObjectType::getFlag(Type,UNMOVE);
- if (!bVar1) {
- uVar8 = 0;
- iVar6 = y;
- bVar1 = CoordinateFlag();
- if (!bVar1) {
- iVar4 = 0x29;
- bVar1 = ObjectType::getFlag(Type,HANG);
- iVar7 = y;
- iVar5 = x;
- if (!bVar1) goto LAB_0808ffd8;
- bVar1 = false;
- uVar8 = 0x2a;
- iVar4 = x;
- iVar6 = y;
- bVar2 = CoordinateFlag();
- if (bVar2) {
-LAB_080900f0:
- bVar1 = true;
- }
- else {
- uVar8 = 0x2b;
- bVar2 = CoordinateFlag();
- iVar4 = iVar5;
- iVar6 = iVar7;
- if (bVar2) goto LAB_080900f0;
- }
- if (!bVar1) goto LAB_0808ffd8;
- }
- }
- iVar5 = y;
- if (CreatureID == 0) {
- return;
- }
- bVar1 = false;
- uVar8 = 0;
- iVar6 = y;
- bVar2 = CoordinateFlag();
- if (bVar2) {
- uVar8 = 0x20;
- bVar1 = CoordinateFlag();
- bVar1 = !bVar1;
- iVar6 = iVar5;
- }
- if (bVar1) {
- return;
- }
- iVar4 = 0x20;
- bVar1 = ObjectType::getFlag(Type,UNPASS);
- if (bVar1) goto LAB_0808ffd8;
- bVar1 = false;
- bVar2 = CoordinateFlag();
- if (bVar2) {
- bVar1 = CoordinateFlag();
- bVar1 = !bVar1;
- }
- if (bVar1) {
- return;
- }
- bVar1 = false;
- uVar8 = 0x2a;
- iVar4 = x;
- iVar6 = y;
- bVar2 = CoordinateFlag();
- if (bVar2) {
-LAB_0808ffb3:
- bVar1 = true;
- }
- else {
- uVar8 = 0x2b;
- bVar2 = CoordinateFlag();
- iVar4 = x;
- iVar6 = y;
- if (bVar2) goto LAB_0808ffb3;
- }
- if (bVar1) {
- iVar4 = 0x29;
- bVar1 = ObjectType::getFlag(Type,HANG);
- if (bVar1) {
- return;
- }
- }
-LAB_0808ffd8:
- puVar3 = (undefined4 *)__cxa_allocate_exception(4,iVar4,iVar6,uVar8);
- *puVar3 = 4;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
-}
-
-void CheckContainerPlace(ObjectType *Type,Object *Con,Object *oldObj)
-
-{
- bool bVar1;
- int iVar2;
- ulong uVar3;
- undefined4 *puVar4;
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 08090283 to 08090364 has its CatchHandler @ 08090394
- GetSpecialObject((SPECIALMEANING)local_2c);
- if (Type->TypeID != local_2c[0].ObjectID) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST);
- if (!bVar1) {
- bVar1 = ObjectType::getFlag(Type,UNMOVE);
- if (bVar1) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 2;
- }
- else {
- bVar1 = ObjectType::getFlag(Type,TAKE);
- if (bVar1) {
- local_2c[0].ObjectID = NONE.ObjectID;
- if (oldObj->ObjectID != NONE.ObjectID) {
- return;
- }
- local_3c[0] = (Object)Con->ObjectID;
- iVar2 = CountObjectsInContainer(local_3c);
- Object::getObjectType(local_2c);
- uVar3 = ObjectType::getAttribute((ObjectType *)local_2c,CAPACITY);
- if (iVar2 < (int)uVar3) {
- return;
- }
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 10;
- }
- else {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 3;
- }
- }
- // WARNING: Subroutine does not return
- __cxa_throw(puVar4,&RESULT::typeinfo,0);
- }
- }
- return;
-}
-
-
-
-void CheckDepotSpace(ulong CreatureID,Object *Source,Object *Destination,int Count)
-
-{
- bool bVar1;
- TCreature *pTVar2;
- undefined4 *puVar3;
- TCreature *cr;
- Object *pOVar4;
- Object local_3c [4];
- Object local_2c [7];
-
- if (CreatureID == 0) {
- return;
- }
- // try { // try from 080903d9 to 08090536 has its CatchHandler @ 08090540
- pTVar2 = GetCreature(CreatureID);
- if (pTVar2 == (TCreature *)0x0) {
- error("CheckDepotSpace: Kreatur %lu existiert nicht.\n",CreatureID);
- }
- else {
- local_2c[0].ObjectID = NONE.ObjectID;
- if (Destination->ObjectID != NONE.ObjectID) {
- if (pTVar2->Type != PLAYER) {
- return;
- }
- bVar1 = false;
- if ((pTVar2[1].super_TSkillBase.TimerList[6] == (TSkill *)NONE.ObjectID) ||
- (Count <= (int)pTVar2[1].super_TSkillBase.TimerList[8])) {
- bVar1 = true;
- }
- if (bVar1) {
- return;
- }
- while( true ) {
- local_2c[0].ObjectID = NONE.ObjectID;
- bVar1 = false;
- local_3c[0].ObjectID = NONE.ObjectID;
- if ((Source->ObjectID != NONE.ObjectID) &&
- (Object::getObjectType(local_3c), local_3c[0].ObjectID != 0)) {
- bVar1 = true;
- }
- if (!bVar1) break;
- local_3c[0].ObjectID = (ulong)pTVar2[1].super_TSkillBase.TimerList[6];
- if ((TSkill *)Source->ObjectID == (TSkill *)local_3c[0].ObjectID) {
- return;
- }
- Object::getContainer(local_2c);
- Source->ObjectID = (ulong)local_2c[0];
- }
- while( true ) {
- pOVar4 = Destination;
- Object::getObjectType(local_3c);
- if (local_3c[0].ObjectID == 0) {
- return;
- }
- local_3c[0].ObjectID = (ulong)pTVar2[1].super_TSkillBase.TimerList[6];
- if ((TSkill *)Destination->ObjectID == (TSkill *)local_3c[0].ObjectID) break;
- Object::getContainer(local_2c);
- local_3c[0].ObjectID = local_2c[0].ObjectID;
- Destination->ObjectID = (ulong)local_2c[0];
- }
- puVar3 = (undefined4 *)__cxa_allocate_exception(4,pOVar4);
- *puVar3 = 10;
- goto LAB_080904cb;
- }
- error("CheckDepotSpace: Ziel existiert nicht.\n");
- }
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
-LAB_080904cb:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
-}
-
-void CheckInventoryPlace(ObjectType *Type,Object *Con,Object *OldObj)
-
-{
- uint uVar1;
- bool bVar2;
- int ClothesType;
- ulong uVar3;
- ulong uVar4;
- ulong uVar5;
- undefined4 *puVar6;
- int Position;
- int iVar7;
- ulong uVar8;
- undefined4 uVar9;
- ulong local_ac;
- Object Help;
- Object local_9c [4];
- ulong local_8c [4];
- ulong local_7c;
- ulong local_6c [4];
- ulong local_5c;
- ulong local_4c [4];
- ulong local_3c;
- Object local_2c [7];
-
- local_2c[0] = (Object)Con->ObjectID;
- // try { // try from 08090a00 to 08090e39 has its CatchHandler @ 08090ea0
- uVar3 = GetObjectBodyPosition(local_2c);
- uVar1 = uVar3 - 5;
- if ((1 < uVar1) && (uVar3 != 10)) {
- bVar2 = ObjectType::getFlag(Type,CLOTHES);
- if (!bVar2) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0xb;
- goto LAB_08090c8d;
- }
- uVar4 = ObjectType::getAttribute(Type,BODYPOSITION);
- if (uVar4 == 0) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0xc;
- goto LAB_08090c8d;
- }
- if (uVar3 != uVar4) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0xd;
- goto LAB_08090c8d;
- }
- }
- local_2c[0] = (Object)Con->ObjectID;
- uVar4 = GetObjectCreatureID(local_2c);
- bVar2 = ObjectType::getFlag(Type,CLOTHES);
- if (((!bVar2) || (uVar5 = ObjectType::getAttribute(Type,BODYPOSITION), uVar5 != 0)) ||
- (1 < uVar1)) {
- bVar2 = false;
- uVar5 = uVar4;
- uVar8 = uVar3;
- GetBodyObject((ulong)&local_ac,uVar4);
- local_9c[0].ObjectID = NONE.ObjectID;
- local_8c[0] = NONE.ObjectID;
- if (local_ac != NONE.ObjectID) {
- uVar5 = uVar4;
- GetBodyObject((ulong)local_8c,uVar4);
- local_7c = OldObj->ObjectID;
- uVar8 = uVar3;
- local_6c[0] = local_7c;
- if (local_8c[0] != local_7c) {
- bVar2 = true;
- }
- }
- if (!bVar2) {
- if (1 < uVar1) {
- return;
- }
- iVar7 = 5;
- do {
- GetBodyObject((ulong)&local_ac,uVar4);
- local_9c[0].ObjectID = NONE.ObjectID;
- if ((local_ac != NONE.ObjectID) &&
- (local_9c[0] = (Object)OldObj->ObjectID, local_ac != local_9c[0].ObjectID)) {
- Object::getObjectType(local_9c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_9c,CLOTHES);
- if (bVar2) {
- Object::getObjectType(local_9c);
- uVar3 = ObjectType::getAttribute((ObjectType *)local_9c,BODYPOSITION);
- if (uVar3 == 0) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0xf;
- goto LAB_08090c8d;
- }
- }
- bVar2 = ObjectType::getFlag(Type,WEAPON);
- if (((bVar2) || (bVar2 = ObjectType::getFlag(Type,THROW), bVar2)) ||
- ((bVar2 = ObjectType::getFlag(Type,BOW), bVar2 ||
- (bVar2 = ObjectType::getFlag(Type,WAND), bVar2)))) {
- Object::getObjectType(local_9c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_9c,WEAPON);
- if (!bVar2) {
- Object::getObjectType(local_9c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_9c,THROW);
- if (!bVar2) {
- Object::getObjectType(local_9c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_9c,BOW);
- if (!bVar2) {
- Object::getObjectType(local_9c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_9c,WAND);
- if (!bVar2) goto LAB_08090b3f;
- }
- }
- }
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0x10;
- goto LAB_08090c8d;
- }
- }
-LAB_08090b3f:
- iVar7 = iVar7 + 1;
- if (6 < iVar7) {
- return;
- }
- } while( true );
- }
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,uVar5,uVar8);
- *puVar6 = 4;
- goto LAB_08090c8d;
- }
- bVar2 = false;
- GetBodyObject((ulong)local_2c,uVar4);
- local_3c = NONE.ObjectID;
- local_4c[0] = NONE.ObjectID;
- if (local_2c[0].ObjectID == NONE.ObjectID) {
-LAB_08090dd4:
- uVar9 = 6;
- uVar3 = uVar4;
- GetBodyObject((ulong)local_6c,uVar4);
- local_7c = NONE.ObjectID;
- local_8c[0] = NONE.ObjectID;
- if (local_6c[0] != NONE.ObjectID) {
- uVar9 = 6;
- GetBodyObject((ulong)local_8c,uVar4);
- local_ac = OldObj->ObjectID;
- uVar3 = uVar4;
- local_9c[0].ObjectID = local_ac;
- if (local_8c[0] != local_ac) goto LAB_08090e56;
- }
- }
- else {
- uVar9 = 5;
- uVar3 = uVar4;
- GetBodyObject((ulong)local_4c,uVar4);
- local_6c[0] = OldObj->ObjectID;
- local_5c = local_6c[0];
- if (local_4c[0] == local_6c[0]) goto LAB_08090dd4;
-LAB_08090e56:
- bVar2 = true;
- }
- if (!bVar2) {
- return;
- }
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,uVar3,uVar9);
- *puVar6 = 0xe;
-LAB_08090c8d:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar6,&RESULT::typeinfo,0);
-}
-
-
-
-void CheckWeight(ulong CreatureID,Object *Obj,int Count)
-
-{
- TSkill *this;
- bool bVar1;
- ulong uVar2;
- TCreature *pTVar3;
- int iVar4;
- int iVar5;
- int iVar6;
- undefined4 *puVar7;
- TSkill *sk;
- TCreature *cr;
- Object local_2c [7];
-
- local_2c[0] = (Object)Obj->ObjectID;
- // try { // try from 08090ee0 to 08091075 has its CatchHandler @ 08091078
- uVar2 = GetObjectCreatureID(local_2c);
- if (uVar2 == CreatureID) {
- return;
- }
- pTVar3 = GetCreature(CreatureID);
- if (pTVar3 == (TCreature *)0x0) {
- error("CheckWeight: Kreatur %d existiert nicht.\n",CreatureID);
-LAB_08091005:
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = 0xffffffff;
- }
- else {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,TAKE);
- if (bVar1) {
- if (pTVar3->Type == PLAYER) {
- bVar1 = CheckRight(CreatureID,UNLIMITED_CAPACITY);
- if (bVar1) {
- return;
- }
- if ((pTVar3->Type == PLAYER) &&
- (bVar1 = CheckRight(CreatureID,ZERO_CAPACITY), bVar1)) goto LAB_08090fbd;
- }
- this = (pTVar3->super_TSkillBase).Skills[5];
- if (this == (TSkill *)0x0) {
- error("CheckWeight: Skill CARRYSTRENGTH existiert nicht.\n");
- goto LAB_08091005;
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CUMULATIVE);
- if (bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- iVar4 = GetWeight(local_2c,Count);
- }
- else {
- cr = (TCreature *)Obj->ObjectID;
- iVar4 = GetCompleteWeight((Object *)&cr);
- }
- iVar5 = GetInventoryWeight(CreatureID);
- iVar6 = TSkill::Get(this);
- if (iVar4 + iVar5 <= iVar6 * 100) {
- return;
- }
- }
-LAB_08090fbd:
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = 8;
- }
- // WARNING: Subroutine does not return
- __cxa_throw(puVar7,&RESULT::typeinfo,0);
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: sk
-
-void CheckWeight(ulong CreatureID,ObjectType *Type,ulong Data,int oldWeight)
-
-{
- TSkill *this;
- bool bVar1;
- TCreature *pTVar2;
- ulong uVar3;
- int iVar4;
- int iVar5;
- undefined4 *puVar6;
- TCreature *cr;
- TSkill *sk;
-
- // try { // try from 080910a8 to 080911f2 has its CatchHandler @ 080911f5
- pTVar2 = GetCreature(CreatureID);
- if (pTVar2 == (TCreature *)0x0) {
- error("CheckWeight: Kreatur %d existiert nicht.\n",CreatureID);
-LAB_0809118c:
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0xffffffff;
- }
- else {
- bVar1 = ObjectType::getFlag(Type,TAKE);
- if (bVar1) {
- if (pTVar2->Type == PLAYER) {
- bVar1 = CheckRight(CreatureID,UNLIMITED_CAPACITY);
- if (bVar1) {
- return;
- }
- if ((pTVar2->Type == PLAYER) &&
- (bVar1 = CheckRight(CreatureID,ZERO_CAPACITY), bVar1)) goto LAB_08091156;
- }
- this = (pTVar2->super_TSkillBase).Skills[5];
- if (this == (TSkill *)0x0) {
- error("CheckWeight: Skill CARRYSTRENGTH existiert nicht.\n");
- goto LAB_0809118c;
- }
- uVar3 = ObjectType::getAttribute(Type,WEIGHT);
- bVar1 = ObjectType::getFlag(Type,CUMULATIVE);
- if ((bVar1) && (1 < Data)) {
- uVar3 = Data * uVar3;
- }
- if ((int)uVar3 <= oldWeight) {
- return;
- }
- iVar4 = GetInventoryWeight(CreatureID);
- iVar5 = TSkill::Get(this);
- if ((int)(uVar3 + iVar4) <= oldWeight + iVar5 * 100) {
- return;
- }
- }
-LAB_08091156:
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 8;
- }
- // WARNING: Subroutine does not return
- __cxa_throw(puVar6,&RESULT::typeinfo,0);
-}
-
-
-
-void __regparm1 NotifyCreature(ulong CreatureID,Object *Obj,bool Inventory)
-
-{
- bool bVar1;
- TCreature *this;
- undefined3 in_stack_00000009;
- char in_stack_0000000c;
- TCreature *cr;
- Object OStack_2c;
- bool Inventory_local;
-
- if (Obj != (Object *)0x0) {
- Object::getObjectType(&stack0xffffffd4);
- if (OStack_2c.ObjectID != 99) {
- this = GetCreature((ulong)Obj);
- if (this == (TCreature *)0x0) {
- error("NotifyCreature: Kreatur existiert nicht.\n",_Inventory);
- }
- else {
- Object::getObjectType(&stack0xffffffd4);
- bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffffd4,LIGHT);
- if ((bVar1) && (in_stack_0000000c != '\0')) {
- AnnounceChangedCreature((ulong)Obj,2);
- }
- TCreature::NotifyChangeInventory(this);
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Inventory_local
-
-void __regparm3 NotifyCreature(ulong CreatureID,ObjectType *Type,bool Inventory)
-
-{
- bool bVar1;
- TCreature *this;
- TCreature *cr;
- ulong in_stack_00000004;
- ObjectType *in_stack_00000008;
- char in_stack_0000000c;
- bool Inventory_local;
-
- if (in_stack_00000004 == 0) {
- return;
- }
- this = GetCreature(in_stack_00000004);
- if (this != (TCreature *)0x0) {
- bVar1 = ObjectType::getFlag(in_stack_00000008,LIGHT);
- if ((bVar1) && (in_stack_0000000c != '\0')) {
- AnnounceChangedCreature(in_stack_00000004,2);
- }
- TCreature::NotifyChangeInventory(this);
- return;
- }
- error("NotifyCreature: Kreatur existiert nicht.\n");
- return;
-}
-
-
-
-void NotifyAllCreatures(Object *Obj,int Type,Object *OldCon)
-
-{
- bool bVar1;
- ulong uVar2;
- ulong uVar3;
- TCreature *pTVar4;
- uint uVar5;
- uint uVar6;
- char *Text;
- int local_a4;
- int oldx;
- int oldy;
- int oldz;
- int x;
- int y;
- int z;
- TFindCreatures Search;
- undefined1 local_5c [4];
- TFindCreatures Search1;
- Object local_2c [7];
-
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID != 99) {
- return;
- }
- if (Type != 3) {
- local_2c[0] = (Object)Obj->ObjectID;
- TFindCreatures::TFindCreatures((TFindCreatures *)&z,10,10,local_2c,7);
- while (uVar2 = TFindCreatures::getNext((TFindCreatures *)&z), uVar2 != 0) {
- uVar3 = Object::getCreatureID(Obj);
- pTVar4 = GetCreature(uVar2);
- (*pTVar4->_vptr_TCreature[9])(pTVar4,uVar3,Type);
- }
- return;
- }
- bVar1 = Object::exists(OldCon);
- if (bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- GetObjectCoordinates(local_2c,&oldz,&x,&y);
- local_2c[0] = (Object)OldCon->ObjectID;
- GetObjectCoordinates(local_2c,&local_a4,&oldx,&oldy);
- uVar5 = oldz - local_a4;
- if (0x7fffffff < uVar5) {
- uVar5 = -uVar5;
- }
- if ((int)uVar5 < 0x15) {
- uVar5 = x - oldx;
- if (0x7fffffff < uVar5) {
- uVar5 = -uVar5;
- }
- if ((int)uVar5 < 0x15) {
- uVar5 = x - oldx;
- if (0x7fffffff < uVar5) {
- uVar5 = -uVar5;
- }
- uVar6 = oldz - local_a4;
- if (0x7fffffff < uVar6) {
- uVar6 = -uVar6;
- }
- TFindCreatures::TFindCreatures
- ((TFindCreatures *)&z,(int)(uVar6 + 1) / 2 + 10,
- (int)(uVar5 + 1) / 2 + 10,(oldz + local_a4) / 2,(oldx + x) / 2,7);
- while (uVar2 = TFindCreatures::getNext((TFindCreatures *)&z), uVar2 != 0) {
- uVar3 = Object::getCreatureID(Obj);
- pTVar4 = GetCreature(uVar2);
- (*pTVar4->_vptr_TCreature[9])(pTVar4,uVar3,2);
- }
- return;
- }
- }
- TFindCreatures::TFindCreatures((TFindCreatures *)local_5c,10,10,local_a4,oldx,7);
- while (uVar2 = TFindCreatures::getNext((TFindCreatures *)local_5c), uVar2 != 0) {
- uVar3 = Object::getCreatureID(Obj);
- pTVar4 = GetCreature(uVar2);
- (*pTVar4->_vptr_TCreature[9])(pTVar4,uVar3,2);
- }
- TFindCreatures::TFindCreatures((TFindCreatures *)&z,10,10,oldz,x,7);
- while (uVar2 = TFindCreatures::getNext((TFindCreatures *)&z), uVar2 != 0) {
- uVar3 = Object::getCreatureID(Obj);
- pTVar4 = GetCreature(uVar2);
- (*pTVar4->_vptr_TCreature[9])(pTVar4,uVar3,2);
- }
- return;
- }
- Text = &DAT_080ff300;
- }
- else {
- Text = &DAT_080ff2c0;
- }
- error(Text);
- return;
-}
-
-
-
-void NotifyTrades(Object *Obj)
-
-{
- bool bVar1;
- ulong ID;
- ulong CharacterID;
- TPlayer *this;
- TPlayer *pl;
- TPlayer *pTVar2;
- char *pcVar3;
- Object *Obj_00;
- Object OStack_8c;
- bool Affected;
- Object Help_1;
- Object local_7c [4];
- Object local_6c;
- Object Help;
- undefined1 local_5c [4];
- TFindCreatures Search;
- Object local_2c;
- Object TradeObject;
-
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- Object::getObjectType(&local_2c);
- if (local_2c.ObjectID != 99) {
- Obj_00 = &local_2c;
- local_2c = (Object)Obj->ObjectID;
- pcVar3 = (char *)0xa;
- pTVar2 = (TPlayer *)0xc;
- TFindCreatures::TFindCreatures((TFindCreatures *)local_5c,0xc,10,Obj_00,1);
-LAB_08091720:
- CharacterID = TFindCreatures::getNext((TFindCreatures *)local_5c);
- if (CharacterID != 0) {
- this = GetPlayer(CharacterID);
- if (this == (TPlayer *)0x0) {
- error("NotifyTrade: Spieler existiert nicht.\n",pTVar2,pcVar3,Obj_00);
- }
- else {
- Obj_00 = (Object *)0x0;
- pcVar3 = (char *)0x1;
- pTVar2 = this;
- TPlayer::InspectTrade((TPlayer *)&local_2c,SUB41(this,0),1);
- local_6c = (Object)NONE.ObjectID;
- if (local_2c.ObjectID != NONE.ObjectID) {
- local_6c = (Object)Obj->ObjectID;
- bVar1 = local_2c.ObjectID == local_6c.ObjectID;
- if (!bVar1) {
- while( true ) {
- Object::getObjectType(local_7c);
- if (local_7c[0].ObjectID == 0) break;
- local_7c[0].ObjectID = local_6c.ObjectID;
- if (local_2c.ObjectID == local_6c.ObjectID) {
- bVar1 = true;
- }
- Object::getContainer(&stack0xffffff74);
- local_7c[0].ObjectID = OStack_8c.ObjectID;
- local_6c.ObjectID = OStack_8c.ObjectID;
- }
- if (!bVar1) {
- OStack_8c.ObjectID = local_2c.ObjectID;
- while( true ) {
- pTVar2 = (TPlayer *)&stack0xffffff74;
- Object::getObjectType(local_7c);
- if (local_7c[0].ObjectID == 0) break;
- local_7c[0] = (Object)Obj->ObjectID;
- if (OStack_8c.ObjectID == local_7c[0].ObjectID) {
- bVar1 = true;
- }
- Object::getContainer(&local_6c);
- OStack_8c.ObjectID = local_6c.ObjectID;
- local_7c[0].ObjectID = OStack_8c.ObjectID;
- }
- if (!bVar1) goto LAB_08091720;
- }
- }
- SendCloseTrade((this->super_TCreature).Connection);
- pcVar3 = "Trade cancelled.";
- pTVar2 = (TPlayer *)0x17;
- SendMessage((this->super_TCreature).Connection,0x17,"Trade cancelled.");
- TPlayer::RejectTrade(this);
- }
- }
- goto LAB_08091720;
- }
- }
- }
- else {
- error(&DAT_080ff360);
- }
- return;
-}
-
-
-
-void NotifyDepot(ulong CreatureID,Object *Obj,int Count)
-
-{
- bool bVar1;
- TCreature *pTVar2;
- undefined4 *puVar3;
- TCreature *cr;
- Object local_3c [4];
- Object local_2c [7];
-
- if (CreatureID != 0) {
- pTVar2 = GetCreature(CreatureID);
- if (pTVar2 == (TCreature *)0x0) {
- error("NotifyDepot: Kreatur %lu existiert nicht.\n",CreatureID);
- }
- else {
- bVar1 = Object::exists(Obj);
- if (!bVar1) {
- error("NotifyDepot: Objekt existiert nicht.\n");
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
- }
- if ((pTVar2->Type == PLAYER) &&
- (local_2c[0].ObjectID = NONE.ObjectID,
- pTVar2[1].super_TSkillBase.TimerList[6] != (TSkill *)NONE.ObjectID)) {
- while (Object::getObjectType(local_2c), local_2c[0].ObjectID != 0) {
- local_2c[0].ObjectID = (ulong)pTVar2[1].super_TSkillBase.TimerList[6];
- if ((TSkill *)Obj->ObjectID == (TSkill *)local_2c[0].ObjectID) {
- pTVar2[1].super_TSkillBase.TimerList[8] =
- (TSkill *)
- ((int)&pTVar2[1].super_TSkillBase.TimerList[8]->_vptr_TSkill + Count);
- print();
- return;
- }
- Object::getContainer(local_3c);
- local_2c[0].ObjectID = local_3c[0].ObjectID;
- Obj->ObjectID = (ulong)local_3c[0];
- }
- }
- }
- }
- return;
-}
-
-
-
-void CloseContainer(Object *Con,bool Force)
-
-{
- bool bVar1;
- bool bVar2;
- ulong ID;
- ulong CharacterID;
- TPlayer *this;
- int con;
- int ContNr;
- bool Affected;
- TPlayer *pl;
- Object OStack_7c;
- bool Force_local;
- Object local_6c [4];
- undefined1 local_5c [4];
- TFindCreatures Search;
- _func_int_varargs **local_2c;
- Object Obj;
-
- bVar2 = Object::exists(Con);
- if (bVar2) {
- Object::getObjectType((Object *)&local_2c);
- if (local_2c != (_func_int_varargs **)0x63) {
- local_2c = (_func_int_varargs **)Con->ObjectID;
- TFindCreatures::TFindCreatures((TFindCreatures *)local_5c,0xc,10,(Object *)&local_2c,1);
- while (CharacterID = TFindCreatures::getNext((TFindCreatures *)local_5c),
- CharacterID != 0) {
- this = GetPlayer(CharacterID);
- if (this == (TPlayer *)0x0) {
- error("CloseContainer: Spieler existiert nicht.\n");
- }
- else {
- ContNr = 0;
- do {
- bVar2 = false;
- TPlayer::GetOpenContainer((TPlayer *)&local_2c,(int)this);
- while( true ) {
- bVar1 = false;
- local_6c[0].ObjectID = NONE.ObjectID;
- OStack_7c.ObjectID = NONE.ObjectID;
- if ((local_2c != (_func_int_varargs **)NONE.ObjectID) &&
- (Object::getObjectType(&stack0xffffff84), OStack_7c.ObjectID != 0)) {
- bVar1 = true;
- }
- if (!bVar1) break;
- OStack_7c = (Object)Con->ObjectID;
- if (local_2c == (_func_int_varargs **)OStack_7c.ObjectID) {
- bVar2 = true;
- }
- Object::getContainer(local_6c);
- local_2c = (_func_int_varargs **)local_6c[0].ObjectID;
- }
- if (bVar2) {
- if (!Force) {
- OStack_7c = (Object)Con->ObjectID;
- bVar2 = ObjectAccessible((this->super_TCreature).ID,&stack0xffffff84
- ,1);
- if (bVar2) {
- SendContainer((this->super_TCreature).Connection,ContNr);
- goto LAB_08091b89;
- }
- }
- local_6c[0].ObjectID = NONE.ObjectID;
- TPlayer::SetOpenContainer(this,ContNr,local_6c);
- SendCloseContainer((this->super_TCreature).Connection,ContNr);
- }
-LAB_08091b89:
- ContNr = ContNr + 1;
- } while (ContNr < 0x10);
- }
- }
- }
- }
- else {
- error(&DAT_080ff4a0);
- }
- return;
-}
-
-
-
-Object Create(Object *Con,ObjectType *Type,ulong Value)
-
-{
- bool bVar1;
- ulong uVar2;
- TCreature *this;
- undefined4 *puVar3;
- int _TypeID;
- ulong in_stack_00000010;
- char *Text;
- ulong newCreature;
- int x;
- int y;
- int z;
- Object Obj;
- Object local_5c [4];
- Object local_4c;
- Object Top;
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 08091c0b to 0809230e has its CatchHandler @ 08092330
- bVar1 = Object::exists((Object *)Type);
- if (bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER);
- if (!bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST);
- if (!bVar1) {
- Text = "Create: Zielobjekt ist kein Container.\n";
- goto LAB_080922e0;
- }
- }
- ObjectType::setTypeID((ObjectType *)local_2c,0);
- if (*(ulong *)Value != local_2c[0].ObjectID) {
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID == 0) {
- local_2c[0].ObjectID = Type->TypeID;
- ObjectType::setTypeID((ObjectType *)local_3c,*(int *)Value);
- CheckMapPlace(0,(ObjectType *)local_3c,local_2c);
- }
- else {
- Object::getObjectType(local_3c);
- bVar1 = false;
- if ((0 < (int)local_3c[0].ObjectID) && ((int)local_3c[0].ObjectID < 0xb)) {
- bVar1 = true;
- }
- if (bVar1) {
- local_4c.ObjectID = NONE.ObjectID;
- local_3c[0].ObjectID = Type->TypeID;
- ObjectType::setTypeID((ObjectType *)local_2c,*(int *)Value);
- CheckInventoryPlace((ObjectType *)local_2c,local_3c,&local_4c);
- }
- else {
- local_3c[0].ObjectID = NONE.ObjectID;
- local_2c[0].ObjectID = Type->TypeID;
- ObjectType::setTypeID((ObjectType *)&local_4c,*(int *)Value);
- CheckContainerPlace((ObjectType *)&local_4c,local_2c,local_3c);
- }
- local_4c.ObjectID = Type->TypeID;
- uVar2 = GetObjectCreatureID(&local_4c);
- if (uVar2 != 0) {
- ObjectType::setTypeID((ObjectType *)&local_4c,*(int *)Value);
- CheckWeight(uVar2,(ObjectType *)&local_4c,in_stack_00000010,0);
- }
- }
- Object::getObjectType(&local_4c);
- if ((local_4c.ObjectID == 0) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)Value,CUMULATIVE), bVar1)) {
- if (in_stack_00000010 == 0) {
- in_stack_00000010 = 1;
- }
- local_4c.ObjectID = Type->TypeID;
- GetObjectCoordinates(&local_4c,(int *)&newCreature,&x,&y);
- GetTopObject((int)&local_4c,newCreature,x,(bool)(undefined1)y);
- bVar1 = false;
- local_3c[0].ObjectID = NONE.ObjectID;
- local_2c[0].ObjectID = NONE.ObjectID;
- if (local_4c.ObjectID != NONE.ObjectID) {
- Object::getObjectType(local_2c);
- ObjectType::setTypeID((ObjectType *)local_5c,*(int *)Value);
- if ((local_2c[0].ObjectID == local_5c[0].ObjectID) &&
- (uVar2 = Object::getAttribute(&local_4c,AMOUNT),
- uVar2 + in_stack_00000010 < 0x65)) {
- bVar1 = true;
- }
- }
- if (bVar1) {
- uVar2 = Object::getAttribute(&local_4c,AMOUNT);
- z = local_4c.ObjectID;
- Change((Object *)&z,AMOUNT,uVar2 + in_stack_00000010);
- Con->ObjectID = (ulong)local_4c;
- return (Object)(ulong)Con;
- }
- }
- ObjectType::setTypeID((ObjectType *)local_5c,*(int *)Value);
- local_4c.ObjectID = Type->TypeID;
- SetObject((Object *)&z,(ObjectType *)&local_4c,(ulong)local_5c);
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,CUMULATIVE);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,AMOUNT,in_stack_00000010);
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,MAGICFIELD);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,RESPONSIBLE,in_stack_00000010);
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,LIQUIDPOOL);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,POOLLIQUIDTYPE,in_stack_00000010);
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,LIQUIDCONTAINER);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,CONTAINERLIQUIDTYPE,in_stack_00000010);
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,KEY);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,KEYNUMBER,in_stack_00000010);
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,RUNE);
- if (bVar1) {
- local_5c[0].ObjectID = z;
- ChangeObject(local_5c,CHARGES,in_stack_00000010);
- }
- if (*(int *)Value != 99) {
-LAB_08091e32:
- local_5c[0].ObjectID = z;
- AnnounceChangedObject(local_5c,1);
- local_5c[0].ObjectID = z;
- NotifyTrades(local_5c);
- Object::getContainer(local_5c);
- Object::getObjectType(&local_4c);
- local_4c.ObjectID = z;
- local_3c[0].ObjectID = z;
- uVar2 = GetObjectCreatureID(local_3c);
- NotifyCreature(uVar2,(Object *)uVar2,SUB41(&local_4c,0));
- Object::getContainer(local_5c);
- Object::getContainer(&local_4c);
- local_3c[0].ObjectID = z;
- MovementEvent(local_3c,&local_4c,local_5c);
- Object::getContainer(local_5c);
- local_4c.ObjectID = z;
- CollisionEvent(&local_4c,local_5c);
- local_5c[0].ObjectID = NONE.ObjectID;
- local_4c.ObjectID = z;
- NotifyAllCreatures(&local_4c,1,local_5c);
- Con->ObjectID = z;
- return (Object)(ulong)Con;
- }
- this = GetCreature(in_stack_00000010);
- if (this != (TCreature *)0x0) {
- _TypeID = 10;
- do {
- ObjectType::setTypeID((ObjectType *)&local_4c,_TypeID);
- local_3c[0].ObjectID = z;
- SetObject(local_5c,(ObjectType *)local_3c,(ulong)&local_4c);
- _TypeID = _TypeID + -1;
- } while (0 < _TypeID);
- local_5c[0].ObjectID = z;
- local_3c[0].ObjectID = z;
- (this->CrObject).ObjectID = z;
- local_4c.ObjectID = z;
- TCreature::NotifyCreate(this);
- goto LAB_08091e32;
- }
- error(&DAT_080ff520,in_stack_00000010);
- local_5c[0].ObjectID = z;
- Delete(local_5c,-1);
- goto LAB_08091ff4;
- }
- Text = "Create: Objekttyp existiert nicht.\n";
- }
- else {
- Text = "Create: Zielobjekt existiert nicht.\n";
- }
-LAB_080922e0:
- error(Text);
-LAB_08091ff4:
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
-}
-
-
-
-Object Copy(Object *Con,Object *Source)
-
-{
- bool bVar1;
- ulong uVar2;
- undefined4 *puVar3;
- ulong newCreature;
- Object *Obj;
- Object *in_stack_0000000c;
- char *Text;
- Object local_5c [4];
- Object local_4c [4];
- Object local_3c;
- Object Help;
- Object local_2c [7];
-
- // try { // try from 08092368 to 08092715 has its CatchHandler @ 08092730
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER);
- if (!bVar1) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST);
- if (!bVar1) {
- Text = "Copy: Ziel ist kein Container.\n";
- goto LAB_080926bf;
- }
- }
- bVar1 = Object::exists(in_stack_0000000c);
- if (bVar1) {
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID != 99) {
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID == 0) {
- local_2c[0] = (Object)Obj->ObjectID;
- local_3c.ObjectID = in_stack_0000000c->ObjectID;
- CheckMapDestination(0,&local_3c,local_2c);
- }
- else {
- local_3c = (Object)Obj->ObjectID;
- uVar2 = GetObjectCreatureID(&local_3c);
- if (uVar2 != 0) {
- local_3c.ObjectID = in_stack_0000000c->ObjectID;
- CheckWeight(uVar2,&local_3c,-1);
- }
- Object::getObjectType(&local_3c);
- bVar1 = false;
- if ((0 < (int)local_3c.ObjectID) && ((int)local_3c.ObjectID < 0xb)) {
- bVar1 = true;
- }
- if (bVar1) {
- local_3c = (Object)Obj->ObjectID;
- local_2c[0].ObjectID = in_stack_0000000c->ObjectID;
- CheckInventoryDestination(local_2c,&local_3c,true);
- }
- else {
- local_3c = (Object)Obj->ObjectID;
- local_2c[0].ObjectID = in_stack_0000000c->ObjectID;
- CheckContainerDestination(local_2c,&local_3c);
- }
- }
- local_3c.ObjectID = in_stack_0000000c->ObjectID;
- local_2c[0] = (Object)Obj->ObjectID;
- CopyObject(Con,local_2c);
- Object::getObjectType(&local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER);
- if (bVar1) {
- local_2c[0].ObjectID = in_stack_0000000c->ObjectID;
- GetFirstContainerObject(&local_3c);
- local_4c[0] = (Object)NONE.ObjectID;
- local_2c[0].ObjectID = local_4c[0].ObjectID;
- if (local_3c.ObjectID != NONE.ObjectID) {
- do {
- local_5c[0] = (Object)Con->ObjectID;
- local_4c[0].ObjectID = NONE.ObjectID;
- local_2c[0].ObjectID = local_3c.ObjectID;
- Copy(local_4c,local_5c);
- Object::getNextObject(local_4c);
- local_3c.ObjectID = local_4c[0].ObjectID;
- bVar1 = local_4c[0].ObjectID != NONE.ObjectID;
- local_2c[0].ObjectID = NONE.ObjectID;
- local_4c[0].ObjectID = NONE.ObjectID;
- } while (bVar1);
- }
- }
- local_5c[0] = (Object)Con->ObjectID;
- AnnounceChangedObject(local_5c,1);
- local_5c[0] = (Object)Con->ObjectID;
- NotifyTrades(local_5c);
- Object::getContainer(local_5c);
- Object::getObjectType(local_4c);
- local_4c[0] = (Object)Con->ObjectID;
- local_3c.ObjectID = local_4c[0].ObjectID;
- uVar2 = GetObjectCreatureID(&local_3c);
- NotifyCreature(uVar2,(Object *)uVar2,SUB41(local_4c,0));
- Object::getContainer(local_5c);
- Object::getContainer(local_4c);
- local_3c = (Object)Con->ObjectID;
- MovementEvent(&local_3c,local_4c,local_5c);
- Object::getContainer(local_5c);
- local_4c[0] = (Object)Con->ObjectID;
- CollisionEvent(local_4c,local_5c);
- local_5c[0].ObjectID = NONE.ObjectID;
- local_4c[0] = (Object)Con->ObjectID;
- NotifyAllCreatures(local_4c,1,local_5c);
- return (Object)(ulong)Con;
- }
- Text = "Copy: Quelle ist eine Kreatur.\n";
- }
- else {
- Text = "Copy: Quelle existiert nicht.\n";
- }
- }
- else {
- Text = "Copy: Ziel existiert nicht.\n";
- }
-LAB_080926bf:
- error(Text);
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
-}
-
-void Change(Object *Obj,ObjectType *NewType,ulong Value)
-
-{
- bool bVar1;
- bool bVar2;
- ulong uVar3;
- int iVar4;
- undefined4 *puVar5;
- ulong Data;
- char *pcVar6;
- Object OVar7;
- ulong Creature;
- Object local_7c;
- ObjectType OldType;
- Object local_6c [4];
- Object local_5c [4];
- Object local_4c [4];
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 0809370b to 08093ef9 has its CatchHandler @ 08093f30
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- Object::getObjectType(local_2c);
- if ((local_2c[0].ObjectID == 99) || (NewType->TypeID == 99)) {
- pcVar6 = &DAT_080ffa00;
- }
- else {
- ObjectType::setTypeID((ObjectType *)local_2c,0);
- if (NewType->TypeID == local_2c[0].ObjectID) {
- local_3c[0] = (Object)Obj->ObjectID;
- Delete(local_3c,-1);
- return;
- }
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER);
- if (bVar1) {
- bVar1 = ObjectType::getFlag(NewType,CONTAINER);
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- GetFirstContainerObject(local_3c);
- local_5c[0] = (Object)NONE.ObjectID;
- local_4c[0].ObjectID = NONE.ObjectID;
- if (local_3c[0].ObjectID == NONE.ObjectID) goto LAB_08093e33;
- Object::getObjectType(local_5c);
- iVar4 = NewType->TypeID;
- pcVar6 = &DAT_080ff9c0;
- OVar7.ObjectID = local_5c[0].ObjectID;
-LAB_08093e9d:
- error(pcVar6,iVar4,OVar7.ObjectID);
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0x14;
- goto LAB_08093d62;
- }
-LAB_08093e33:
- bVar1 = ObjectType::getFlag(NewType,CONTAINER);
- if (bVar1) {
- uVar3 = ObjectType::getAttribute(NewType,CAPACITY);
- local_5c[0] = (Object)Obj->ObjectID;
- iVar4 = CountObjectsInContainer(local_5c);
- if ((int)uVar3 < iVar4) {
- Object::getObjectType(local_4c);
- iVar4 = NewType->TypeID;
- pcVar6 = &DAT_080ff980;
- OVar7.ObjectID = local_4c[0].ObjectID;
- goto LAB_08093e9d;
- }
- }
- }
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,CHEST);
- if ((!bVar1) || (bVar1 = ObjectType::getFlag(NewType,CHEST), bVar1)) {
- bVar1 = false;
- Object::getObjectType(local_5c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_5c,CUMULATIVE);
- if (bVar2) {
- Object::getObjectType(local_5c);
- ObjectType::setTypeID((ObjectType *)local_4c,NewType->TypeID);
- ObjectType::setTypeID((ObjectType *)local_3c,local_4c[0].ObjectID);
- if ((local_5c[0].ObjectID != local_3c[0].ObjectID) &&
- (uVar3 = Object::getAttribute(Obj,AMOUNT), 1 < uVar3)) {
- bVar1 = true;
- }
- }
- if (!bVar1) {
- local_5c[0] = (Object)Obj->ObjectID;
- uVar3 = GetObjectCreatureID(local_5c);
- if (uVar3 != 0) {
- Object::getObjectType(local_5c);
- ObjectType::setTypeID((ObjectType *)local_4c,NewType->TypeID);
- ObjectType::setTypeID((ObjectType *)local_3c,local_4c[0].ObjectID);
- if (local_5c[0].ObjectID != local_3c[0].ObjectID) {
- Object::getContainer(local_3c);
- Object::getObjectType(local_2c);
- bVar1 = false;
- if ((0 < (int)local_2c[0].ObjectID) && ((int)local_2c[0].ObjectID < 0xb)
- ) {
- bVar1 = true;
- }
- if (bVar1) {
- local_7c = (Object)Obj->ObjectID;
- ObjectType::setTypeID((ObjectType *)local_6c,NewType->TypeID);
- Object::getContainer(local_2c);
- CheckInventoryPlace((ObjectType *)local_6c,local_2c,&local_7c);
- }
- else {
- local_2c[0] = (Object)Obj->ObjectID;
- ObjectType::setTypeID((ObjectType *)local_6c,NewType->TypeID);
- Object::getContainer(&local_7c);
- CheckContainerPlace((ObjectType *)local_6c,&local_7c,local_2c);
- }
- local_7c = (Object)Obj->ObjectID;
- iVar4 = GetWeight(&local_7c,-1);
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,CUMULATIVE);
- if (bVar1) {
- Data = Object::getAttribute(Obj,AMOUNT);
- }
- else {
- Data = 1;
- }
- ObjectType::setTypeID((ObjectType *)local_6c,NewType->TypeID);
- CheckWeight(uVar3,(ObjectType *)local_6c,Data,iVar4);
- }
- }
- Object::getObjectType(&local_7c);
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,CONTAINER);
- if ((bVar1) && (bVar1 = ObjectType::getFlag(NewType,CONTAINER), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- CloseContainer(local_6c,true);
- }
- ObjectType::setTypeID((ObjectType *)local_6c,NewType->TypeID);
- local_5c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_5c,(ObjectType *)local_6c);
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,CUMULATIVE);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,CUMULATIVE), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,AMOUNT,Value);
- }
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,MAGICFIELD);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,MAGICFIELD), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,RESPONSIBLE,Value);
- }
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,LIQUIDPOOL);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,LIQUIDPOOL), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,POOLLIQUIDTYPE,Value);
- }
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,LIQUIDCONTAINER);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,LIQUIDCONTAINER), !bVar1
- )) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,CONTAINERLIQUIDTYPE,Value);
- }
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,KEY);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,KEY), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,KEYNUMBER,Value);
- }
- Object::getObjectType(local_6c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_6c,RUNE);
- if ((bVar1) &&
- (bVar1 = ObjectType::getFlag((ObjectType *)&local_7c,RUNE), !bVar1)) {
- local_6c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_6c,CHARGES,Value);
- }
- local_6c[0] = (Object)Obj->ObjectID;
- AnnounceChangedObject(local_6c,2);
- local_6c[0] = (Object)Obj->ObjectID;
- NotifyTrades(local_6c);
- Object::getContainer(local_6c);
- Object::getObjectType(local_5c);
- local_5c[0] = (Object)Obj->ObjectID;
- local_4c[0].ObjectID = local_5c[0].ObjectID;
- uVar3 = GetObjectCreatureID(local_4c);
- NotifyCreature(uVar3,(Object *)uVar3,SUB41(local_5c,0));
- local_6c[0].ObjectID = NONE.ObjectID;
- local_5c[0] = (Object)Obj->ObjectID;
- NotifyAllCreatures(local_5c,2,local_6c);
- return;
- }
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0x15;
- goto LAB_08093d62;
- }
- pcVar6 = &DAT_080ff940;
- }
- }
- else {
- pcVar6 = &DAT_080ffa40;
- }
- error(pcVar6);
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0xffffffff;
-LAB_08093d62:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar5,&RESULT::typeinfo,0);
-}
-
-
-
-void Change(Object *Obj,INSTANCEATTRIBUTE Attribute,ulong Value)
-
-{
- bool bVar1;
- ulong uVar2;
- ulong uVar3;
- int oldWeight;
- undefined4 *puVar4;
- ulong Creature;
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 08093f6b to 0809414b has its CatchHandler @ 08094150
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- if ((((CHESTQUESTNUMBER < Attribute) && (Attribute != DOORLEVEL)) &&
- (Attribute != DOORQUESTNUMBER)) &&
- (((Attribute != DOORQUESTVALUE && (Attribute != ABSTELEPORTDESTINATION)) &&
- (Attribute != REMAININGEXPIRETIME)))) {
- local_2c[0] = (Object)Obj->ObjectID;
- uVar2 = GetObjectCreatureID(local_2c);
- if (((uVar2 != 0) && (Attribute == AMOUNT)) &&
- (uVar3 = Object::getAttribute(Obj,AMOUNT), uVar3 < Value)) {
- local_2c[0] = (Object)Obj->ObjectID;
- oldWeight = GetWeight(local_2c,-1);
- Object::getObjectType(local_3c);
- CheckWeight(uVar2,(ObjectType *)local_3c,Value,oldWeight);
- }
- local_3c[0] = (Object)Obj->ObjectID;
- ChangeObject(local_3c,Attribute,Value);
- if (((Attribute == AMOUNT) || (Attribute == CONTAINERLIQUIDTYPE)) ||
- (Attribute == POOLLIQUIDTYPE)) {
- local_3c[0] = (Object)Obj->ObjectID;
- AnnounceChangedObject(local_3c,2);
- }
- local_3c[0] = (Object)Obj->ObjectID;
- NotifyTrades(local_3c);
- Object::getContainer(local_3c);
- Object::getObjectType(local_2c);
- Creature = Obj->ObjectID;
- local_2c[0].ObjectID = Creature;
- uVar2 = GetObjectCreatureID((Object *)&Creature);
- NotifyCreature(uVar2,(Object *)uVar2,SUB41(local_2c,0));
- return;
- }
- error(&DAT_080ffa80,Attribute);
- }
- else {
- error(&DAT_080ffa40);
- }
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar4,&RESULT::typeinfo,0);
-}
-
-
-
-void Delete(Object *Obj,int Count)
-
-{
- bool bVar1;
- TCreature *cr;
- ulong uVar2;
- TCreature *this;
- undefined4 *puVar3;
- bool Inventory;
- ObjectType *Type;
- ulong oldCreature;
- Object local_5c;
- Object oldCon;
- Object local_4c;
- ObjectType oldType;
- Object local_3c [4];
- Object local_2c;
- Object Rest;
-
- // try { // try from 0809418b to 08094506 has its CatchHandler @ 08094510
- bVar1 = Object::exists(Obj);
- if (!bVar1) {
- error(&DAT_080ffb60);
-LAB_080944d1:
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
- }
- Object::getObjectType(&local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,CUMULATIVE);
- if ((bVar1) && ((Count == 0 || (uVar2 = Object::getAttribute(Obj,AMOUNT), (int)uVar2 < Count))))
- {
- error(&DAT_080ffb00,Count);
- goto LAB_080944d1;
- }
- local_2c.ObjectID = NONE.ObjectID;
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE);
- if (((bVar1) && (Count != -1)) && (uVar2 = Object::getAttribute(Obj,AMOUNT), Count < (int)uVar2)
- ) {
- local_5c = (Object)Obj->ObjectID;
- local_4c.ObjectID = local_5c.ObjectID;
- local_3c[0].ObjectID = local_5c.ObjectID;
- local_2c.ObjectID = local_5c.ObjectID;
- SplitObject(local_3c,(int)&local_5c);
- local_4c.ObjectID = local_3c[0].ObjectID;
- Obj->ObjectID = (ulong)local_3c[0];
- }
- else {
- local_5c = (Object)Obj->ObjectID;
- NotifyTrades(&local_5c);
- }
- 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) goto LAB_080942ee;
- }
- Object::getObjectType(&local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_5c,CONTAINER);
- if (bVar1) {
- local_5c = (Object)Obj->ObjectID;
- CloseContainer(&local_5c,true);
- }
- while( true ) {
- local_4c = (Object)Obj->ObjectID;
- GetFirstContainerObject(&local_5c);
- local_4c.ObjectID = NONE.ObjectID;
- if (local_5c.ObjectID == NONE.ObjectID) break;
- local_4c.ObjectID = local_5c.ObjectID;
- DeleteObject(&local_4c);
- }
-LAB_080942ee:
- Object::getContainer(&local_5c);
- local_4c = (Object)Obj->ObjectID;
- uVar2 = GetObjectCreatureID(&local_4c);
- Object::getObjectType(&local_4c);
- local_3c[0].ObjectID = local_5c.ObjectID;
- oldCreature = Obj->ObjectID;
- SeparationEvent((Object *)&oldCreature,local_3c);
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- oldCreature = NONE.ObjectID;
- if (local_2c.ObjectID == NONE.ObjectID) {
- local_3c[0] = (Object)Obj->ObjectID;
- AnnounceChangedObject(local_3c,0);
- }
- oldCreature = NONE.ObjectID;
- local_3c[0] = (Object)Obj->ObjectID;
- NotifyAllCreatures(local_3c,0,(Object *)&oldCreature);
- if (local_4c.ObjectID == 99) {
- this = GetCreature(uVar2);
- if (this == (TCreature *)0x0) {
- error(&DAT_080ffac0,uVar2);
- }
- else {
- TCreature::NotifyDelete(this);
- }
- }
- oldCreature = Obj->ObjectID;
- DeleteObject((Object *)&oldCreature);
- oldCreature = NONE.ObjectID;
- local_3c[0].ObjectID = NONE.ObjectID;
- if (local_2c.ObjectID != NONE.ObjectID) {
- local_3c[0].ObjectID = local_2c.ObjectID;
- AnnounceChangedObject(local_3c,2);
- local_3c[0].ObjectID = local_2c.ObjectID;
- NotifyTrades(local_3c);
- }
- Object::getObjectType((Object *)&oldCreature);
- ObjectType::setTypeID((ObjectType *)&oldCreature,local_4c.ObjectID);
- NotifyCreature(uVar2,Type,Inventory);
- }
- return;
-}
-
-
-
-void Empty(Object *Con,int Rest)
-
-{
- bool bVar1;
- int iVar2;
- undefined4 *puVar3;
- char *Text;
- bool IsCorpse;
- int Count;
- Object local_4c [4];
- Object local_3c [4];
- Object local_2c;
- Object Obj;
-
- // try { // try from 0809454b to 080946b9 has its CatchHandler @ 080946c5
- bVar1 = Object::exists(Con);
- if (bVar1) {
- if (Rest < 0) {
- error(&DAT_081013ed,Rest);
- goto LAB_08094680;
- }
- Object::getObjectType(&local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,CONTAINER);
- if (bVar1) {
- local_2c = (Object)Con->ObjectID;
- iVar2 = CountObjectsInContainer(&local_2c);
- local_2c = (Object)Con->ObjectID;
- CloseContainer(&local_2c,true);
- Object::getObjectType(&local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,CORPSE);
- for (; Rest < iVar2; iVar2 = iVar2 + -1) {
- local_3c[0] = (Object)Con->ObjectID;
- GetFirstContainerObject(&local_2c);
- if (bVar1) {
- local_3c[0].ObjectID = local_2c.ObjectID;
- Delete(local_3c,-1);
- }
- else {
- local_3c[0].ObjectID = NONE.ObjectID;
- Object::getContainer(local_4c);
- Count = local_2c.ObjectID;
- Move(0,(Object *)&Count,local_4c,-1,false,local_3c);
- }
- }
- return;
- }
- Text = &DAT_080ffba0;
- }
- else {
- Text = &DAT_080ffbe0;
- }
- error(Text);
-LAB_08094680:
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void GraphicalEffect(void)
-
-{
- int in_stack_00000004;
- int in_stack_00000008;
- int in_stack_0000000c;
- int in_stack_00000010;
-
- AnnounceGraphicalEffect(in_stack_00000004,in_stack_00000008,in_stack_0000000c,in_stack_00000010)
- ;
- return;
-}
-
-
-
-void GraphicalEffect(Object *Obj,int Type)
-
-{
- bool bVar1;
- int local_28;
- int x;
- int y;
- int z;
-
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- z = Obj->ObjectID;
- GetObjectCoordinates((Object *)&z,&local_28,&x,&y);
- AnnounceGraphicalEffect(local_28,x,y,Type);
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void TextualEffect(void)
-
-{
- bool bVar1;
- Object *in_stack_00000004;
- int in_stack_00000008;
- char *in_stack_0000000c;
- int local_58;
- int x;
- int y;
- int z;
- char Buffer [10];
- Object local_3c [4];
- Object local_2c [7];
-
- bVar1 = Object::exists(in_stack_00000004);
- if (bVar1) {
- Object::getObjectType(local_2c);
- if (local_2c[0].ObjectID != 0) {
- z = in_stack_00000004->ObjectID;
- GetMapContainer(local_3c);
- in_stack_00000004->ObjectID = local_3c[0].ObjectID;
- }
- vsnprintf((char *)&z,10,in_stack_0000000c,&stack0x00000010);
- local_3c[0].ObjectID = in_stack_00000004->ObjectID;
- GetObjectCoordinates(local_3c,&local_58,&x,&y);
- AnnounceTextualEffect(local_58,x,y,in_stack_00000008,(char *)&z);
- }
- else {
- error(&DAT_080ffc20);
- }
- return;
-}
-
-
-
-void Missile(Object *Start,Object *Dest,int Type)
-
-{
- bool bVar1;
- char *Text;
- int local_44;
- int zx;
- int zy;
- int zz;
- int sx;
- int sy;
- int sz;
-
- bVar1 = Object::exists(Start);
- if (bVar1) {
- bVar1 = Object::exists(Dest);
- if (bVar1) {
- sz = Start->ObjectID;
- GetObjectCoordinates((Object *)&sz,&zz,&sx,&sy);
- sz = Dest->ObjectID;
- GetObjectCoordinates((Object *)&sz,&local_44,&zx,&zy);
- AnnounceMissile(zz,sx,sy,local_44,zx,zy,Type);
- return;
- }
- Text = &DAT_080ffca0;
- }
- else {
- Text = &DAT_080ffc60;
- }
- error(Text);
- return;
-}
-
-
-
void Look(ulong CreatureID,Object *Obj)
{
diff --git a/src/cr.hh b/src/cr.hh
index 162cb68..a2206f4 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -717,6 +717,7 @@ struct TPlayer: TCreature {
Object GetOpenContainer(int ContainerNr);
void SetOpenContainer(int ContainerNr, Object Con);
void RejectTrade(void);
+ Object InspectTrade(bool OwnOffer, int Position);
// VIRTUAL FUNCTIONS
// =================
diff --git a/src/crcombat.cc b/src/crcombat.cc
index c1f27a4..0b45ea4 100644
--- a/src/crcombat.cc
+++ b/src/crcombat.cc
@@ -2,6 +2,7 @@
#include "config.hh"
#include "info.hh"
#include "magic.hh"
+#include "operate.hh"
#include "stubs.hh"
diff --git a/src/crmain.cc b/src/crmain.cc
index 52a7c13..7e0ab42 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -592,7 +592,7 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){
this->SetTimer(SKILL_ILLUSION, 0, 0, 0, -1);
this->Outfit = this->OrgOutfit;
AnnounceChangedCreature(this->ID, CREATURE_OUTFIT_CHANGED);
- NotifyAllCreatures(this->CrObject, 2, NONE); // CREATURE_APPEAR ?
+ NotifyAllCreatures(this->CrObject, OBJECT_CHANGED, NONE);
}
if(DamageType == DAMAGE_MANADRAIN){
@@ -890,8 +890,7 @@ void TCreature::CreatureMoveStimulus(uint32 CreatureID, int Type){
return;
}
- // TODO(fusion): Find out what `Type` is here.
- if(Type != 2 // STIMULUS_TYPE_??
+ if(Type != OBJECT_CHANGED
|| !this->LockToDo
|| this->ActToDo >= this->NrToDo
|| this->ToDoList.at(this->ActToDo)->Code != TDAttack){
diff --git a/src/crskill.cc b/src/crskill.cc
index f400dc9..235f277 100644
--- a/src/crskill.cc
+++ b/src/crskill.cc
@@ -956,7 +956,7 @@ void TSkillIllusion::Event(int Range){
if(this->Get() <= 0){
Master->Outfit = Master->OrgOutfit;
AnnounceChangedCreature(Master->ID, CREATURE_OUTFIT_CHANGED);
- NotifyAllCreatures(Master->CrObject, 2, NONE);
+ NotifyAllCreatures(Master->CrObject, OBJECT_CHANGED, NONE);
}
}
}
diff --git a/src/info.cc b/src/info.cc
index 3cdfe02..0461356 100644
--- a/src/info.cc
+++ b/src/info.cc
@@ -486,6 +486,17 @@ Object GetInventoryObject(uint32 CreatureID, ObjectType Type, uint32 Value){
return Result;
}
+bool IsHeldByContainer(Object Obj, Object Con){
+ // TODO(fusion): Why do we check for map container in some loops?
+ while(Obj != NONE && !Obj.getObjectType().isMapContainer()){
+ if(Obj == Con){
+ return true;
+ }
+ Obj = Obj.getContainer();
+ }
+ return false;
+}
+
int CountObjectsInContainer(Object Con){
if(!Con.exists()){
error("CountObjectsInContainer: Container existiert nicht.\n");
diff --git a/src/info.hh b/src/info.hh
index adf3ce4..0a7f919 100644
--- a/src/info.hh
+++ b/src/info.hh
@@ -31,6 +31,7 @@ Object GetContainer(uint32 CreatureID, int x, int y, int z);
Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type);
Object GetRowObject(Object Obj, ObjectType Type, uint32 Value, bool Recurse);
Object GetInventoryObject(uint32 CreatureID, ObjectType Type, uint32 Value);
+bool IsHeldByContainer(Object Obj, Object Con);
int CountObjectsInContainer(Object Con);
int CountObjects(Object Obj);
int CountObjects(Object Obj, ObjectType Type, uint32 Value);
diff --git a/src/magic.cc b/src/magic.cc
index 6cff8bc..0b161ec 100644
--- a/src/magic.cc
+++ b/src/magic.cc
@@ -2401,7 +2401,7 @@ void CancelInvisibility(TCreature *Actor, Object Target, int ManaPoints, int Sou
if(Victim->Skills[SKILL_ILLUSION]->Get() == 0){
Victim->Outfit = Victim->OrgOutfit;
AnnounceChangedCreature(Victim->ID, CREATURE_OUTFIT_CHANGED);
- NotifyAllCreatures(Victim->CrObject, 2, NONE); // CREATURE_APPEAR ?
+ NotifyAllCreatures(Victim->CrObject, OBJECT_CHANGED, NONE);
}else{
Effect = EFFECT_BLOCK_HIT;
diff --git a/src/map.cc b/src/map.cc
index b9085c9..0329e20 100644
--- a/src/map.cc
+++ b/src/map.cc
@@ -1971,33 +1971,6 @@ void ChangeObject(Object Obj, INSTANCEATTRIBUTE Attribute, uint32 Value){
Obj.setAttribute(Attribute, Value);
}
-// TODO(fusion): This probably belongs to `operate.cc`.
-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");
diff --git a/src/map.hh b/src/map.hh
index 8989f05..81edef0 100644
--- a/src/map.hh
+++ b/src/map.hh
@@ -145,7 +145,6 @@ Object CreateObject(void);
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);
diff --git a/src/moveuse.cc b/src/moveuse.cc
new file mode 100644
index 0000000..f11fffa
--- /dev/null
+++ b/src/moveuse.cc
@@ -0,0 +1,56 @@
+#include "operate.hh"
+
+// NOTE(fusion): Oh no.
+void ChangeObject(Object Obj, ObjectType NewType, uint32 Value){
+ if(!Obj.exists()){
+ error("ChangeObject: Übergebenes Objekt existiert nicht (1, NewType=%d).\n", NewType.TypeID);
+ return;
+ }
+
+ Object Con = Obj.getContainer();
+ while(true){
+ if(!Obj.exists()){
+ error("ChangeObject: Übergebenes Objekt existiert nicht (2, NewType=%d).\n", NewType.TypeID);
+ return;
+ }
+
+ try{
+ // NOTE(fusion): `Change` requires CUMULATIVE objects to have AMOUNT
+ // equal to one or it fails with `SPLITOBJECT`.
+ 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);
+ return;
+ }catch(RESULT r){
+ if(!Obj.exists()){
+ error("ChangeObject: Übergebenes Objekt existiert nicht (3, NewType=%d).\n", NewType.TypeID);
+ return;
+ }
+
+ if(r == CONTAINERFULL){
+ Con = GetMapContainer(Obj);
+ }else if(r == TOOHEAVY){
+ Object MapCon = GetMapContainer(Obj);
+ Move(0, Obj, MapCon, -1, true, NONE);
+ }else if(r == NOROOM){
+ if(!Obj.getObjectType().getFlag(CUMULATIVE)
+ || Obj.getAttribute(AMOUNT) <= 1){
+ throw;
+ }
+
+ // TODO(fusion): Why do we use `Con` with `GetMapContainer` here?
+ uint32 Amount = Obj.getAttribute(AMOUNT);
+ Object MapCon = GetMapContainer(Con);
+ Move(0, Obj, MapCon, Amount - 1, true, NONE);
+ }else{
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/moveuse.hh b/src/moveuse.hh
new file mode 100644
index 0000000..1036142
--- /dev/null
+++ b/src/moveuse.hh
@@ -0,0 +1,9 @@
+#ifndef TIBIA_MOVEUSE_HH_
+#define TIBIA_MOVEUSE_HH_ 1
+
+#include "common.hh"
+#include "map.hh"
+
+void ChangeObject(Object Obj, ObjectType NewType, uint32 Value);
+
+#endif //TIBIA_MOVEUSE_HH_
diff --git a/src/operate.cc b/src/operate.cc
index 34df0a7..5f7d4d3 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -4,29 +4,6 @@
#include "stubs.hh"
-// operate.cc
-void CheckMoveObject(uint32 CreatureID, Object Obj, bool Take);
-void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon);
-void CheckDepotSpace(uint32 CreatureID, Object Source, Object Destination, int Count);
-void CheckWeight(uint32 CreatureID, Object Obj, int Count);
-void NotifyCreature(uint32 CreatureID, Object Obj, bool Inventory);
-void NotifyCreature(uint32 CreatureID, ObjectType Type, bool Inventory);
-//void NotifyAllCreatures(Object Obj, int Type, Object OldCon);
-void NotifyTrades(Object Obj);
-void NotifyDepot(uint32 CreatureID, Object Obj, int Count);
-void CloseContainer(Object Con, bool Force);
-
-// moveuse.cc
-void MovementEvent(Object Obj, Object Start, Object Dest);
-void CollisionEvent(Object Obj, Object Dest);
-void SeparationEvent(Object Obj, Object Start);
-
-
-//==================================================================================================
-//==================================================================================================
-//==================================================================================================
-//==================================================================================================
-
// TODO(fusion): The radii parameters for `TFindCreatures` are commonly around
// 16 and 14 for x and y respectively so there is probably some constant involved.
// Also, since we're talking about radii, these values are quite large when you
@@ -449,9 +426,9 @@ void CheckMoveObject(uint32 CreatureID, Object Obj, bool Take){
}
}
-// NOTE(fusion): This is a helper function for `CheckMapDestination` and improves
-// the readability of an otherwise convoluted function.
-static bool IsMapDestinationBlocked(int DestX, int DestY, int DestZ, ObjectType Type){
+// NOTE(fusion): This is a helper function for `CheckMapDestination` and `CheckMapPlace`
+// and improves the readability of otherwise two convoluted functions.
+static bool IsMapBlocked(int DestX, int DestY, int DestZ, ObjectType Type){
if(Type.isCreatureContainer()){
return false;
}
@@ -466,9 +443,11 @@ static bool IsMapDestinationBlocked(int DestX, int DestY, int DestZ, ObjectType
return false;
}
- if(CoordinateFlag(DestX, DestY, DestZ, HOOKSOUTH) || CoordinateFlag(DestX, DestY, DestZ, HOOKEAST)){
- if(Type.getFlag(HANG) && !CoordinateFlag(DestX, DestY, DestZ, HANG)){
- return true;
+ if(Type.getFlag(HANG)){
+ bool HasHook = CoordinateFlag(DestX, DestY, DestZ, HOOKSOUTH)
+ || CoordinateFlag(DestX, DestY, DestZ, HOOKEAST);
+ if(HasHook && !CoordinateFlag(DestX, DestY, DestZ, HANG)){
+ return false;
}
}
}
@@ -484,7 +463,7 @@ void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon){
int DestX, DestY, DestZ;
ObjectType ObjType = Obj.getObjectType();
GetObjectCoordinates(MapCon, &DestX, &DestY, &DestZ);
- if(IsMapDestinationBlocked(DestX, DestY, DestZ, ObjType)){
+ if(IsMapBlocked(DestX, DestY, DestZ, ObjType)){
throw NOROOM;
}
@@ -507,8 +486,12 @@ void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon){
}
}
- // TODO(fusion): Should probably check if moving creature is NULL?
TCreature *MovingCreature = GetCreature(Obj);
+ if(MovingCreature == NULL){
+ error("CheckMapDestination: Moving creature is NULL.");
+ throw ERROR;
+ }
+
if(OrigZ == DestZ || MovingCreature->Type != MONSTER){
if(!MovingCreature->MovePossible(DestX, DestY, DestZ, true, OrigZ != DestZ)){
if(CreatureID == MovingCreature->ID){
@@ -579,14 +562,34 @@ void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon){
}
}
-// TODO(fusion): This could have been a simple return value.
-void CheckContainerDestination(Object Obj, Object Con){
- Object Help = Con;
- while(Help != NONE && !Help.getObjectType().isMapContainer()){
- if(Help == Obj){
- throw CROSSREFERENCE;
+void CheckMapPlace(uint32 CreatureID, ObjectType Type, Object MapCon){
+ int DestX, DestY, DestZ;
+ GetObjectCoordinates(MapCon, &DestX, &DestY, &DestZ);
+
+ if(!Type.getFlag(UNMOVE) && !CoordinateFlag(DestX, DestY, DestZ, BANK)){
+ if(!Type.getFlag(HANG)){
+ throw NOROOM;
+ }
+
+ if(!CoordinateFlag(DestX, DestY, DestZ, HOOKSOUTH)
+ && !CoordinateFlag(DestX, DestY, DestZ, HOOKEAST)){
+ throw NOROOM;
}
- Help = Help.getContainer();
+ }
+
+ // TODO(fusion): The original function used a slightly modified version of
+ // `IsMapBlocked` which wouldn't check if there was already a HANG item at
+ // the destination but since this function seems to only be called from
+ // `Create` which sets `CreatureID` to zero, I assume this was probably an
+ // oversight?
+ if(CreatureID != 0 && IsMapBlocked(DestX, DestY, DestZ, Type)){
+ throw NOROOM;
+ }
+}
+
+void CheckContainerDestination(Object Obj, Object Con){
+ if(IsHeldByContainer(Con, Obj)){
+ throw CROSSREFERENCE;
}
ObjectType ConType = Con.getObjectType();
@@ -599,6 +602,60 @@ void CheckContainerDestination(Object Obj, Object Con){
}
}
+void CheckContainerPlace(ObjectType Type, Object Con, Object OldObj){
+ if(Type == GetSpecialObject(DEPOT_CHEST)){
+ return;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.getFlag(CHEST)){
+ if(Type.getFlag(UNMOVE)){
+ throw NOTMOVABLE;
+ }
+
+ if(!Type.getFlag(TAKE)){
+ throw NOTTAKABLE;
+ }
+
+ if(OldObj == NONE){
+ int ConObjects = CountObjectsInContainer(Con);
+ int ConCapacity = (int)ConType.getAttribute(CAPACITY);
+ if(ConObjects >= ConCapacity){
+ throw CONTAINERFULL;
+ }
+ }
+ }
+}
+
+void CheckDepotSpace(uint32 CreatureID, Object Source, Object Destination, int Count){
+ if(CreatureID == 0){
+ return;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("CheckDepotSpace: Kreatur %u existiert nicht.\n", CreatureID);
+ throw ERROR;
+ }
+
+ if(Destination == NONE){
+ error("CheckDepotSpace: Ziel existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(Creature->Type == PLAYER){
+ TPlayer *Player = (TPlayer*)Creature;
+ if(Player->Depot == NONE || Count <= Player->DepotSpace){
+ return;
+ }
+
+ if(!IsHeldByContainer(Source, Player->Depot)
+ && IsHeldByContainer(Destination, Player->Depot)){
+ throw CONTAINERFULL;
+ }
+ }
+}
+
void CheckInventoryDestination(Object Obj, Object Con, bool Split){
ObjectType ObjType = Obj.getObjectType();
int ConPosition = GetObjectBodyPosition(Con);
@@ -619,7 +676,7 @@ void CheckInventoryDestination(Object Obj, Object Con, bool Split){
}
uint32 CreatureID = GetObjectCreatureID(Con);
- if(ObjType.isTwoHanded() && HandContainer){
+ if(HandContainer && ObjType.isTwoHanded()){
Object RightHand = GetBodyObject(CreatureID, INVENTORY_RIGHTHAND);
if(RightHand != NONE && RightHand != Obj){
throw HANDSNOTFREE;
@@ -658,6 +715,546 @@ void CheckInventoryDestination(Object Obj, Object Con, bool Split){
}
}
+void CheckInventoryPlace(ObjectType Type, Object Con, Object OldObj){
+ // TODO(fusion): This is awfully similar to `CheckInventoryDestination` with
+ // a few subtle differences. Perhaps they use the same underlying function?
+
+ int ConPosition = GetObjectBodyPosition(Con);
+ bool HandContainer = ConPosition == INVENTORY_RIGHTHAND
+ || ConPosition == INVENTORY_LEFTHAND;
+
+ if(!HandContainer && ConPosition != INVENTORY_AMMO){
+ if(!Type.getFlag(CLOTHES)){
+ throw WRONGPOSITION;
+ }
+
+ int TypePosition = (int)Type.getAttribute(BODYPOSITION);
+ if(TypePosition == 0){
+ throw WRONGPOSITION2;
+ }else if(TypePosition != ConPosition){
+ throw WRONGCLOTHES;
+ }
+ }
+
+ uint32 CreatureID = GetObjectCreatureID(Con);
+ if(HandContainer && Type.isTwoHanded()){
+ Object RightHand = GetBodyObject(CreatureID, INVENTORY_RIGHTHAND);
+ if(RightHand != NONE && RightHand != OldObj){
+ throw HANDSNOTFREE;
+ }
+
+ Object LeftHand = GetBodyObject(CreatureID, INVENTORY_LEFTHAND);
+ if(LeftHand != NONE && LeftHand != OldObj){
+ throw HANDSNOTFREE;
+ }
+
+ return;
+ }
+
+ if(GetBodyObject(CreatureID, ConPosition) != NONE
+ && GetBodyObject(CreatureID, ConPosition) != OldObj){
+ throw NOROOM;
+ }
+
+ if(HandContainer){
+ for(int Position = INVENTORY_HAND_FIRST;
+ Position <= INVENTORY_HAND_LAST;
+ Position += 1){
+ Object Other = GetBodyObject(CreatureID, Position);
+ if(Other != NONE && Other != OldObj){
+ ObjectType OtherType = Other.getObjectType();
+ if(OtherType.isTwoHanded()){
+ throw HANDBLOCKED;
+ }
+
+ if(OtherType.isWeapon() && Type.isWeapon()){
+ throw ONEWEAPONONLY;
+ }
+ }
+ }
+ }
+}
+
+void CheckWeight(uint32 CreatureID, Object Obj, int Count){
+ if(GetObjectCreatureID(Obj) == CreatureID){
+ return;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("CheckWeight: Kreatur %d existiert nicht.\n", CreatureID);
+ throw ERROR;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.getFlag(TAKE)){
+ throw TOOHEAVY;
+ }
+
+ if(Creature->Type == PLAYER){
+ if(CheckRight(CreatureID, UNLIMITED_CAPACITY)){
+ return;
+ }
+
+ if(CheckRight(CreatureID, ZERO_CAPACITY)){
+ throw TOOHEAVY;
+ }
+ }
+
+ TSkill *CarryStrength = Creature->Skills[SKILL_CARRY_STRENGTH];
+ if(CarryStrength == NULL){
+ error("CheckWeight: Skill CARRYSTRENGTH existiert nicht.\n");
+ throw ERROR;
+ }
+
+ int ObjWeight;
+ if(ObjType.getFlag(CUMULATIVE)){
+ ObjWeight = GetWeight(Obj, Count);
+ }else{
+ ObjWeight = GetCompleteWeight(Obj);
+ }
+
+ int InventoryWeight = GetInventoryWeight(CreatureID);
+ int MaxWeight = CarryStrength->Get() * 100;
+ if((InventoryWeight + ObjWeight) > MaxWeight){
+ throw TOOHEAVY;
+ }
+}
+
+void CheckWeight(uint32 CreatureID, ObjectType Type, uint32 Value, int OldWeight){
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("CheckWeight: Kreatur %d existiert nicht.\n", CreatureID);
+ throw ERROR;
+ }
+
+ if(!Type.getFlag(TAKE)){
+ throw TOOHEAVY;
+ }
+
+ if(Creature->Type == PLAYER){
+ if(CheckRight(CreatureID, UNLIMITED_CAPACITY)){
+ return;
+ }
+
+ if(CheckRight(CreatureID, ZERO_CAPACITY)){
+ throw TOOHEAVY;
+ }
+ }
+
+ TSkill *CarryStrength = Creature->Skills[SKILL_CARRY_STRENGTH];
+ if(CarryStrength == NULL){
+ error("CheckWeight: Skill CARRYSTRENGTH existiert nicht.\n");
+ throw ERROR;
+ }
+
+ int TypeWeight = (int)Type.getAttribute(WEIGHT);
+ if(Type.getFlag(CUMULATIVE) && (int)Value > 1){
+ TypeWeight *= (int)Value;
+ }
+
+ if(TypeWeight > OldWeight){
+ int InventoryWeight = GetInventoryWeight(CreatureID);
+ int MaxWeight = CarryStrength->Get() * 100;
+ if((InventoryWeight + TypeWeight) > MaxWeight){
+ throw TOOHEAVY;
+ }
+ }
+}
+
+void NotifyCreature(uint32 CreatureID, Object Obj, bool Inventory){
+ if(CreatureID == 0){
+ return;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.isCreatureContainer()){
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("NotifyCreature: Kreatur existiert nicht.\n");
+ return;
+ }
+
+ if(Inventory && ObjType.getFlag(LIGHT)){
+ AnnounceChangedCreature(CreatureID, CREATURE_LIGHT_CHANGED);
+ }
+
+ Creature->NotifyChangeInventory();
+ }
+}
+
+void NotifyCreature(uint32 CreatureID, ObjectType Type, bool Inventory){
+ if(CreatureID == 0){
+ return;
+ }
+
+ // TODO(fusion): Shouldn't we check if `Type` is creature container too?
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("NotifyCreature: Kreatur existiert nicht.\n");
+ return;
+ }
+
+ if(Inventory && Type.getFlag(LIGHT)){
+ AnnounceChangedCreature(CreatureID, CREATURE_LIGHT_CHANGED);
+ }
+
+ Creature->NotifyChangeInventory();
+}
+
+void NotifyAllCreatures(Object Obj, int Type, Object OldCon){
+ if(!Obj.exists()){
+ error("NotifyAllCreatures: Übergebenes Objekt existiert nicht.\n");
+ return;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.isCreatureContainer()){
+ return;
+ }
+
+ int ObjX, ObjY, ObjZ;
+ uint32 CreatureID = Obj.getCreatureID();
+ GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ);
+
+ constexpr int StimulusRadius = 10;
+ int SearchRadiusX = StimulusRadius;
+ int SearchRadiusY = StimulusRadius;
+ int SearchCenterX = ObjX;
+ int SearchCenterY = ObjY;
+ if(Type == OBJECT_MOVED){
+ if(!OldCon.exists()){
+ error("NotifyAllCreatures: Übergebener alter Container existiert nicht.\n");
+ return;
+ }
+
+ // NOTE(fusion): Report stimulus as `OBJECT_CHANGED`.
+ Type = OBJECT_CHANGED;
+
+ // NOTE(fusion): Perform a secondary search if the distances are beyond
+ // the stimulus diameter or, extend the primary search otherwise.
+ int OldX, OldY, OldZ;
+ GetObjectCoordinates(OldCon, &OldX, &OldY, &OldZ);
+ int DistanceX = std::abs(ObjX - OldX);
+ int DistanceY = std::abs(ObjY - OldY);
+ if(DistanceX > (StimulusRadius * 2) || DistanceY > (StimulusRadius * 2)){
+ TFindCreatures Search(StimulusRadius, StimulusRadius, OldX, OldY, FIND_ALL);
+ while(true){
+ uint32 SpectatorID = Search.getNext();
+ if(SpectatorID == 0){
+ break;
+ }
+
+ // TODO(fusion): Check if the spectator is NULL?
+ TCreature *Spectator = GetCreature(SpectatorID);
+ Spectator->CreatureMoveStimulus(CreatureID, Type);
+ }
+ }else{
+ SearchRadiusX = StimulusRadius + (DistanceX + 1) / 2;
+ SearchRadiusY = StimulusRadius + (DistanceY + 1) / 2;
+ SearchCenterX = (ObjX + OldX) / 2;
+ SearchCenterY = (ObjY + OldY) / 2;
+ }
+ }
+
+ TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_ALL);
+ while(true){
+ uint32 SpectatorID = Search.getNext();
+ if(SpectatorID == 0){
+ break;
+ }
+
+ // TODO(fusion): Check if the spectator is NULL?
+ TCreature *Spectator = GetCreature(SpectatorID);
+ Spectator->CreatureMoveStimulus(CreatureID, Type);
+ }
+}
+
+void NotifyTrades(Object Obj){
+ if(!Obj.exists()){
+ error("NotifyTrades: Übergebenes Objekt existiert nicht.\n");
+ return;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(ObjType.isCreatureContainer()){
+ return;
+ }
+
+ // TODO(fusion): These radii seem to be correct but I'm skeptical because
+ // you're required to be close to the trade object to even start the trade.
+ // Maybe you can walk around after a trade is started?
+ TFindCreatures Search(12, 10, Obj, FIND_PLAYERS);
+ while(true){
+ uint32 CharacterID = Search.getNext();
+ if(CharacterID == 0){
+ break;
+ }
+
+ TPlayer *Player = GetPlayer(CharacterID);
+ if(Player == NULL){
+ error("NotifyTrade: Spieler existiert nicht.\n");
+ continue;
+ }
+
+ Object TradeObject = Player->InspectTrade(true, 0);
+ if(TradeObject != NONE){
+ if(IsHeldByContainer(Obj, TradeObject) || IsHeldByContainer(TradeObject, Obj)){
+ SendCloseTrade(Player->Connection);
+ SendMessage(Player->Connection, TALK_FAILURE_MESSAGE, "Trade cancelled.");
+ Player->RejectTrade();
+ }
+ }
+ }
+}
+
+void NotifyDepot(uint32 CreatureID, Object Obj, int Count){
+ if(CreatureID == 0){
+ return;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("NotifyDepot: Kreatur %u existiert nicht.\n", CreatureID);
+ // TODO(fusion): We should probably also throw here.
+ //throw ERROR;
+ return;
+ }
+
+ if(!Obj.exists()){
+ error("NotifyDepot: Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(Creature->Type == PLAYER){
+ TPlayer *Player = (TPlayer*)Creature;
+ if(Player->Depot == NONE){
+ return;
+ }
+
+ if(IsHeldByContainer(Obj, Player->Depot)){
+ Player->DepotSpace += Count;
+ print(3, "Neuer Depot-Freiraum für %s: %d\n",
+ Player->Name, Player->DepotSpace);
+ }
+ }
+}
+
+void CloseContainer(Object Con, bool Force){
+ if(!Con.exists()){
+ error("CloseContainer: Übergebener Container existiert nicht.\n");
+ return;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(ConType.isCreatureContainer()){
+ return;
+ }
+
+ // TODO(fusion): Similar to `NotifyTrades`.
+ TFindCreatures Search(12, 10, Con, FIND_PLAYERS);
+ while(true){
+ uint32 CharacterID = Search.getNext();
+ if(CharacterID == 0){
+ break;
+ }
+
+ TPlayer *Player = GetPlayer(CharacterID);
+ if(Player == NULL){
+ error("CloseContainer: Spieler existiert nicht.\n");
+ continue;
+ }
+
+ for(int ContainerNr = 0;
+ ContainerNr < NARRAY(Player->OpenContainer);
+ ContainerNr += 1){
+ Object OpenCon = Player->GetOpenContainer(ContainerNr);
+ if(IsHeldByContainer(OpenCon, Con)){
+ if(Force || !ObjectAccessible(Player->ID, Con, 1)){
+ Player->SetOpenContainer(ContainerNr, NONE);
+ SendCloseContainer(Player->Connection, ContainerNr);
+ }else{
+ // TODO(fusion): Why are we doing this? Is the container being refreshed?
+ SendContainer(Player->Connection, ContainerNr);
+ }
+ }
+ }
+ }
+}
+
+Object Create(Object Con, ObjectType Type, uint32 Value){
+ if(!Con.exists()){
+ error("Create: Zielobjekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.getFlag(CONTAINER) && !ConType.getFlag(CHEST)){
+ error("Create: Zielobjekt ist kein Container.\n");
+ throw ERROR;
+ }
+
+ // TODO(fusion): The map container does indeed use type id zero but it seems
+ // it is also considered a "no type" id so we might also want to add an alias
+ // to it as `isValid()`, `isVoid()`, `isNone()`, or `isNull()` perhaps.
+ if(Type.isMapContainer()){
+ error("Create: Objekttyp existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(ConType.isMapContainer()){
+ CheckMapPlace(0, Type, Con);
+ }else if(ConType.isBodyContainer()){
+ CheckInventoryPlace(Type, Con, NONE);
+ }else{
+ CheckContainerPlace(Type, Con, NONE);
+ }
+
+ uint32 ConOwnerID = GetObjectCreatureID(Con);
+ if(ConOwnerID != 0){
+ CheckWeight(ConOwnerID, Type, Value, 0);
+ }
+
+ // NOTE(fusion): Attempt to merge with top object.
+ if(ConType.isMapContainer() && Type.getFlag(CUMULATIVE)){
+ int ConX, ConY, ConZ;
+ GetObjectCoordinates(Con, &ConX, &ConY, &ConZ);
+ Object Top = GetTopObject(ConX, ConY, ConZ, true);
+ if(Top != NONE && Top.getObjectType() == Type){
+ uint32 Count = Top.getAttribute(AMOUNT);
+ if(Value != 0){
+ Count += Value;
+ }else{
+ Count += 1;
+ }
+
+ if(Count <= 100){
+ Change(Top, AMOUNT, Count);
+ return Top;
+ }
+ }
+ }
+
+ // TODO(fusion): I feel these usages of `Value` should be exclusive?
+
+ Object Obj = SetObject(Con, Type, (Type.isCreatureContainer() ? Value : 0));
+
+ if(Type.getFlag(CUMULATIVE)){
+ ChangeObject(Obj, AMOUNT, Value);
+ }
+
+ if(Type.getFlag(MAGICFIELD)){
+ ChangeObject(Obj, RESPONSIBLE, Value);
+ }
+
+ if(Type.getFlag(LIQUIDPOOL)){
+ ChangeObject(POOLLIQUIDTYPE, Value);
+ }
+
+ if(Type.getFlag(LIQUIDCONTAINER)){
+ ChangeObject(CONTAINERLIQUIDTYPE, Value);
+ }
+
+ if(Type.getFlag(KEY)){
+ ChangeObject(KEYNUMBER, Value);
+ }
+
+ if(Type.getFlag(RUNE)){
+ ChangeObject(CHARGES, Value);
+ }
+
+ if(Type.isCreatureContainer()){
+ // BUG(fusion): We should just check this before creating the object.
+ // Also, using `Delete` instead of `DeleteObject` here is problematic
+ // because the object's placement wasn't yet broadcasted.
+ TCreature *Creature = GetCreature(Value);
+ if(Creature == NULL){
+ error("Create: Ungültige Kreatur-ID %u\n", Value);
+ Delete(Obj, -1);
+ throw ERROR;
+ }
+
+ // IMPORTANT(fusion): Creature body containers are created here and their
+ // type ids match inventory slots exactly. We're looping in reverse because
+ // `SetObject` will insert objects at the front of the object chain.
+ for(int Position = INVENTORY_LAST;
+ Position >= INVENTORY_FIRST;
+ Position -= 1){
+ SetObject(Obj, ObjectType(Position), 0);
+ }
+
+ Creature->NotifyCreate();
+ }
+
+ AnnounceChangedObject(Obj, OBJECT_CREATED);
+ NotifyTrades(Obj);
+ NotifyCreature(ConOwnerID, Obj, ConType.isBodyContainer());
+ MovementEvent(Obj, Con, Con); // TODO(fusion): This one doesn't make a lot of sense.
+ CollisionEvent(Obj, Con);
+ NotifyAllCreatures(Obj, OBJECT_CREATED, NONE);
+ return Obj;
+}
+
+Object Copy(Object Con, Object Source){
+ if(!Con.exists()){
+ error("Copy: Ziel existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.getFlag(CONTAINER) && !ConType.getFlag(CHEST)){
+ error("Copy: Ziel ist kein Container.\n");
+ throw ERROR;
+ }
+
+ if(!Source.exists()){
+ error("Copy: Quelle existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType SourceType = Source.getObjectType();
+ if(SourceType.isCreatureContainer()){
+ error("Copy: Quelle ist eine Kreatur.\n");
+ throw ERROR;
+ }
+
+ if(ConType.isMapContainer()){
+ CheckMapDestination(0, Source, Con);
+ }else if(ConType.isBodyContainer()){
+ // TODO(fusion): Not sure about this third param.
+ CheckInventoryDestination(Source, Con, true);
+ }else{
+ CheckContainerDestination(Source, Con);
+ }
+
+ uint32 ConOwnerID = GetObjectCreatureID(Con);
+ if(ConOwnerID != 0){
+ CheckWeight(ConOwnerID, Source, -1);
+ }
+
+ // TODO(fusion): Using `Copy` recursively here should work because the object
+ // is placed when `CopyObject` is called. The thing is, announce and notify
+ // functions will do meaningless work there (I think, check what happens when
+ // we're actually running).
+ Object Obj = CopyObject(Con, Source);
+ if(SourceType.getFlag(CONTAINER)){
+ Object Help = GetFirstContainerObject(Source);
+ while(Help != NONE){
+ Copy(Obj, Help);
+ Help = Help.getNextObject();
+ }
+ }
+
+ AnnounceChangedObject(Obj, OBJECT_CREATED);
+ NotifyTrades(Obj);
+ NotifyCreature(ConOwnerID, Obj, ConType.isBodyContainer());
+ MovementEvent(Obj, Con, Con); // TODO(fusion): Same as `Create`.
+ CollisionEvent(Obj, Con);
+ NotifyAllCreatures(Obj, OBJECT_CREATED, NONE);
+ return Obj;
+}
+
void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Object Ignore){
if(!Obj.exists()){
error("Move: Übergebenes Objekt existiert nicht.\n");
@@ -778,6 +1375,10 @@ void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Ob
// TODO(fusion): This could probably be moved to the end of the function
// along with the other `CloseContainer`.
+ // Probably the other way around, since events could modify the object
+ // and I don't think it makes a difference if we close it before or after
+ // performing the move.
+ // Except it does because the object's position will be different lol.
if(ObjType.getFlag(CONTAINER) && CreatureID == 0){
CloseContainer(Obj, true);
}
@@ -825,7 +1426,7 @@ void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Ob
MovementEvent(Obj, OldCon, Con);
CollisionEvent(Obj, Con);
- NotifyAllCreatures(Obj, 3, OldCon); // CREATURE_MOVE_STIMULUS_ ?
+ NotifyAllCreatures(Obj, OBJECT_MOVED, OldCon);
}
void Merge(uint32 CreatureID, Object Obj, Object Dest, int Count, Object Ignore){
@@ -910,5 +1511,296 @@ void Merge(uint32 CreatureID, Object Obj, Object Dest, int Count, Object Ignore)
NotifyCreature(ObjOwnerID, Dest, ObjCon.getObjectType().isBodyContainer());
NotifyCreature(DestOwnerID, Dest, DestCon.getObjectType().isBodyContainer());
CollisionEvent(Dest, DestCon);
- NotifyAllCreatures(Dest, 2, NONE); // CREATURE_MOVE_STIMULUS_ ?
+ NotifyAllCreatures(Dest, OBJECT_CHANGED, NONE);
+}
+
+void Change(Object Obj, ObjectType NewType, uint32 Value){
+ if(Obj.exists()){
+ error("Change: Übergebenes Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType OldType = Obj.getObjectType();
+ if(OldType.isCreatureContainer() || NewType.isCreatureContainer()){
+ error("Change: Kann keine Kreaturen verändern.\n");
+ throw ERROR;
+ }
+
+ // TODO(fusion): Same thing as `Create`. The zero type id is also used as
+ // a "no type" id.
+ if(NewType.isMapContainer()){
+ Delete(Obj, -1);
+ return;
+ }
+
+ if(OldType.getFlag(CONTAINER)){
+ if(!NewType.getFlag(CONTAINER) && GetFirstContainerObject(Obj) != NONE){
+ error("Change: Zielobjekt %d für %d ist kein Container mehr.\n",
+ NewType.TypeID, OldType.TypeID);
+ throw EMPTYCONTAINER;
+ }
+
+ if(NewType.getFlag(CONTAINER)){
+ int ObjectCount = CountObjectsInContainer(Obj);
+ int NewCapacity = (int)NewType.getAttribute(CAPACITY);
+ if(ObjectCount < NewCapacity){
+ error("Change: Zielobjekt %d für %d ist kleinerer Container.\n",
+ NewType.TypeID, OldType.TypeID);
+ throw EMPTYCONTAINER;
+ }
+ }
+ }
+
+ if(OldType.getFlag(CHEST) && !NewType.getFlag(CHEST)){
+ error("Change: Schatztruhe muß Schatztruhe bleiben.\n");
+ throw ERROR;
+ }
+
+ if(OldType.getFlag(CUMULATIVE)
+ && OldType != NewType
+ && Obj.getAttribute(AMOUNT) > 1){
+ throw SPLITOBJECT;
+ }
+
+ Object Con = Obj.getContainer();
+ ObjectType ConType = Con.getObjectType();
+ uint32 ObjOwnerID = GetObjectCreatureID(Obj);
+ if(ObjOwnerID != 0 && OldType != NewType){
+ if(ConType.isBodyContainer()){
+ CheckInventoryPlace(NewType, Con, Obj);
+ }else{
+ CheckContainerPlace(NewType, Con, Obj);
+ }
+
+ uint32 Count = 1;
+ if(OldType.getFlag(CUMULATIVE)){
+ Count = Obj.getAttribute(AMOUNT);
+ }
+
+ int OldWeight = GetWeight(Obj, -1);
+ CheckWeight(ObjOwnerID, NewType, Count, OldWeight);
+ }
+
+ if(OldType.getFlag(CONTAINER) && !NewType.getFlag(CONTAINER)){
+ CloseContainer(Obj, true);
+ }
+
+ ChangeObject(Obj, NewType);
+
+ // TODO(fusion): Same thing as `Create`. I feel these usages of `Value`
+ // should be exclusive.
+
+ if(NewType.getFlag(CUMULATIVE) && !OldType.getFlag(CUMULATIVE)){
+ ChangeObject(Obj, AMOUNT, Value);
+ }
+
+ if(NewType.getFlag(MAGICFIELD) && !OldType.getFlag(MAGICFIELD)){
+ ChangeObject(Obj, RESPONSIBLE, Value);
+ }
+
+ if(NewType.getFlag(LIQUIDPOOL) && !OldType.getFlag(LIQUIDPOOL)){
+ ChangeObject(Obj, POOLLIQUIDTYPE, Value);
+ }
+
+ if(NewType.getFlag(LIQUIDCONTAINER) && !OldType.getFlag(LIQUIDCONTAINER)){
+ ChangeObject(Obj, CONTAINERLIQUIDTYPE, Value);
+ }
+
+ if(NewType.getFlag(KEY) && !OldType.getFlag(KEY)){
+ ChangeObject(Obj, KEYNUMBER, Value);
+ }
+
+ if(NewType.getFlag(RUNE) && !OldType.getFlag(RUNE)){
+ ChangeObject(Obj, CHARGES, Value);
+ }
+
+ AnnounceChangedObject(Obj, OBJECT_CHANGED);
+ NotifyTrades(Obj);
+ NotifyCreature(ObjOwnerID, Obj, ConType.isBodyContainer());
+ NotifyAllCreatures(Obj, OBJECT_CHANGED, NONE);
+}
+
+void Change(Object Obj, INSTANCEATTRIBUTE Attribute, uint32 Value){
+ if(!Obj.exists()){
+ error("Change: Übergebenes Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(Attribute == CONTENT
+ || Attribute == CHESTQUESTNUMBER
+ || Attribute == DOORLEVEL
+ || Attribute == DOORQUESTNUMBER
+ || Attribute == DOORQUESTVALUE
+ || Attribute == ABSTELEPORTDESTINATION
+ || Attribute == REMAININGEXPIRETIME){
+ error("Change: Kann Attribut %d nicht ändern.\n", Attribute);
+ throw ERROR;
+ }
+
+ uint32 ObjOwnerID = GetObjectCreatureID(Obj);
+ if(ObjOwnerID != 0 && Attribute == AMOUNT && Value > Obj.getAttribute(AMOUNT)){
+ int OldWeight = GetWeight(Obj, -1);
+ CheckWeight(ObjOwnerID, Obj.getObjectType(), Value, OldWeight);
+ }
+
+ ChangeObject(Obj, Attribute, Value);
+ if(Attribute == AMOUNT
+ || Attribute == CONTAINERLIQUIDTYPE
+ || Attribute == POOLLIQUIDTYPE){
+ AnnounceChangedObject(Obj, OBJECT_CHANGED);
+ }
+
+ NotifyTrades(Obj);
+ NotifyCreature(ObjOwnerID, Obj, Obj.getContainer().getObjectType().isBodyContainer());
+}
+
+void Delete(Object Obj, int Count){
+ if(!Obj.exists()){
+ error("Delete: Übergebenes Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(ObjType.getFlag(CUMULATIVE) && Count > (int)Obj.getAttribute(AMOUNT)){
+ error("Delete: Ungültige Anzahl %d an Teilen bei kumulierbarem Objekt.\n", Count);
+ throw ERROR;
+ }
+
+ Object Remainder = NONE;
+ if(ObjType.getFlag(CUMULATIVE) && Count != -1
+ && Count < (int)Obj.getAttribute(AMOUNT)){
+ Remainder = Obj;
+ Obj = SplitObject(Obj, Count);
+ }else{
+ NotifyTrades(Obj);
+ }
+
+ if(ObjType.getFlag(CONTAINER) || ObjType.getFlag(CHEST)){
+ if(ObjType.getFlag(CONTAINER)){
+ CloseContainer(Obj, true);
+ }
+
+ Object Help = GetFirstContainerObject(Obj);
+ while(Help != NONE){
+ Object Next = Help.getNextObject();
+ DeleteObject(Help);
+ Help = Next;
+ }
+ }
+
+ Object Con = Obj.getContainer();
+ uint32 ObjOwnerID = GetObjectCreatureID(Obj);
+ SeparationEvent(Obj, Con);
+
+ // BUG(fusion): Object may have been destroyed by the separation event? This
+ // looks suspicious because even if the object is properly destroyed, its
+ // remainder could be left unannounced.
+ // If it's a container, its objects don't get a separation event trigger,
+ // and the separation event trigger on the container itself is only triggered
+ // after it is empty.
+ if(Obj.exists()){
+ if(Remainder == NONE){
+ AnnounceChangedObject(Obj, OBJECT_DELETED);
+ }
+
+ NotifyAllCreatures(Obj, OBJECT_DELETED, NONE);
+ if(ObjType.isCreatureContainer()){
+ TCreature *Creature = GetCreature(ObjOwnerID);
+ if(Creature != NULL){
+ Creature->NotifyDelete();
+ }else{
+ error("Delete: Kreatur mit ungültiger ID %d.\n", ObjOwnerID);
+ }
+ }
+
+ DeleteObject(Obj);
+
+ if(Remainder != NONE){
+ AnnounceChangedObject(Remainder, OBJECT_CHANGED);
+ NotifyTrades(Remainder);
+ }
+
+ NotifyCreature(ObjOwnerID, ObjType, Con.getObjectType().isBodyContainer());
+ }
+}
+
+void Empty(Object Con, int Remainder){
+ if(!Con.exists()){
+ error("Empty: Übergebener Container existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(Remainder < 0){
+ error("Empty: Ungültiger Rest %d.\n", Remainder);
+ throw ERROR;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.getFlag(CONTAINER)){
+ error("Empty: Übergebenes Objekt ist kein Container.\n");
+ throw ERROR;
+ }
+
+ CloseContainer(Con, true);
+
+ bool IsCorpse = ConType.getFlag(CORPSE);
+ int ObjectCount = CountObjectsInContainer(Con);
+ Object Help = GetFirstContainerObject(Con);
+ while(Help != NONE && ObjectCount > Remainder){
+ Object Next = Help.getNextObject();
+ if(IsCorpse){
+ Delete(Help, -1);
+ }else{
+ Move(0, Help, Con.getContainer(), -1, false, NONE);
+ }
+ Help = Next;
+ ObjectCount -= 1;
+ }
+}
+
+void GraphicalEffect(int x, int y, int z, int Type){
+ AnnounceGraphicalEffect(x, y, z, Type);
+}
+
+void GraphicalEffect(Object Obj, int Type){
+ if(Obj.exists()){
+ int ObjX, ObjY, ObjZ;
+ GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ);
+ AnnounceGraphicalEffect(ObjX, ObjY, ObjZ, Type);
+ }
+}
+
+void TextualEffect(Object Obj, int Color, const char *Format, ...){
+ if(!Obj.exists()){
+ error("TextualEffect: Übergebener Mapcontainer existiert nicht.\n");
+ return;
+ }
+
+ char Buffer[10];
+ va_list ap;
+ va_start(ap, Format);
+ vsnprintf(Buffer, sizeof(Buffer), Format, ap);
+ va_end(ap);
+
+ int ObjX, ObjY, ObjZ;
+ GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ);
+ AnnounceTextualEffect(ObjX, ObjY, ObjZ, Color, Buffer);
+}
+
+void Missile(Object Start, Object Dest, int Type){
+ if(!Start.exists()){
+ error("Missile: Übergebener Startpunkt existiert nicht.\n");
+ return;
+ }
+
+ if(!Dest.exists()){
+ error("Missile: Übergebener Zielpunkt existiert nicht.\n");
+ return;
+ }
+
+ int StartX, StartY, StartZ;
+ int DestX, DestY, DestZ;
+ GetObjectCoordinates(Start, &StartX, &StartY, &StartZ);
+ GetObjectCoordinates(Dest, &DestX, &DestY, &DestZ);
+ AnnounceMissile(StartX, StartY, StartZ, DestX, DestY, DestZ, Type);
}
diff --git a/src/operate.hh b/src/operate.hh
index de7b54d..7d137fd 100644
--- a/src/operate.hh
+++ b/src/operate.hh
@@ -17,9 +17,49 @@ enum : int {
OBJECT_DELETED = 0,
OBJECT_CREATED = 1,
OBJECT_CHANGED = 2,
+ OBJECT_MOVED = 3,
};
+void AnnounceMovingCreature(uint32 CreatureID, Object Con);
+void AnnounceChangedCreature(uint32 CreatureID, int Type);
+void AnnounceChangedField(Object Obj, int Type);
+void AnnounceChangedContainer(Object Obj, int Type);
+void AnnounceChangedInventory(Object Obj, int Type);
+void AnnounceChangedObject(Object Obj, int Type);
+void AnnounceGraphicalEffect(int x, int y, int z, int Type);
+void AnnounceTextualEffect(int x, int y, int z, int Color, const char *Text);
+void AnnounceMissile(int OrigX, int OrigY, int OrigZ,
+ int DestX, int DestY, int DestZ, int Type);
+void CheckTopMoveObject(uint32 CreatureID, Object Obj, Object Ignore);
+void CheckTopUseObject(uint32 CreatureID, Object Obj);
+void CheckTopMultiuseObject(uint32 CreatureID, Object Obj);
+void CheckMoveObject(uint32 CreatureID, Object Obj, bool Take);
+void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon);
+void CheckMapPlace(uint32 CreatureID, ObjectType Type, Object MapCon);
void CheckContainerDestination(Object Obj, Object Con);
+void CheckContainerPlace(ObjectType Type, Object Con, Object OldObj);
+void CheckDepotSpace(uint32 CreatureID, Object Source, Object Destination, int Count);
void CheckInventoryDestination(Object Obj, Object Con, bool Split);
+void CheckInventoryPlace(ObjectType Type, Object Con, Object OldObj);
+void CheckWeight(uint32 CreatureID, Object Obj, int Count);
+void CheckWeight(uint32 CreatureID, ObjectType Type, uint32 Value, int OldWeight);
+void NotifyCreature(uint32 CreatureID, Object Obj, bool Inventory);
+void NotifyCreature(uint32 CreatureID, ObjectType Type, bool Inventory);
+void NotifyAllCreatures(Object Obj, int Type, Object OldCon);
+void NotifyTrades(Object Obj);
+void NotifyDepot(uint32 CreatureID, Object Obj, int Count);
+void CloseContainer(Object Con, bool Force);
+Object Create(Object Con, ObjectType Type, uint32 Value);
+Object Copy(Object Con, Object Source);
+void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Object Ignore);
+void Merge(uint32 CreatureID, Object Obj, Object Dest, int Count, Object Ignore);
+void Change(Object Obj, ObjectType NewType, uint32 Value);
+void Change(Object Obj, INSTANCEATTRIBUTE Attribute, uint32 Value);
+void Delete(Object Obj, int Count);
+void Empty(Object Con, int Remainder);
+void GraphicalEffect(int x, int y, int z, int Type);
+void GraphicalEffect(Object Obj, int Type);
+void TextualEffect(Object Obj, int Color, const char *Format, ...) ATTR_PRINTF(3, 4);
+void Missile(Object Start, Object Dest, int Type);
#endif //TIBIA_OPERATE_HH_
diff --git a/src/stubs.hh b/src/stubs.hh
index 4104dd3..c8b2e63 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -15,10 +15,7 @@ typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, const
typedef void TSendMailsFunction(TPlayerData *PlayerData);
extern void AbortWriter(void);
-extern void AnnounceChangedCreature(uint32 CreatureID, int Type);
-extern void AnnounceChangedObject(Object Obj, int Type);
extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3);
-extern void Change(Object Obj, ObjectType NewType, uint32 Value);
extern void ChangeNPCState(TCreature *Npc, int NewState, bool Stimulus);
extern void CharacterDeathOrder(TCreature *Creature, int OldLevel,
uint32 Offender, const char *Remark, bool Unjustified);
@@ -26,18 +23,14 @@ extern bool CheckRight(uint32 CreatureID, RIGHT Right);
extern void CleanHouseField(int x, int y, int z);
extern void ConvinceMonster(TCreature *Master, TCreature *Slave);
extern void ChallengeMonster(TCreature *Challenger, TCreature *Monster);
-extern Object Create(Object Con, ObjectType Type, uint32 Value);
extern Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value);
extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect);
extern void CreatePlayerList(bool Online);
extern void CreatePool(Object Con, ObjectType Type, uint32 Value);
-extern void Delete(Object Obj, int Count);
extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
extern TPlayer *GetPlayer(uint32 CreatureID);
-extern void GraphicalEffect(int x, int y, int z, int Type);
-extern void GraphicalEffect(Object Obj, int Type);
extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player);
extern void InitLog(const char *ProtocolName);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);
@@ -47,12 +40,8 @@ extern void LoadMonsterRaid(const char *FileName, int Start,
bool *Type, int *Date, int *Interval, int *Duration);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void LogoutAllPlayers(void);
-extern void Missile(Object Start, Object Dest, int Type);
-extern void Merge(uint32 CreatureID, Object Obj, Object Dest, int Count, Object Ignore);
-extern void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Object Ignore);
extern void NetLoadCheck(void);
extern void NetLoadSummary(void);
-extern void NotifyAllCreatures(Object Obj, int Type, Object OldCon);
extern void ProcessCommunicationControl(void);
extern void ProcessConnections(void);
extern void ProcessCronSystem(void);
@@ -67,6 +56,7 @@ extern void SavePlayerDataOrder(void);
extern void SendAll(void);
extern void SendAmbiente(TConnection *Connection);
extern void SendClearTarget(TConnection *Connection);
+extern void SendContainer(TConnection *Connection, int ContainerNr);
extern void SendCloseContainer(TConnection *Connection, int ContainerNr);
extern void SendCloseTrade(TConnection *Connection);
extern void SendCreatureHealth(TConnection *Connection, uint32 CreatureID);
@@ -104,8 +94,10 @@ extern void ShowGuestList(uint16 HouseID, TPlayer *Player, char *Buffer);
extern void ShowSubownerList(uint16 HouseID, TPlayer *Player, char *Buffer);
extern void ShowNameDoor(Object Door, TPlayer *Player, char *Buffer);
extern void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text, bool CheckSpamming);
-extern void TextualEffect(Object Obj, int Color, const char *Text, ...) ATTR_PRINTF(3, 4);
extern void Turn(uint32 CreatureID, Object Obj);
extern void Use(uint32 CreatureID, Object Obj1, Object Object2, uint8 Info);
+extern void MovementEvent(Object Obj, Object Start, Object Dest);
+extern void CollisionEvent(Object Obj, Object Dest);
+extern void SeparationEvent(Object Obj, Object Start);
#endif //TIBIA_STUBS_HH_