aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-15 17:35:06 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-15 17:35:06 -0300
commit3cc587ab8df80d42d9dab1a73a37701f565a3499 (patch)
treeea10cae94a9ef7a3c9b4080746a9697287e8991b
parent33464579f6b8b079597617593d2bb733e982db8f (diff)
downloadgame-3cc587ab8df80d42d9dab1a73a37701f565a3499.tar.gz
game-3cc587ab8df80d42d9dab1a73a37701f565a3499.zip
more work on `operate.cc`
-rw-r--r--reference/game.c1987
-rw-r--r--reference/types.hh41
-rw-r--r--src/connection.hh2
-rw-r--r--src/containers.hh37
-rw-r--r--src/cr.hh3
-rw-r--r--src/crmain.cc23
-rw-r--r--src/crplayer.cc1
-rw-r--r--src/info.hh1
-rw-r--r--src/main.cc3
-rw-r--r--src/objects.hh11
-rw-r--r--src/operate.cc1025
-rw-r--r--src/operate.hh96
-rw-r--r--src/stubs.hh38
13 files changed, 1208 insertions, 2060 deletions
diff --git a/reference/game.c b/reference/game.c
index 186295c..5fd4ee7 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -18375,1356 +18375,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-void Use(ulong CreatureID,Object *Obj1,Object *Obj2,uchar Info)
-
-{
- bool bVar1;
- bool bVar2;
- ulong uVar3;
- undefined4 *puVar4;
- TCreature *pTVar5;
- char *Text;
- Object *this;
- TCreature *cr;
- int iStack_68;
- uchar Info_local;
- int x;
- int y;
- int z;
- Object local_4c [4];
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 080970b2 to 080978b7 has its CatchHandler @ 080978d3
- bVar1 = Object::exists(Obj1);
- if (bVar1) {
- bVar1 = false;
- local_2c[0].ObjectID = NONE.ObjectID;
- local_3c[0].ObjectID = NONE.ObjectID;
- if ((Obj2->ObjectID != NONE.ObjectID) && (bVar2 = Object::exists(Obj2), !bVar2)) {
- bVar1 = true;
- }
- if (!bVar1) {
- local_3c[0] = (Object)Obj1->ObjectID;
- CheckTopUseObject(CreatureID,local_3c);
- local_3c[0] = (Object)Obj1->ObjectID;
- bVar1 = ObjectAccessible(CreatureID,local_3c,1);
- if (bVar1) {
- bVar1 = false;
- local_3c[0].ObjectID = NONE.ObjectID;
- local_2c[0].ObjectID = NONE.ObjectID;
- uVar3 = Obj2->ObjectID;
- if (uVar3 != NONE.ObjectID) {
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,DISTUSE);
- bVar1 = !bVar1;
- uVar3 = Obj2->ObjectID;
- }
- if (bVar1) {
- local_2c[0].ObjectID = uVar3;
- CheckTopMultiuseObject(CreatureID,local_2c);
- uVar3 = Obj2->ObjectID;
- }
- bVar1 = false;
- local_3c[0].ObjectID = NONE.ObjectID;
- local_2c[0].ObjectID = NONE.ObjectID;
- if ((uVar3 != NONE.ObjectID) &&
- (local_2c[0].ObjectID = uVar3, bVar2 = ObjectAccessible(CreatureID,local_2c,1),
- !bVar2)) {
- bVar1 = true;
- }
- if (bVar1) {
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,DISTUSE);
- if (!bVar1) goto LAB_0809780e;
- pTVar5 = GetCreature(CreatureID);
- if (pTVar5 == (TCreature *)0x0) {
- Text = "Use: Verursachende Kreatur existiert nicht.\n";
- goto LAB_080977f2;
- }
- local_4c[0] = (Object)Obj2->ObjectID;
- GetObjectCoordinates(local_4c,&stack0xffffff98,&x,&y);
- if (y < pTVar5->posz) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0x17;
- goto LAB_0809762d;
- }
- if (pTVar5->posz < y) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0x18;
- goto LAB_0809762d;
- }
- bVar1 = ThrowPossible(pTVar5->posx,pTVar5->posy,pTVar5->posz,iStack_68,x,y,0);
- if (!bVar1) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 7;
- goto LAB_0809762d;
- }
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CONTAINER);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseContainer(CreatureID,local_4c,Info);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CHEST);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseChest(CreatureID,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,LIQUIDCONTAINER);
- if (bVar1) {
- local_4c[0] = (Object)Obj2->ObjectID;
- local_3c[0] = (Object)Obj1->ObjectID;
- UseLiquidContainer(CreatureID,local_3c,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,FOOD);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseFood(CreatureID,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,WRITE);
- if (!bVar1) {
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,WRITEONCE);
- if (!bVar1) {
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,INFORMATION);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseAnnouncer(CreatureID,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,RUNE);
- if (bVar1) {
- local_4c[0] = (Object)Obj2->ObjectID;
- local_3c[0] = (Object)Obj1->ObjectID;
- UseMagicItem(CreatureID,local_3c,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,KEY);
- if (bVar1) {
- local_4c[0] = (Object)Obj2->ObjectID;
- local_3c[0] = (Object)Obj1->ObjectID;
- UseKeyDoor(CreatureID,local_3c,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,NAMEDOOR);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseNameDoor(CreatureID,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,LEVELDOOR);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseLevelDoor(CreatureID,local_4c);
- return;
- }
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,QUESTDOOR);
- if (bVar1) {
- local_4c[0] = (Object)Obj1->ObjectID;
- UseQuestDoor(CreatureID,local_4c);
- return;
- }
- bVar1 = false;
- Object::getObjectType(local_4c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_4c,WEAPON);
- if (bVar2) {
- Object::getObjectType(local_4c);
- uVar3 = ObjectType::getAttribute((ObjectType *)local_4c,WEAPONTYPE);
- bVar2 = false;
- if ((0 < (int)uVar3) && ((int)uVar3 < 4)) {
- bVar2 = true;
- }
- if (bVar2) {
- local_4c[0] = (Object)NONE.ObjectID;
- local_3c[0].ObjectID = NONE.ObjectID;
- if (Obj2->ObjectID != NONE.ObjectID) {
- Object::getObjectType(local_3c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_3c,DESTROY);
- if (bVar2) {
- bVar1 = true;
- }
- }
- }
- }
- if (bVar1) {
- local_3c[0] = (Object)Obj2->ObjectID;
- local_2c[0] = (Object)Obj1->ObjectID;
- UseWeapon(CreatureID,local_2c,local_3c);
- return;
- }
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CHANGEUSE);
- if (bVar1) {
- local_3c[0] = (Object)Obj1->ObjectID;
- UseChangeObject(CreatureID,local_3c);
- return;
- }
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,USEEVENT);
- if ((bVar1) &&
- (local_3c[0].ObjectID = NONE.ObjectID, Obj2->ObjectID == NONE.ObjectID))
- {
- local_2c[0] = (Object)Obj1->ObjectID;
- UseObject(CreatureID,local_2c);
- return;
- }
- Object::getObjectType(local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,USEEVENT);
- if (bVar1) {
- local_2c[0] = (Object)Obj2->ObjectID;
- z = Obj1->ObjectID;
- UseObjects(CreatureID,(Object *)&z,local_2c);
- return;
- }
- this = (Object *)&z;
- Object::getObjectType(this);
- bVar1 = ObjectType::getFlag((ObjectType *)this,TEXT);
- if (bVar1) {
- Object::getObjectType(this);
- uVar3 = ObjectType::getAttribute((ObjectType *)this,FONTSIZE);
- if (uVar3 == 1) {
- z = Obj1->ObjectID;
- goto LAB_080972e9;
- }
- }
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0x1d;
- goto LAB_0809762d;
- }
- }
- local_4c[0] = (Object)Obj1->ObjectID;
- this = local_4c;
-LAB_080972e9:
- UseTextObject(CreatureID,this);
- return;
- }
-LAB_0809780e:
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 1;
- goto LAB_0809762d;
- }
- Text = &DAT_081001e0;
- }
- else {
- Text = &DAT_08100220;
- }
-LAB_080977f2:
- error(Text);
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0xffffffff;
-LAB_0809762d:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar4,&RESULT::typeinfo,0);
-}
-
-
-
-void Turn(ulong CreatureID,Object *Obj)
-
-{
- bool bVar1;
- ulong _TypeID;
- undefined4 *puVar2;
- Object local_4c [4];
- Object local_3c [4];
- Object local_2c;
- ObjectType NewType;
-
- // try { // try from 08097905 to 08097a4e has its CatchHandler @ 08097a63
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- local_2c = (Object)Obj->ObjectID;
- bVar1 = ObjectAccessible(CreatureID,&local_2c,1);
- if (bVar1) {
- Object::getObjectType(&local_2c);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,ROTATE);
- if (bVar1) {
- Object::getObjectType(local_3c);
- _TypeID = ObjectType::getAttribute((ObjectType *)local_3c,ROTATETARGET);
- ObjectType::setTypeID((ObjectType *)&local_2c,_TypeID);
- ObjectType::setTypeID((ObjectType *)local_3c,0);
- if (local_2c.ObjectID == local_3c[0].ObjectID) {
- Object::getObjectType(local_4c);
- error(&DAT_08100260,local_4c[0].ObjectID);
- }
- ObjectType::setTypeID((ObjectType *)local_4c,local_2c.ObjectID);
- local_3c[0] = (Object)Obj->ObjectID;
- Change(local_3c,(ObjectType *)local_4c,0);
- return;
- }
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = 0x39;
- }
- else {
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = 1;
- }
- }
- else {
- error(&DAT_081002a0);
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = 0xffffffff;
- }
- // WARNING: Subroutine does not return
- __cxa_throw(puVar2,&RESULT::typeinfo,0);
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void CreatePool(void)
-
-{
- bool bVar1;
- undefined4 *puVar2;
- Object *in_stack_00000004;
- int *in_stack_00000008;
- char *Text;
- Object local_5c [4];
- ObjectType local_4c;
- Object Help;
- ObjectType local_3c [4];
- Object local_2c;
- Object Obj;
-
- // try { // try from 08097a95 to 08097bba has its CatchHandler @ 08097c76
- bVar1 = Object::exists(in_stack_00000004);
- if (bVar1) {
- Object::getObjectType(&local_2c);
- if (local_2c.ObjectID == 0) {
- local_3c[0].TypeID = in_stack_00000004->ObjectID;
- GetFirstContainerObject(&local_2c);
- if (local_2c.ObjectID != NONE.ObjectID) {
- do {
- local_4c.TypeID = local_2c.ObjectID;
- local_3c[0].TypeID = NONE.ObjectID;
- Object::getNextObject(local_5c);
- local_2c.ObjectID = local_5c[0].ObjectID;
- local_3c[0].TypeID = local_5c[0].ObjectID;
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,BOTTOM);
- if (bVar1) {
- Object::getObjectType(local_5c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_5c,LIQUIDPOOL);
- if (!bVar1) {
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = 4;
- goto LAB_08097bef;
- }
- local_5c[0].ObjectID = local_4c.TypeID;
- // try { // try from 08097bd3 to 08097bd7 has its CatchHandler @ 08097c30
- Delete(local_5c,-1);
- }
- } while (local_2c.ObjectID != NONE.ObjectID);
- }
- local_4c.TypeID = NONE.ObjectID;
- local_3c[0].TypeID = NONE.ObjectID;
- ObjectType::setTypeID(&local_4c,*in_stack_00000008);
- local_3c[0].TypeID = in_stack_00000004->ObjectID;
- Create(local_5c,local_3c,(ulong)&local_4c);
- return;
- }
- Text = &DAT_081002e0;
- }
- else {
- Text = &DAT_08100320;
- }
- error(Text);
- puVar2 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar2 = 0xffffffff;
-LAB_08097bef:
- // WARNING: Subroutine does not return
- // try { // try from 08097c02 to 08097c12 has its CatchHandler @ 08097c76
- __cxa_throw(puVar2,&RESULT::typeinfo,0);
-}
-
-
-
-void EditText(ulong CreatureID,Object *Obj,char *Text)
-
-{
- bool bVar1;
- TCreature *pTVar2;
- size_t sVar3;
- ulong uVar4;
- char *pcVar5;
- int iVar6;
- undefined4 *puVar7;
- TCreature *cr;
-
- // try { // try from 08097ca8 to 08097f12 has its CatchHandler @ 08097f30
- bVar1 = Object::exists(Obj);
- if (bVar1) {
- Object::getObjectType((Object *)&cr);
- bVar1 = ObjectType::getFlag((ObjectType *)&cr,WRITE);
- if (bVar1) {
-LAB_08097cdf:
- pTVar2 = GetCreature(CreatureID);
- if (pTVar2 != (TCreature *)0x0) {
- sVar3 = strlen(Text);
- Object::getObjectType((Object *)&cr);
- bVar1 = ObjectType::getFlag((ObjectType *)&cr,WRITE);
- Object::getObjectType((Object *)&cr);
- uVar4 = ObjectType::getAttribute((ObjectType *)&cr,!bVar1 + MAXLENGTH);
- if (uVar4 <= sVar3) {
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = 0x28;
- goto LAB_08097e92;
- }
- if (CreatureID != 0) {
- cr = (TCreature *)Obj->ObjectID;
- bVar1 = ObjectAccessible(CreatureID,(Object *)&cr,1);
- if (!bVar1) {
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = 1;
- goto LAB_08097e92;
- }
- }
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- if ((uVar4 == 0) && (*Text != '\0')) {
-LAB_08097dbf:
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- DeleteDynamicString(uVar4);
- cr = (TCreature *)Obj->ObjectID;
- uVar4 = AddDynamicString(Text);
- Change((Object *)&cr,TEXTSTRING,uVar4);
- uVar4 = Object::getAttribute(Obj,EDITOR);
- DeleteDynamicString(uVar4);
- cr = (TCreature *)Obj->ObjectID;
- uVar4 = AddDynamicString(pTVar2->Name);
- Change((Object *)&cr,EDITOR,uVar4);
- }
- else {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- if (uVar4 != 0) {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- pcVar5 = GetDynamicString(uVar4);
- iVar6 = strcmp(Text,pcVar5);
- if (iVar6 != 0) goto LAB_08097dbf;
- }
- print();
- }
- return;
- }
- pcVar5 = "EditText: Kreatur existiert nicht.\n";
- }
- else {
- Object::getObjectType((Object *)&cr);
- bVar1 = ObjectType::getFlag((ObjectType *)&cr,WRITEONCE);
- if (bVar1) {
- uVar4 = Object::getAttribute(Obj,TEXTSTRING);
- if (uVar4 == 0) goto LAB_08097cdf;
- }
- pcVar5 = "EditText: Objekt ist nicht beschreibbar.\n";
- }
- }
- else {
- pcVar5 = &DAT_08100440;
- }
- error(pcVar5);
- puVar7 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar7 = 0xffffffff;
-LAB_08097e92:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar7,&RESULT::typeinfo,0);
-}
-
-
-
-Object CreateAtCreature(ulong CreatureID,ObjectType *Type,ulong Value)
-
-{
- bool bVar1;
- bool bVar2;
- bool bVar3;
- TCreature *pTVar4;
- undefined4 *puVar5;
- int pos;
- int iVar6;
- ulong in_stack_00000010;
- Object *Type_00;
- Object *this;
- bool local_61;
- bool invert;
- bool first;
- TCreature *cr;
- Object local_4c;
- Object Obj;
- Object local_3c [4];
- Object local_2c [7];
-
- // try { // try from 08097f5f to 08097f63 has its CatchHandler @ 08098240
- pTVar4 = GetCreature((ulong)Type);
- if (pTVar4 == (TCreature *)0x0) {
- // try { // try from 08098159 to 08098187 has its CatchHandler @ 08098240
- error("GiveObjectToCreature: Kann Kreatur nicht finden.\n");
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar5,&RESULT::typeinfo,0);
- }
- // try { // try from 08097f7e to 08097fa3 has its CatchHandler @ 08098188
- ObjectType::setTypeID((ObjectType *)local_2c,*(int *)Value);
- CheckWeight((ulong)Type,(ObjectType *)local_2c,in_stack_00000010,0);
- local_61 = true;
- iVar6 = 0;
- // try { // try from 08097fb8 to 08097fbc has its CatchHandler @ 08098240
- bVar2 = ObjectType::getFlag((ObjectType *)Value,MOVEMENTEVENT);
- while( true ) {
- iVar6 = iVar6 + 1;
- // try { // try from 08097fd2 to 08097fd6 has its CatchHandler @ 08098210
- GetBodyObject((ulong)&local_4c,(int)Type);
- if ((local_61 != bVar2) &&
- (local_3c[0].ObjectID = NONE.ObjectID, local_4c.ObjectID == NONE.ObjectID)) {
- ObjectType::setTypeID((ObjectType *)local_2c,*(int *)Value);
- Type_00 = (Object *)&cr;
- GetBodyContainer((ulong)Type_00,(int)Type);
- this = local_2c;
- goto LAB_080980b2;
- }
- bVar1 = false;
- if (local_61 == bVar2) {
- cr = (TCreature *)NONE.ObjectID;
- local_3c[0].ObjectID = NONE.ObjectID;
- if (local_4c.ObjectID != NONE.ObjectID) {
- Object::getObjectType(local_3c);
- bVar3 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER);
- if (bVar3) {
- bVar1 = true;
- }
- }
- }
- if (bVar1) break;
- if (9 < iVar6) {
- if (local_61 == false) {
- // try { // try from 08098029 to 0809806b has its CatchHandler @ 08098240
- ObjectType::setTypeID((ObjectType *)&cr,*(int *)Value);
- local_3c[0].ObjectID = (pTVar4->CrObject).ObjectID;
- GetMapContainer(&local_4c);
- Create((Object *)CreatureID,(ObjectType *)&local_4c,(ulong)&cr);
- return (Object)CreatureID;
- }
- local_61 = false;
- iVar6 = 0;
- }
- }
- this = local_3c;
- // try { // try from 0809808f to 08098131 has its CatchHandler @ 08098210
- ObjectType::setTypeID((ObjectType *)this,*(int *)Value);
- Type_00 = local_2c;
- local_2c[0].ObjectID = local_4c.ObjectID;
-LAB_080980b2:
- Create((Object *)CreatureID,(ObjectType *)Type_00,(ulong)this);
- return (Object)CreatureID;
-}
-
-
-
-void DeleteAtCreature(ulong CreatureID,ObjectType *Type,int Amount,ulong Data)
-
-{
- bool bVar1;
- ulong uVar2;
- undefined4 *puVar3;
- Object *pOVar4;
- ulong uVar5;
- Object local_3c [4];
- Object local_2c;
- Object Obj;
-
- if (0 < Amount) {
- do {
- // try { // try from 0809827c to 080983d5 has its CatchHandler @ 080983d6
- ObjectType::setTypeID((ObjectType *)local_3c,Type->TypeID);
- uVar2 = CreatureID;
- pOVar4 = local_3c;
- uVar5 = Data;
- GetInventoryObject((ulong)&local_2c,(ObjectType *)CreatureID,(ulong)local_3c);
- local_3c[0].ObjectID = NONE.ObjectID;
- if (local_2c.ObjectID == NONE.ObjectID) {
- error("DeleteAtCreature: Kein Objekt gefunden.\n",uVar2,pOVar4,uVar5);
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0xffffffff;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
- }
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE);
- if ((bVar1) && (uVar2 = Object::getAttribute(&local_2c,AMOUNT), (int)uVar2 <= Amount)) {
- uVar2 = Object::getAttribute(&local_2c,AMOUNT);
- Amount = Amount - uVar2;
- local_3c[0].ObjectID = local_2c.ObjectID;
- Delete(local_3c,-1);
- }
- else {
- Object::getObjectType(local_3c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE);
- if (bVar1) {
- local_3c[0].ObjectID = local_2c.ObjectID;
- uVar2 = Object::getAttribute(&local_2c,AMOUNT);
- Change(local_3c,AMOUNT,uVar2 - Amount);
- Amount = 0;
- }
- else {
- local_3c[0].ObjectID = local_2c.ObjectID;
- Delete(local_3c,-1);
- Amount = Amount + -1;
- }
- }
- } while (0 < Amount);
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ProcessCronSystem(void)
-
-{
- bool bVar1;
- RESULT r_1;
- ulong uVar2;
- RESULT r;
- Object local_5c [4];
- Object local_4c [4];
- ObjectType local_3c;
- ObjectType Dest;
- ulong local_2c;
- Object Obj;
-
- while( true ) {
- CronCheck();
- local_3c.TypeID = NONE.ObjectID;
- if (local_2c == NONE.ObjectID) break;
- // try { // try from 08098422 to 080984f7 has its CatchHandler @ 08098508
- Object::getObjectType(local_4c);
- uVar2 = ObjectType::getAttribute((ObjectType *)local_4c,EXPIRETARGET);
- ObjectType::setTypeID(&local_3c,uVar2);
- Object::getObjectType(local_4c);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CONTAINER);
- if (bVar1) {
- ObjectType::setTypeID((ObjectType *)local_4c,0);
- if ((local_3c.TypeID == local_4c[0].ObjectID) ||
- (bVar1 = ObjectType::getFlag(&local_3c,CONTAINER), !bVar1)) {
- uVar2 = 0;
- }
- else {
- uVar2 = ObjectType::getAttribute(&local_3c,CAPACITY);
- }
- Empty(local_5c,uVar2);
- }
- ObjectType::setTypeID((ObjectType *)local_5c,local_3c.TypeID);
- local_4c[0].ObjectID = local_2c;
- Change(local_4c,(ObjectType *)local_5c,0);
- }
- return;
-}
-
-
-
-bool SectorRefreshable(int SectorX,int SectorY,int SectorZ)
-
-{
- int iVar1;
- ulong id;
- TCreature *pTVar2;
- undefined1 local_3c [4];
- TFindCreatures SearchPlayers;
-
- TFindCreatures::TFindCreatures
- ((TFindCreatures *)local_3c,0x1f,0x1f,SectorX * 0x20 + 0x10,SectorY * 0x20 + 0x10,1);
-LAB_08098600:
- do {
- while( true ) {
- id = TFindCreatures::getNext((TFindCreatures *)local_3c);
- if (id == 0) {
- return true;
- }
- pTVar2 = GetCreature(id);
- if (pTVar2 != (TCreature *)0x0) break;
- error("SectorRefreshable: Kreatur existiert nicht.\n");
- }
- iVar1 = pTVar2->posz;
- if (iVar1 < 8) {
- if (SectorZ < 8) {
- return false;
- }
- if (iVar1 < 8) goto LAB_08098600;
- }
- if ((SectorZ - iVar1) + 2U < 5) {
- return false;
- }
- } while( true );
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void RefreshSector(void)
-
-{
- bool bVar1;
- bool bVar2;
- ulong id;
- TCreature *pTVar3;
- TCreature *cr;
- int in_stack_00000004;
- int in_stack_00000008;
- int in_stack_0000000c;
- uchar *in_stack_00000010;
- int in_stack_00000014;
- Object *Obj_00;
- Object *Con;
- int x_00;
- int iVar4;
- int y_00;
- Object *Ignore;
- Object *pOStack_a8;
- bool PositionOk;
- int x;
- int y;
- int z;
- Object local_8c [4];
- Object local_7c [4];
- Object local_6c;
- Object Obj;
- undefined1 local_5c [4];
- TFindCreatures SearchMonsters;
- undefined1 local_2c [4];
- TReadBuffer Buffer;
-
- bVar1 = SectorRefreshable(in_stack_00000004,in_stack_00000008,in_stack_0000000c);
- if (bVar1) {
- TReadBuffer::TReadBuffer((TReadBuffer *)local_2c,in_stack_00000010,in_stack_00000014);
- RefreshSector(in_stack_00000004,in_stack_00000008,in_stack_0000000c,(TReadStream *)local_2c)
- ;
- x_00 = in_stack_00000004 * 0x20 + 0x10;
- y_00 = in_stack_00000008 * 0x20 + 0x10;
- Con = (Object *)0x10;
- Obj_00 = (Object *)0x10;
- TFindCreatures::TFindCreatures((TFindCreatures *)local_5c,0x10,0x10,x_00,y_00,7);
-LAB_08098700:
- id = TFindCreatures::getNext((TFindCreatures *)local_5c);
- if (id != 0) {
- pTVar3 = GetCreature(id);
- if (pTVar3 == (TCreature *)0x0) {
- error("RefreshSector: Kreatur existiert nicht.\n",Obj_00,Con,x_00,y_00);
- }
- else {
- iVar4 = pTVar3->posz;
- if (iVar4 == in_stack_0000000c) {
- bVar1 = true;
- Obj_00 = (Object *)pTVar3->posx;
- Con = (Object *)pTVar3->posy;
- pOStack_a8 = Obj_00;
- x = (int)Con;
- y = iVar4;
- GetFirstObject();
- x_00 = iVar4;
- if (local_6c.ObjectID != NONE.ObjectID) {
- do {
- local_8c[0].ObjectID = NONE.ObjectID;
- local_7c[0].ObjectID = NONE.ObjectID;
- Object::getObjectType(local_8c);
- x_00 = iVar4;
- if (local_8c[0].ObjectID != 99) {
- Object::getObjectType(local_8c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_8c,UNPASS);
- x_00 = iVar4;
- if (bVar2) {
- bVar1 = false;
- }
- }
- Obj_00 = &local_6c;
- Object::getNextObject(local_7c);
- local_6c.ObjectID = local_7c[0].ObjectID;
- iVar4 = x_00;
- } while (local_7c[0].ObjectID != NONE.ObjectID);
- }
- local_8c[0].ObjectID = NONE.ObjectID;
- local_7c[0].ObjectID = NONE.ObjectID;
- if (!bVar1) {
- y_00 = 0;
- // try { // try from 0809881e to 08098994 has its CatchHandler @ 08098a14
- bVar1 = SearchFreeField((int *)&stack0xffffff58,&x,&y,1,0,false);
- if (bVar1) {
- local_8c[0].ObjectID = NONE.ObjectID;
- GetMapContainer((int)local_7c,(int)pOStack_a8,x);
- z = (pTVar3->CrObject).ObjectID;
- Ignore = local_8c;
- Obj_00 = (Object *)&z;
- Con = local_7c;
- }
- else {
- if (pTVar3->Type != NPC) {
- if (pTVar3->Type == MONSTER) {
- Obj_00 = (Object *)&DAT_08100600;
- Con = pOStack_a8;
- x_00 = x;
- y_00 = y;
- print();
- if (pTVar3 != (TCreature *)0x0) {
- (*pTVar3->_vptr_TCreature[1])(pTVar3);
- }
- }
- else {
- Obj_00 = pOStack_a8;
- Con = (Object *)x;
- x_00 = y;
- error("Spieler auf [%d,%d,%d] ist von Refresh betroffen.\n",
- pOStack_a8,x,y);
- }
- goto LAB_08098700;
- }
- print();
- Ignore = (Object *)&z;
- z = NONE.ObjectID;
- GetMapContainer((int)local_8c,pTVar3->startx,pTVar3->starty);
- local_7c[0].ObjectID = (pTVar3->CrObject).ObjectID;
- Obj_00 = local_7c;
- Con = local_8c;
- }
- y_00 = 0;
- x_00 = -1;
- Move(0,Obj_00,Con,-1,false,Ignore);
- }
- }
- }
- goto LAB_08098700;
- }
- }
- return;
-}
-
-
-
-// WARNING: Removing unreachable block (ram,0x08098d29)
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void RefreshMap(void)
-
-{
- byte b;
- bool bVar1;
- char cVar2;
- int DataSize;
- int iVar3;
- byte *pbVar4;
- int iVar5;
- int iVar6;
- int y;
- TWriteStream *SectorY;
- char *pcVar7;
- undefined1 uVar8;
- TWriteStream *__in_chrg;
- char *Stream;
- char *pcVar9;
- int local_5040;
- int z;
- byte local_5029;
- bool Refreshable;
- int yy;
- int xx;
- int x;
- TReadBuffer ReadBuffer;
- TReadScriptFile Script;
- TWriteStream local_102c;
- char FileName [4096];
- TDynamicWriteBuffer HelpBuffer;
-
- __in_chrg = (TWriteStream *)0x10000;
- TDynamicWriteBuffer::TDynamicWriteBuffer((TDynamicWriteBuffer *)(FileName + 0xffc),0x10000);
- xx = SectorXMin;
- iVar5 = SectorXMax;
- iVar6 = SectorYMax;
- if (SectorXMin <= SectorXMax) {
- do {
- iVar3 = SectorZMax;
- SectorY = (TWriteStream *)SectorYMin;
- if (SectorYMin <= iVar6) {
- do {
- local_5040 = SectorZMin;
- if (SectorZMin <= iVar3) {
- do {
- __in_chrg = SectorY;
- // try { // try from 08098afd to 08098b58 has its CatchHandler @ 08098dd0
- bVar1 = SectorRefreshable(xx,(int)SectorY,local_5040);
- if (bVar1) {
- Stream = (char *)&local_102c;
- pcVar9 = ORIGMAPPATH;
- __in_chrg = (TWriteStream *)&DAT_080f2af5;
- sprintf(Stream,"%s/%04u-%04u-%02u.sec",ORIGMAPPATH,xx,SectorY,
- local_5040);
- bVar1 = FileExists(Stream);
- if (bVar1) {
- // try { // try from 08098b66 to 08098b6a has its CatchHandler @ 08098db6
- TReadScriptFile::TReadScriptFile
- ((TReadScriptFile *)&ReadBuffer.Position);
- // try { // try from 08098b78 to 08098d61 has its CatchHandler @ 08098d75
- TReadScriptFile::open
- ((TReadScriptFile *)&ReadBuffer.Position,Stream,
- (int)pcVar9);
- local_5029 = 0;
- yy = -1;
- b = 0xff;
- while (TReadScriptFile::nextToken
- ((TReadScriptFile *)&ReadBuffer.Position),
- ReadBuffer.Position != 0) {
- if ((ReadBuffer.Position != 6) ||
- (cVar2 = TReadScriptFile::getSpecial
- ((TReadScriptFile *)
- &ReadBuffer.Position), cVar2 != ','))
- {
- if (ReadBuffer.Position == 4) {
- pbVar4 = TReadScriptFile::getBytesequence
- ((TReadScriptFile *)
- &ReadBuffer.Position);
- yy = (int)*pbVar4;
- b = pbVar4[1];
- Stream = (char *)0x3a;
- TReadScriptFile::readSymbol
- ((TReadScriptFile *)&ReadBuffer.Position,
- ':');
- local_5029 = 0;
- }
- else if (ReadBuffer.Position == 1) {
- uVar8 = yy == -1;
- if ((bool)uVar8) {
- Stream = "coordinate expected";
- TReadScriptFile::error
- ((TReadScriptFile *)
- &ReadBuffer.Position,
- "coordinate expected");
- }
- pcVar9 = TReadScriptFile::getIdentifier
- ((TReadScriptFile *)
- &ReadBuffer.Position);
- iVar5 = 8;
- pcVar7 = "refresh";
- do {
- if (iVar5 == 0) break;
- iVar5 = iVar5 + -1;
- uVar8 = *pcVar9 == *pcVar7;
- pcVar9 = pcVar9 + 1;
- pcVar7 = pcVar7 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- local_5029 = 1;
- }
- pcVar9 = TReadScriptFile::getIdentifier
- ((TReadScriptFile *)
- &ReadBuffer.Position);
- iVar5 = 8;
- pcVar7 = "content";
- do {
- if (iVar5 == 0) break;
- iVar5 = iVar5 + -1;
- uVar8 = *pcVar9 == *pcVar7;
- pcVar9 = pcVar9 + 1;
- pcVar7 = pcVar7 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- TReadScriptFile::readSymbol
- ((TReadScriptFile *)
- &ReadBuffer.Position,'=');
- if (local_5029 != 0) {
- TDynamicWriteBuffer::writeByte
- ((TDynamicWriteBuffer *)
- (FileName + 0xffc),(uchar)yy);
- TDynamicWriteBuffer::writeByte
- ((TDynamicWriteBuffer *)
- (FileName + 0xffc),b);
- }
- Stream = FileName + 0xffc;
- LoadObjects((TReadScriptFile *)
- &ReadBuffer.Position,
- (TWriteStream *)Stream,
- (bool)(local_5029 ^ 1));
- }
- }
- }
- }
- TReadScriptFile::close
- ((TReadScriptFile *)&ReadBuffer.Position,(int)Stream);
- // try { // try from 08098d6b to 08098d6f has its CatchHandler @ 08098db6
- TReadScriptFile::~TReadScriptFile
- ((TReadScriptFile *)&ReadBuffer.Position,(int)Stream);
- __in_chrg = (TWriteStream *)Stream;
- }
- }
- local_5040 = local_5040 + 1;
- iVar3 = SectorZMax;
- iVar6 = SectorYMax;
- } while (local_5040 <= SectorZMax);
- }
- SectorY = (TWriteStream *)((int)&SectorY->_vptr_TWriteStream + 1);
- iVar5 = SectorXMax;
- } while ((int)SectorY <= iVar6);
- }
- xx = xx + 1;
- } while (xx <= iVar5);
- }
- TDynamicWriteBuffer::~TDynamicWriteBuffer
- ((TDynamicWriteBuffer *)(FileName + 0xffc),(int)__in_chrg);
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void RefreshCylinders(void)
-
-{
- bool bVar1;
- int iVar2;
- int iVar3;
- int z;
- int iVar4;
- int i;
- int iVar5;
-
- if (0 < RefreshedCylinders) {
- iVar5 = 0;
- iVar2 = RefreshedCylinders;
- iVar3 = SectorZMax;
- do {
- if (RefreshCylinders::RefreshX < SectorXMax) {
- RefreshCylinders::RefreshX = RefreshCylinders::RefreshX + 1;
- iVar4 = RefreshCylinders::RefreshY;
- }
- else {
- RefreshCylinders::RefreshX = SectorXMin;
- iVar4 = SectorYMin;
- if (RefreshCylinders::RefreshY < SectorYMax) {
- iVar4 = RefreshCylinders::RefreshY + 1;
- }
- }
- RefreshCylinders::RefreshY = iVar4;
- iVar4 = SectorZMin;
- if (SectorZMin <= iVar3) {
- do {
- bVar1 = SectorRefreshable(RefreshCylinders::RefreshX,RefreshCylinders::RefreshY,
- iVar4);
- if (bVar1) {
- LoadSectorOrder(RefreshCylinders::RefreshX,RefreshCylinders::RefreshY,iVar4)
- ;
- }
- iVar4 = iVar4 + 1;
- iVar2 = RefreshedCylinders;
- iVar3 = SectorZMax;
- } while (iVar4 <= SectorZMax);
- }
- iVar5 = iVar5 + 1;
- } while (iVar5 < iVar2);
- }
- return;
-}
-
-
-
-void ApplyPatch(int SectorX,int SectorY,int SectorZ,bool FullSector,TReadScriptFile *Script,
- bool SaveHouses)
-
-{
- bool bVar1;
- bool bVar2;
- ulong id;
- TCreature *this;
- Object *Con;
- Object *Con_00;
- int x_00;
- Object *Ignore;
- bool PositionOk;
- bool SaveHouses_local;
- Object *pOStack_98;
- bool FullSector_local;
- int x;
- int y;
- int z;
- Object local_7c [4];
- Object local_6c [4];
- ulong local_5c;
- Object Obj;
- undefined1 local_4c [4];
- TFindCreatures SearchMonsters;
-
- bVar1 = false;
- if ((SectorXMin <= SectorX) && (SectorX <= SectorXMax)) {
- bVar1 = true;
- }
- if (bVar1) {
- bVar1 = false;
- if ((SectorYMin <= SectorY) && (SectorY <= SectorYMax)) {
- bVar1 = true;
- }
- if (bVar1) {
- bVar1 = false;
- if ((SectorZMin <= SectorZ) && (SectorZ <= SectorZMax)) {
- bVar1 = true;
- }
- if (bVar1) {
- // try { // try from 08098f53 to 08099069 has its CatchHandler @ 08099366
- PrepareHouseCleanup();
- PatchSector(SectorX,SectorY,SectorZ,FullSector,Script,SaveHouses);
- FinishHouseCleanup();
- Con_00 = (Object *)0x10;
- x_00 = SectorX * 0x20 + 0x10;
- Con = (Object *)0x10;
- TFindCreatures::TFindCreatures
- ((TFindCreatures *)local_4c,0x10,0x10,x_00,SectorY * 0x20 + 0x10,7);
-LAB_08098fc1:
- id = TFindCreatures::getNext((TFindCreatures *)local_4c);
- if (id != 0) {
- this = GetCreature(id);
- if (this == (TCreature *)0x0) {
- error("ApplyPatch: Kreatur existiert nicht.\n",Con,Con_00,x_00);
- }
- else if (this->posz == SectorZ) {
- bVar1 = true;
- pOStack_98 = (Object *)this->posx;
- x = this->posy;
- y = this->posz;
- GetFirstObject();
- if (local_5c != NONE.ObjectID) {
- do {
- local_7c[0].ObjectID = NONE.ObjectID;
- local_6c[0].ObjectID = NONE.ObjectID;
- Object::getObjectType(local_7c);
- if (local_7c[0].ObjectID != 99) {
- Object::getObjectType(local_7c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_7c,UNPASS);
- if (bVar2) {
- bVar1 = false;
- }
- }
- Object::getNextObject(local_6c);
- local_5c = local_6c[0].ObjectID;
- } while (local_6c[0].ObjectID != NONE.ObjectID);
- }
- local_6c[0].ObjectID = NONE.ObjectID;
- if (bVar1) {
- local_7c[0].ObjectID = (this->CrObject).ObjectID;
- Con = local_6c;
- Con_00 = (Object *)x;
- x_00 = y;
- // try { // try from 080992bc to 0809931c has its CatchHandler @ 08099366
- GetMapContainer((int)Con,(int)pOStack_98,x);
- MoveObject(local_7c,Con);
- }
- else {
- local_7c[0].ObjectID = NONE.ObjectID;
- // try { // try from 080990c4 to 0809926a has its CatchHandler @ 08099322
- bVar1 = SearchFreeField((int *)&stack0xffffff68,&x,&y,1,0,false);
- if (bVar1) {
- Con = local_6c;
- local_7c[0].ObjectID = NONE.ObjectID;
- local_6c[0].ObjectID = (this->CrObject).ObjectID;
- Con_00 = (Object *)&z;
- GetMapContainer((int)Con_00,(int)pOStack_98,x);
- Ignore = local_7c;
- }
- else {
- if (this->Type != NPC) {
- if (this->Type == MONSTER) {
- x_00 = x;
- print();
- z = (this->CrObject).ObjectID;
- Delete((Object *)&z,-1);
- Con_00 = (Object *)0x0;
- Con = (Object *)0x0;
- TCreature::StartLogout(this,false,false);
- }
- else {
- Con = pOStack_98;
- Con_00 = (Object *)x;
- x_00 = y;
- error("Spieler auf [%d,%d,%d] ist von Patch betroffen.\n",
- pOStack_98,x,y);
- }
- goto LAB_08098fc1;
- }
- print();
- Con_00 = local_6c;
- z = NONE.ObjectID;
- local_7c[0].ObjectID = (this->CrObject).ObjectID;
- GetMapContainer((int)Con_00,this->startx,this->starty);
- Ignore = (Object *)&z;
- Con = local_7c;
- }
- x_00 = -1;
- Move(0,Con,Con_00,-1,false,Ignore);
- }
- }
- goto LAB_08098fc1;
- }
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ApplyPatches(void)
-
-{
- bool bVar1;
- DIR *__dirp;
- dirent *pdVar2;
- size_t sVar3;
- int iVar4;
- int iVar5;
- dirent *DirEntry;
- char *pcVar6;
- undefined1 uVar7;
- char *pcVar8;
- char *pcVar9;
- int local_5018;
- int MaxPatch;
- DIR *WorkDir;
- int iStack_500c;
- bool SaveHouses;
- int x;
- int y;
- int z;
- int nr;
- TReadScriptFile Script;
- char local_101c [4];
- char FileName [4096];
-
- sprintf(local_101c,"%s/save-houses",SAVEPATH);
- // try { // try from 080993ba to 08099525 has its CatchHandler @ 0809979b
- bVar1 = FileExists(local_101c);
- if (bVar1) {
- print();
- unlink(local_101c);
- }
- __dirp = opendir(SAVEPATH);
- if (__dirp == (DIR *)0x0) {
- // try { // try from 08099746 to 08099763 has its CatchHandler @ 0809979b
- error("ApplyPatches: Unterverzeichnis %s nicht gefunden.\n",SAVEPATH);
- }
- else {
- local_5018 = -1;
-LAB_080993f0:
- pdVar2 = readdir(__dirp);
- if (pdVar2 != (dirent *)0x0) {
- pcVar9 = pdVar2->d_name;
- sVar3 = strlen(pcVar9);
- uVar7 = sVar3 == 4;
- if (4 < sVar3) {
- iVar5 = 5;
- pcVar8 = pdVar2->d_name + (sVar3 - 4);
- pcVar6 = ".pat";
- do {
- if (iVar5 == 0) break;
- iVar5 = iVar5 + -1;
- uVar7 = *pcVar8 == *pcVar6;
- pcVar8 = pcVar8 + 1;
- pcVar6 = pcVar6 + 1;
- } while ((bool)uVar7);
- if ((bool)uVar7) {
- iVar5 = sscanf(pcVar9,"%d.pat",&z);
- uVar7 = iVar5 == 1;
- if ((bool)uVar7) {
- if (local_5018 < z) {
- local_5018 = z;
- }
- goto LAB_080993f0;
- }
- }
- sVar3 = strlen(pcVar9);
- iVar5 = 5;
- pcVar8 = pdVar2->d_name + (sVar3 - 4);
- pcVar6 = ".sec";
- do {
- if (iVar5 == 0) break;
- iVar5 = iVar5 + -1;
- uVar7 = *pcVar8 == *pcVar6;
- pcVar8 = pcVar8 + 1;
- pcVar6 = pcVar6 + 1;
- } while ((bool)uVar7);
- if (((bool)uVar7) &&
- (iVar5 = sscanf(pcVar9,"%d-%d-%d.sec",&stack0xffffaff4,&x,&y), iVar5 == 3)) {
- iVar5 = y;
- print();
- pcVar8 = SAVEPATH;
- sprintf(local_101c,"%s/%s",SAVEPATH,pcVar9,iVar5);
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)&nr);
- // try { // try from 08099533 to 08099578 has its CatchHandler @ 08099778
- TReadScriptFile::open((TReadScriptFile *)&nr,local_101c,(int)pcVar8);
- iVar5 = x;
- ApplyPatch(iStack_500c,x,y,true,(TReadScriptFile *)&nr,bVar1);
- TReadScriptFile::close((TReadScriptFile *)&nr,iVar5);
- unlink(local_101c);
- // try { // try from 0809958a to 0809961a has its CatchHandler @ 0809979b
- TReadScriptFile::~TReadScriptFile((TReadScriptFile *)&nr,iVar5);
- }
- }
- goto LAB_080993f0;
- }
- iVar5 = 0;
- closedir(__dirp);
- if (-1 < local_5018) {
- do {
- pcVar9 = SAVEPATH;
- sprintf(local_101c,"%s/%03d.pat",SAVEPATH,iVar5);
- bVar1 = FileExists(local_101c);
- if (bVar1) {
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)&nr);
- // try { // try from 08099622 to 08099706 has its CatchHandler @ 08099778
- TReadScriptFile::open((TReadScriptFile *)&nr,local_101c,(int)pcVar9);
- pcVar9 = TReadScriptFile::readIdentifier((TReadScriptFile *)&nr);
- iVar4 = stricmp(pcVar9,"sector",-1);
- if (iVar4 != 0) {
- // try { // try from 0809972d to 08099731 has its CatchHandler @ 08099778
- TReadScriptFile::error((TReadScriptFile *)&nr,"Sector expected");
- }
- iStack_500c = TReadScriptFile::readNumber((TReadScriptFile *)&nr);
- TReadScriptFile::readSymbol((TReadScriptFile *)&nr,',');
- x = TReadScriptFile::readNumber((TReadScriptFile *)&nr);
- TReadScriptFile::readSymbol((TReadScriptFile *)&nr,',');
- y = TReadScriptFile::readNumber((TReadScriptFile *)&nr);
- print();
- iVar4 = x;
- ApplyPatch(iStack_500c,x,y,false,(TReadScriptFile *)&nr,false);
- TReadScriptFile::close((TReadScriptFile *)&nr,iVar4);
- unlink(local_101c);
- // try { // try from 08099718 to 0809971c has its CatchHandler @ 0809979b
- TReadScriptFile::~TReadScriptFile((TReadScriptFile *)&nr,iVar4);
- }
- iVar5 = iVar5 + 1;
- } while (iVar5 <= local_5018);
- }
- }
- return;
-}
-
-
-
// WARNING: Unknown calling convention -- yet parameter storage is locked
int GetNumberOfChannels(void)
@@ -20532,643 +19182,6 @@ void LeaveAllChannels(ulong CharacterID)
return;
}
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-ulong LogCommunication(void)
-
-{
- TStatement *pTVar1;
- ulong uVar2;
- TStatement *Statement;
- ulong in_stack_00000004;
- int in_stack_00000008;
- int in_stack_0000000c;
- char *in_stack_00000010;
- char *Text;
-
- if (in_stack_00000010 == (char *)0x0) {
- Text = "LogCommunication: Text ist NULL.\n";
- }
- else {
- if (in_stack_00000004 != 0) {
- StatementID = StatementID + 1;
- pTVar1 = fifo<TStatement>::append(&Statements);
- pTVar1->StatementID = StatementID;
- uVar2 = time((time_t *)0x0);
- pTVar1->TimeStamp = uVar2;
- pTVar1->CharacterID = in_stack_00000004;
- pTVar1->Mode = in_stack_00000008;
- pTVar1->Channel = in_stack_0000000c;
- uVar2 = AddDynamicString(in_stack_00000010);
- pTVar1->Reported = false;
- pTVar1->Text = uVar2;
- return StatementID;
- }
- Text = "LogCommunication: CharacterID ist Null.\n";
- }
- error(Text);
- return 0;
-}
-
-
-
-ulong LogListener(ulong StatementID,TPlayer *pl)
-
-{
- bool bVar1;
- TListener *Listener;
- TListener *pTVar2;
- ulong uVar3;
-
- uVar3 = 0;
- if ((StatementID != 0) && (uVar3 = 0, pl != (TPlayer *)0x0)) {
- bVar1 = CheckRight((pl->super_TCreature).ID,LOG_COMMUNICATION);
- uVar3 = 0;
- if (bVar1) {
- pTVar2 = fifo<TListener>::append(&Listeners);
- pTVar2->StatementID = StatementID;
- pTVar2->CharacterID = (pl->super_TCreature).ID;
- uVar3 = StatementID;
- }
- }
- return uVar3;
-}
-
-
-
-// WARNING: Restarted to delay deadcode elimination for space: ram
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ProcessCommunicationControl(void)
-
-{
- time_t tVar1;
- TListener *pTVar2;
- TStatement *pTVar3;
- uint local_3c;
- ulong Limit;
-
- tVar1 = time((time_t *)0x0);
- while( true ) {
- if (Statements.Head < Statements.Tail) {
- pTVar3 = (TStatement *)0x0;
- }
- else {
- pTVar3 = Statements.Entry + Statements.Tail % Statements.Size;
- }
- if ((pTVar3 == (TStatement *)0x0) || (tVar1 - 0x708U <= pTVar3->TimeStamp)) break;
- DeleteDynamicString(pTVar3->Text);
- if (Statements.Head < Statements.Tail) {
- error("fifo::remove: Fifo ist leer.\n");
- }
- else {
- Statements.Tail = Statements.Tail + 1;
- }
- }
- if (Statements.Head < Statements.Tail) {
- pTVar3 = (TStatement *)0x0;
- }
- else {
- pTVar3 = Statements.Entry + Statements.Tail % Statements.Size;
- }
- if (pTVar3 == (TStatement *)0x0) {
- local_3c = 0;
- }
- else {
- if (Statements.Head < Statements.Tail) {
- pTVar3 = (TStatement *)0x0;
- }
- else {
- pTVar3 = Statements.Entry + Statements.Tail % Statements.Size;
- }
- local_3c = pTVar3->StatementID;
- }
- while( true ) {
- if (Listeners.Head < Listeners.Tail) {
- pTVar2 = (TListener *)0x0;
- }
- else {
- pTVar2 = Listeners.Entry + Listeners.Tail % Listeners.Size;
- }
- if ((pTVar2 == (TListener *)0x0) || (local_3c <= pTVar2->StatementID)) break;
- if (Listeners.Head < Listeners.Tail) {
- error("fifo::remove: Fifo ist leer.\n");
- }
- else {
- Listeners.Tail = Listeners.Tail + 1;
- }
- }
- return;
-}
-
-
-
-int GetCommunicationContext
- (ulong CharacterID,ulong StatementID,int *NumberOfStatements,
- vector<> **ReportedStatements)
-
-{
- int iVar1;
- bool bVar2;
- vector<> *pvVar3;
- TReportedStatement *pTVar4;
- TStatement *pTVar5;
- char *pcVar6;
- char *pcVar7;
- uint uVar8;
- uint uVar9;
- int i;
- fifo<TStatement> *pfVar10;
- char *pcVar11;
- TListener *pTVar12;
- int *piVar13;
- bool bVar14;
- char *pcVar15;
- char *local_40;
- int FreeSpace;
- TStatement *pTStack_38;
- bool StatementContained;
- fifoIterator<TListener> iter2;
- int local_20;
- fifo<TStatement> *local_1c;
- fifoIterator<TStatement> iter;
-
- local_1c = &Statements;
- iter.Fifo = (fifo<TStatement> *)Statements.Head;
- while( true ) {
- bVar2 = false;
- if ((Statements.Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= Statements.Head)) {
- bVar2 = true;
- }
- if (bVar2) {
- pTVar5 = Statements.Entry + (int)iter.Fifo % Statements.Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5 == (TStatement *)0x0) break;
- bVar2 = false;
- if ((Statements.Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= Statements.Head)) {
- bVar2 = true;
- }
- if (bVar2) {
- pTVar5 = Statements.Entry + (int)iter.Fifo % Statements.Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->StatementID == StatementID) break;
- iter.Fifo = (fifo<TStatement> *)((int)&iter.Fifo[-1].Tail + 3);
- }
- bVar2 = false;
- if ((Statements.Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= Statements.Head)) {
- bVar2 = true;
- }
- if (bVar2) {
- pTStack_38 = Statements.Entry + (int)iter.Fifo % Statements.Size;
- }
- else {
- pTStack_38 = (TStatement *)0x0;
- }
- if (pTStack_38 == (TStatement *)0x0) {
- return 1;
- }
- if (CharacterID != 0) {
-LAB_0809ac90:
- if (pTStack_38->Reported != false) {
- return 2;
- }
- bVar2 = false;
- *NumberOfStatements = 0;
- local_20 = 0x4000;
- iter2.Position = MaxPlayers * 0x42 + 2;
- piVar13 = &iter2.Position;
- if (iter2.Position < 0x4001) {
- piVar13 = &local_20;
- }
- local_40 = (char *)(*piVar13 + -0x11f);
- pvVar3 = (vector<> *)operator_new(0x130);
- pcVar15 = (char *)0x0;
- // try { // try from 0809ad0a to 0809ad0e has its CatchHandler @ 0809b61f
- vector<>::vector(pvVar3,0,100,100);
- *ReportedStatements = pvVar3;
- iter2.Fifo = (fifo<TListener> *)Listeners.Tail;
- local_1c = &Statements;
- pfVar10 = &Statements;
- iter.Fifo = (fifo<TStatement> *)Statements.Tail;
-LAB_0809ad41:
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5 == (TStatement *)0x0) goto LAB_0809b4bf;
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- uVar9 = pTStack_38->TimeStamp;
- if (((int)(uVar9 - 0xb4) <= (int)pTVar5->TimeStamp) &&
- ((int)pTVar5->TimeStamp <= (int)(uVar9 + 0x3c))) {
- bVar14 = true;
- }
- if (!bVar14) goto LAB_0809ae99;
- if ((int)local_40 < 1) {
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (uVar9 < pTVar5->TimeStamp) {
- error(&DAT_08100c20);
-LAB_0809b4bf:
- if ((int)local_40 < 0) {
- pcVar11 = (char *)0x0;
- pcVar15 = (char *)-(int)local_40;
- error(&DAT_08100ce0,pcVar15);
- if (*NumberOfStatements < 1) {
-LAB_0809b5c9:
- if ((int)local_40 < 0) {
- error("GetCommunicationContext: FreeSpace ist immer noch negativ (%d).\n"
- ,local_40);
- pcVar15 = local_40;
- }
- }
- else {
- do {
- pcVar15 = pcVar11;
- pTVar4 = vector<>::operator()(*ReportedStatements,(int)pcVar11);
- if (pTVar4->StatementID != StatementID) {
- pTVar4 = vector<>::operator()(*ReportedStatements,(int)pcVar11);
- pTVar4->StatementID = 0;
- pcVar15 = pcVar11;
- pTVar4 = vector<>::operator()(*ReportedStatements,(int)pcVar11);
- pcVar7 = pTVar4->Text;
- do {
- pcVar6 = pcVar7;
- uVar8 = *(uint *)pcVar6 + 0xfefefeff & ~*(uint *)pcVar6;
- uVar9 = uVar8 & 0x80808080;
- pcVar7 = pcVar6 + 4;
- } while (uVar9 == 0);
- bVar14 = (uVar8 & 0x8080) == 0;
- if (bVar14) {
- uVar9 = uVar9 >> 0x10;
- }
- if (bVar14) {
- pcVar7 = pcVar6 + 6;
- }
- local_40 = pcVar7 + (int)(local_40 +
- (-(int)pTVar4->Text -
- (uint)CARRY1((byte)uVar9,(byte)uVar9)) +
- 0x2b);
- }
- pcVar11 = pcVar11 + 1;
- if (*NumberOfStatements <= (int)pcVar11) goto LAB_0809b5c9;
- } while ((int)local_40 < 0);
- }
- }
- if (bVar2) {
- pTStack_38->Reported = true;
- return 0;
- }
- error("GetCommunicationContext: Statement ist nicht im Kontext enthalten.\n",pcVar15
- );
- pvVar3 = *ReportedStatements;
- if (pvVar3 == (vector<> *)0x0) {
- return 1;
- }
- if (pvVar3->entry != (TReportedStatement *)0x0) {
- operator_delete__(pvVar3->entry);
- }
- operator_delete(pvVar3);
- return 1;
- }
- }
- if (CharacterID != 0) {
- while( true ) {
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- if (pTVar12 == (TListener *)0x0) break;
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->StatementID <= pTVar12->StatementID) break;
- iter2.Fifo = (fifo<TListener> *)((int)&(iter2.Fifo)->Entry + 1);
- }
- do {
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- if (pTVar12 == (TListener *)0x0) goto LAB_0809b39a;
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar12->StatementID != pTVar5->StatementID) goto LAB_0809b39a;
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- if (pTVar12->CharacterID == CharacterID) goto LAB_0809b39a;
- iter2.Fifo = (fifo<TListener> *)((int)&(iter2.Fifo)->Entry + 1);
- } while( true );
- }
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && (bVar14 = true, pfVar10->Head < (int)iter.Fifo)) {
- bVar14 = false;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->Mode != 5) {
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->Mode != 10) {
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->Mode != 0xc) goto LAB_0809ae99;
- }
- }
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTStack_38->Channel != pTVar5->Channel) goto LAB_0809ae99;
- goto LAB_0809aedf;
- }
- iVar1 = pTStack_38->Mode;
- if (((iVar1 == 5) || (iVar1 == 10)) || (iVar1 == 0xc)) {
- bVar2 = false;
- iVar1 = pTStack_38->Channel;
- if ((3 < iVar1) && (iVar1 < 8)) {
- bVar2 = true;
- }
- if ((bVar2) || (iVar1 == 2)) goto LAB_0809ac90;
- }
- error(&DAT_08100bc0);
- return 1;
-LAB_0809b39a:
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- if (pTVar12 != (TListener *)0x0) {
- bVar14 = false;
- if ((Listeners.Tail <= (int)iter2.Fifo) && ((int)iter2.Fifo <= Listeners.Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar12 = Listeners.Entry + (int)iter2.Fifo % Listeners.Size;
- }
- else {
- pTVar12 = (TListener *)0x0;
- }
- bVar14 = false;
- if ((pfVar10->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= pfVar10->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = pfVar10->Entry + (int)iter.Fifo % pfVar10->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar12->StatementID <= pTVar5->StatementID) {
-LAB_0809aedf:
- bVar14 = false;
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- pTVar4->StatementID = pTVar5->StatementID;
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- pTVar4->TimeStamp = pTVar5->TimeStamp;
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- pTVar4->CharacterID = pTVar5->CharacterID;
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- pTVar4->Mode = pTVar5->Mode;
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- bVar14 = false;
- pTVar4->Channel = pTVar5->Channel;
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- if (pTVar5->Text == 0) {
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- pTVar4->Text[0] = '\0';
- }
- else {
- bVar14 = false;
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- pcVar15 = GetDynamicString(pTVar5->Text);
- pTVar4 = vector<>::operator()(*ReportedStatements,*NumberOfStatements);
- strcpy(pTVar4->Text,pcVar15);
- }
- pcVar15 = (char *)*NumberOfStatements;
- pTVar4 = vector<>::operator()(*ReportedStatements,(int)pcVar15);
- pcVar11 = pTVar4->Text;
- do {
- pcVar7 = pcVar11;
- uVar8 = *(uint *)pcVar7 + 0xfefefeff & ~*(uint *)pcVar7;
- uVar9 = uVar8 & 0x80808080;
- pcVar11 = pcVar7 + 4;
- } while (uVar9 == 0);
- if ((uVar8 & 0x8080) == 0) {
- pcVar11 = pcVar7 + 6;
- uVar9 = uVar9 >> 0x10;
- }
- bVar14 = false;
- local_40 = local_40 +
- (-0x2e - (int)(pcVar11 +
- ((-3 - (uint)CARRY1((byte)uVar9,(byte)uVar9)) -
- (int)pTVar4->Text)));
- *NumberOfStatements = *NumberOfStatements + 1;
- if ((local_1c->Tail <= (int)iter.Fifo) && ((int)iter.Fifo <= local_1c->Head)) {
- bVar14 = true;
- }
- if (bVar14) {
- pTVar5 = local_1c->Entry + (int)iter.Fifo % local_1c->Size;
- }
- else {
- pTVar5 = (TStatement *)0x0;
- }
- pfVar10 = local_1c;
- if (pTVar5->StatementID == StatementID) {
- bVar2 = true;
- }
- }
- }
-LAB_0809ae99:
- iter.Fifo = (fifo<TStatement> *)((int)&(iter.Fifo)->Entry + 1);
- goto LAB_0809ad41;
-}
-
-
-
TParty * GetParty(ulong Leader)
{
diff --git a/reference/types.hh b/reference/types.hh
index f3ce69d..5b900e6 100644
--- a/reference/types.hh
+++ b/reference/types.hh
@@ -89,20 +89,6 @@ struct TWaitinglistEntry {
bool Sleeping;
};
-struct TReportedStatement {
- ulong StatementID;
- ulong TimeStamp;
- ulong CharacterID;
- int Mode;
- int Channel;
- char Text[256];
-};
-
-struct TListener {
- ulong StatementID;
- ulong CharacterID;
-};
-
struct TDelayedMail {
ulong CharacterID;
int DepotNumber;
@@ -122,29 +108,12 @@ struct TMonsterhome {
int Timer;
};
-struct TChannel {
- ulong Moderator;
- char ModeratorName[30];
- struct vector<long_unsigned_int> Subscriber;
- int Subscribers;
- struct vector<long_unsigned_int> InvitedPlayer;
- int InvitedPlayers;
-};
-
struct THelpDepot {
ulong CharacterID;
struct Object Box;
int DepotNr;
};
-struct TParty {
- ulong Leader;
- struct vector<long_unsigned_int> Member;
- int Members;
- struct vector<long_unsigned_int> InvitedPlayer;
- int InvitedPlayers;
-};
-
struct TMoveUseAction {
enum ActionType Action;
int Parameters[5];
@@ -169,16 +138,6 @@ struct THouseArea {
int DepotNr;
};
-struct TStatement {
- ulong StatementID;
- ulong TimeStamp;
- ulong CharacterID;
- int Mode;
- int Channel;
- ulong Text;
- bool Reported;
-};
-
struct TDirectReplyData {
ulong CharacterID;
char Message[100];
diff --git a/src/connection.hh b/src/connection.hh
index ec79a6e..44b7360 100644
--- a/src/connection.hh
+++ b/src/connection.hh
@@ -5,6 +5,7 @@
#include "enums.hh"
struct TConnection;
+struct TPlayer;
struct TKnownCreature {
KNOWNCREATURESTATE State;
@@ -14,6 +15,7 @@ struct TKnownCreature {
};
struct TConnection {
+ TPlayer *GetPlayer(void);
void Logout(int Delay, bool StopFight);
bool IsVisible(int x, int y, int z);
diff --git a/src/containers.hh b/src/containers.hh
index 85dcfde..f82159b 100644
--- a/src/containers.hh
+++ b/src/containers.hh
@@ -118,6 +118,14 @@ struct vector{
return &this->entry[index - this->start];
}
+ T copyAt(int index) const {
+ T Result = {};
+ if(index >= this->start && index < (this->start + this->space)){
+ Result = this->entry[index - this->start];
+ }
+ return Result;
+ }
+
// DATA
// =================
int min;
@@ -466,7 +474,7 @@ struct fifo{
// TODO(fusion): We don't consider integer overflow at all.
this->Head += 1;
- return this->Entry[this->Head % this->Size];
+ return &this->Entry[this->Head % this->Size];
}
void remove(void){
@@ -478,6 +486,33 @@ struct fifo{
this->Tail += 1;
}
+ int iterFirst(void){
+ return this->Head;
+ }
+
+ int iterLast(void){
+ return this->Tail;
+ }
+
+ T *iterNext(int *Position){
+ if(*Position < this->Tail || this->Head < *Position){
+ return NULL;
+ }
+ T *Result = &this->Entry[*Position % this->Size];
+ *Position -= 1;
+ return Result;
+ }
+
+ T *iterPrev(int *Position){
+ if(*Position < this->Tail || this->Head < *Position){
+ return NULL;
+ }
+
+ T *Result = &this->Entry[*Position % this->Size];
+ *Position += 1;
+ return Result;
+ }
+
// TODO(fusion): There is also a `fifoIterator` used a few times and it is
// essentially iterating from `this->Head` towards `this->Tail`. All its
// functions were inlined so I'm not sure it is needed.
diff --git a/src/cr.hh b/src/cr.hh
index a2206f4..32d0090 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -718,6 +718,9 @@ struct TPlayer: TCreature {
void SetOpenContainer(int ContainerNr, Object Con);
void RejectTrade(void);
Object InspectTrade(bool OwnOffer, int Position);
+ int CheckForMuting(void);
+ int RecordTalk(void);
+ int RecordMessage(uint32 Addressee);
// VIRTUAL FUNCTIONS
// =================
diff --git a/src/crmain.cc b/src/crmain.cc
index 7e0ab42..c6a8b74 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -719,9 +719,13 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){
GraphicalEffect(this->CrObject, HitEffect);
TextualEffect(this->CrObject, TextColor, "%d", Damage);
if(SplashLiquid != LIQUID_NONE){
- CreatePool(GetMapContainer(this->CrObject),
- GetSpecialObject(BLOOD_SPLASH),
- SplashLiquid);
+ try{
+ CreatePool(GetMapContainer(this->CrObject),
+ GetSpecialObject(BLOOD_SPLASH),
+ SplashLiquid);
+ }catch(RESULT r){
+ // TODO(fusion): Ignore?
+ }
}
}
@@ -754,10 +758,15 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){
if(ObjType == AmuletOfLossType){
Log("game", "%s stirbt mit Amulett of Loss.\n", this->Name);
this->LoseInventory = 0;
- Delete(Obj, -1);
- // TODO(fusion): Shouldn't we break here? We could also
- // just check if there is an amulet of loss in the necklace
- // container instead of iterating over all of them.
+ try{
+ Delete(Obj, -1);
+ // TODO(fusion): Shouldn't we break here? We could also
+ // just check if there is an amulet of loss in the necklace
+ // container instead of iterating over all inventory.
+ }catch(RESULT r){
+ error("TCreature::Damage: Exception %d beim Löschen von Objekt %d.\n",
+ r, AmuletOfLossType.TypeID);
+ }
}
}
}
diff --git a/src/crplayer.cc b/src/crplayer.cc
index 5b87ec8..8d962fb 100644
--- a/src/crplayer.cc
+++ b/src/crplayer.cc
@@ -1,4 +1,5 @@
#include "cr.hh"
+#include "info.hh"
#include "stubs.hh"
diff --git a/src/info.hh b/src/info.hh
index 863c500..8972276 100644
--- a/src/info.hh
+++ b/src/info.hh
@@ -52,6 +52,7 @@ bool ThrowPossible(int OrigX, int OrigY, int OrigZ,
int DestX, int DestY, int DestZ, int Power);
void GetCreatureLight(uint32 CreatureID, int *Brightness, int *Color);
int GetInventoryWeight(uint32 CreatureID);
+bool CheckRight(uint32 CharacterID, RIGHT Right);
bool CheckBanishmentRight(uint32 CharacterID, int Reason, int Action);
const char *GetBanishmentReason(int Reason);
void InitInfo(void);
diff --git a/src/main.cc b/src/main.cc
index bbdebf1..7a804e0 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -4,6 +4,7 @@
#include "map.hh"
#include "magic.hh"
#include "objects.hh"
+#include "operate.hh"
#include "stubs.hh"
@@ -238,7 +239,7 @@ static void InitAll(void){
InitCr();
//InitHouses();
InitTime();
- //ApplyPatches();
+ ApplyPatches();
}catch(const char *str){
error("Initialisierungsfehler: %s\n", str);
exit(EXIT_FAILURE);
diff --git a/src/objects.hh b/src/objects.hh
index 3d312ac..05b094d 100644
--- a/src/objects.hh
+++ b/src/objects.hh
@@ -62,6 +62,17 @@ struct ObjectType {
|| this->getFlag(WAND);
}
+ bool isCloseWeapon(void){
+ if(!this->getFlag(WEAPON)){
+ return false;
+ }
+
+ int WeaponType = this->getAttribute(WEAPONTYPE);
+ return WeaponType == WEAPON_SWORD
+ || WeaponType == WEAPON_CLUB
+ || WeaponType == WEAPON_AXE;
+ }
+
ObjectType getDisguise(void){
if(this->getFlag(DISGUISE)){
return (int)this->getAttribute(DISGUISETARGET);
diff --git a/src/operate.cc b/src/operate.cc
index 1e1f9a6..2224ed4 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -4,6 +4,23 @@
#include "stubs.hh"
+#include <dirent.h>
+#include <time.h>
+
+static fifo<TStatement> Statements(1024);
+static fifo<TListener> Listeners(1024);
+
+static vector<TChannel> Channel(0, 18, 10);
+static int Channels;
+static int CurrentChannelID;
+static int CurrentSubscriberNumber;
+
+static vector<TParty> Party(0, 100, 50);
+static int Parties;
+
+// World Operations
+// =============================================================================
+
// 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
@@ -383,7 +400,9 @@ void CheckTopMultiuseObject(uint32 CreatureID, Object Obj){
Best = Help;
}
- if(HelpType.getFlag(FORCEUSE) || GetObjectPriority(Help) >= PRIORITY_CREATURE){
+ if(HelpType.getFlag(FORCEUSE)
+ || GetObjectPriority(Help) == PRIORITY_CREATURE
+ || GetObjectPriority(Help) == PRIORITY_LOW){
break;
}
@@ -2145,6 +2164,14 @@ void Look(uint32 CreatureID, Object Obj){
}
void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text, bool CheckSpamming){
+ // TODO(fusion): `Text` was originally `char*`, but I wanted to improve
+ // string handling overall and modifying string parameters is a bad idea,
+ // specially when you don't know their capacity.
+ // It is only modified when a player uses `TALK_YELL` to make it upper
+ // case, which shouldn't be a problem, but if we plan to do any cleanup
+ // afterwards, we need to get this right from the beginning.
+ char YellBuffer[256];
+
TCreature *Creature = GetCreature(CreatureID);
if(Creature == NULL){
error("Talk: Übergebene Kreatur %d existiert nicht.\n", CreatureID);
@@ -2217,11 +2244,9 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
throw EXHAUSTED;
}
- // TODO(fusion): This would be valid if `Text` was `char*`, but I
- // wanted to improve the quality of string handling and parameters
- // across the board, and now we need some scratch buffer to actually
- // modify the text.
- strUpper(Text);
+ strcpy(YellBuffer, Text);
+ strUpper(YellBuffer);
+ Text = YellBuffer;
}
if(Mode == TALK_CHANNEL_CALL && Channel == 5){
@@ -2277,7 +2302,7 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
}
if(Mode == TALK_PRIVATE_MESSAGE){
- Muting = Player->RecordMessage(Receiver->ID);
+ int Muting = Player->RecordMessage(Receiver->ID);
if(Muting > 0){
SendMessage(Player->Connection, TALK_FAILURE_MESSAGE,
"You have addressed too many players. You are muted for %d second%s.",
@@ -2320,7 +2345,7 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
TFindCreatures Search(Radius, Radius, Creature->posx, Creature->posy, FIND_PLAYERS);
while(true){
- uint32 SpectatorID = Search.findNext();
+ uint32 SpectatorID = Search.getNext();
if(SpectatorID == 0){
break;
}
@@ -2413,8 +2438,8 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
continue;
}
- // TODO(fusion): We should probably review this. What if both player
- // guild names are empty? Is it checked elsewhere?
+ // TODO(fusion): We should probably review this. You'd assume creature
+ // should be a player when talking to any channel.
if(Channel == 0 && (Creature->Type != PLAYER
|| strcmp(((TPlayer*)Creature)->Guild, Subscriber->Guild) != 0)){
continue;
@@ -2449,3 +2474,983 @@ void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text,
}
}
}
+
+void Use(uint32 CreatureID, Object Obj1, Object Obj2, uint8 Info){
+ if(!Obj1.exists()){
+ error("Use: Übergebenes Objekt Obj 1 existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(Obj2 != NONE && !Obj2.exists()){
+ error("Use: Übergebenes Objekt Obj 2 existiert nicht.\n");
+ throw ERROR;
+ }
+
+ CheckTopUseObject(CreatureID, Obj1);
+ if(!ObjectAccessible(CreatureID, Obj1, 1)){
+ throw NOTACCESSIBLE;
+ }
+
+ ObjectType ObjType1 = Obj1.getObjectType();
+ if(Obj2 != NONE){
+ // TODO(fusion): Is this correct?
+ if(!ObjType1.getFlag(DISTUSE)){
+ CheckTopMultiuseObject(CreatureID, Obj2);
+ }
+
+ if(!ObjectAccessible(CreatureID, Obj2, 1)){
+ if(!ObjType1.getFlag(DISTUSE)){
+ throw NOTACCESSIBLE;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("Use: Verursachende Kreatur existiert nicht.\n");
+ throw ERROR;
+ }
+
+ int ObjX2, ObjY2, ObjZ2;
+ GetObjectCoordinates(Obj2, &ObjX2, &ObjY2, &ObjZ2);
+ if(Creature->posz > ObjZ2){
+ throw UPSTAIRS;
+ }else if(Creature->posz < ObjZ2){
+ throw DOWNSTAIRS;
+ }
+
+ if(!ThrowPossible(Creature->posx, Creature->posy, Creature->posz, ObjX2, ObjY2, ObjZ2, 0)){
+ throw CANNOTTHROW;
+ }
+ }
+ }
+
+ if(ObjType1.getFlag(CONTAINER)){
+ UseContainer(CreatureID, Obj1, Info);
+ }else if(ObjType1.getFlag(CHEST)){
+ UseChest(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(LIQUIDCONTAINER)){
+ UseLiquidContainer(CreatureID, Obj1, Obj2);
+ }else if(ObjType1.getFlag(FOOD)){
+ UseFood(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(WRITE) || ObjType1.getFlag(WRITEONCE)){
+ UseTextObject(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(INFORMATION)){
+ UseAnnouncer(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(RUNE)){
+ UseMagicItem(CreatureID, Obj1, Obj2);
+ }else if(ObjType1.getFlag(KEY)){
+ UseKeyDoor(CreatureID, Obj1, Obj2);
+ }else if(ObjType1.getFlag(NAMEDOOR)){
+ UseNameDoor(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(LEVELDOOR)){
+ UseLevelDoor(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(QUESTDOOR)){
+ UseQuestDoor(CreatureID, Obj1);
+ }else if(ObjType1.isCloseWeapon()
+ && Obj2 != NONE
+ && Obj2.getObjectType().getFlag(DESTROY)){
+ UseWeapon(CreatureID, Obj1, Obj2);
+ }else if(ObjType1.getFlag(CHANGEUSE)){
+ UseChangeObject(CreatureID, Obj1);
+ }else if(ObjType1.getFlag(USEEVENT)){
+ if(Obj2 != NONE){
+ UseObjects(CreatureID, Obj1, Obj2);
+ }else{
+ UseObject(CreatureID, Obj1);
+ }
+ }else if(ObjType1.getFlag(TEXT)
+ && ObjType1.getAttribute(FONTSIZE) == 1){
+ UseTextObject(CreatureID, Obj1);
+ }else{
+ throw NOTUSABLE;
+ }
+}
+
+void Turn(uint32 CreatureID, Object Obj){
+ if(!Obj.exists()){
+ error("Turn: Übergebenes Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ if(!ObjectAccessible(CreatureID, Obj, 1)){
+ throw NOTACCESSIBLE;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.getFlag(ROTATE)){
+ throw NOTTURNABLE;
+ }
+
+ ObjectType RotateTarget = ObjType.getAttribute(ROTATETARGET);
+ if(RotateTarget == ObjType){
+ error("Turn: Objekt %d wird durch Drehen zerstört.\n", ObjType.TypeID);
+ }
+
+ Change(Obj, RotateTarget, 0);
+}
+
+void CreatePool(Object Con, ObjectType Type, uint32 Value){
+ if(!Con.exists()){
+ error("CreatePool: Übergebener MapContainer existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.isMapContainer()){
+ error("CreatePool: Übergebenes Objekt ist kein MapContainer.\n");
+ throw ERROR;
+ }
+
+ // NOTE(fusion): There can be no liquid pools on fields with other BOTTOM
+ // objects, with the exception of other liquid pools, in which case the new
+ // liquid pool would replace the old one.
+ Object Help = GetFirstContainerObject(Con);
+ while(Help != NONE){
+ Object Next = Help.getNextObject();
+ ObjectType HelpType = Help.getObjectType();
+ if(HelpType.getFlag(BOTTOM)){
+ if(!HelpType.getFlag(LIQUIDPOOL)){
+ throw NOROOM;
+ }
+
+ try{
+ Delete(Help, -1);
+ }catch(RESULT r){
+ error("CreatePool: Exception %d beim Löschen des alten Pools.\n", r);
+ }
+ }
+ Help = Next;
+ }
+
+ Create(Con, Type, Value);
+}
+
+void EditText(uint32 CreatureID, Object Obj, const char *Text){
+ if(!Obj.exists()){
+ error("EditText: Übergebenes Objekt existiert nicht.\n");
+ throw ERROR;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.getFlag(WRITE) && (!ObjType.getFlag(WRITEONCE) || Obj.getAttribute(TEXTSTRING) != 0)){
+ error("EditText: Objekt ist nicht beschreibbar.\n");
+ throw ERROR;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("EditText: Kreatur existiert nicht.\n");
+ throw ERROR;
+ }
+
+ int TextLength = (int)strlen(Text);
+ int MaxLength = (ObjType.getFlag(WRITE)
+ ? ObjType.getAttribute(MAXLENGTH)
+ : ObjType.getAttribute(MAXLENGTHONCE));
+ if(TextLength >= MaxLength){
+ throw TOOLONG;
+ }
+
+ // TODO(fusion): Similar to maybe inlined function in `Look`.
+ // TODO(fusion): Same as in `Look`. `CreatureID` can't be zero here or we'd
+ // have already returned so its probably some inlined function.
+ if(CreatureID != 0 && !ObjectAccessible(CreatureID, Obj, 1)){
+ throw NOTACCESSIBLE;
+ }
+
+ uint32 ObjText = Obj.getAttribute(TEXTSTRING);
+ if((ObjText != 0 && strcmp(GetDynamicString(ObjText), Text) == 0)
+ || (ObjText == 0 && Text[0] == 0)){
+ print(3, "Text hat sich nicht geändert.\n");
+ return;
+ }
+
+ DeleteDynamicString(ObjText);
+ Change(Obj, TEXTSTRING, AddDynamicString(Text));
+
+ DeleteDynamicString(Obj.getAttribute(EDITOR));
+ Change(Obj, EDITOR, AddDynamicString(Creature->Name));
+}
+
+Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value){
+ // TODO(fusion): Bruhh...
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ // TODO(fusion): Different function name?
+ error("GiveObjectToCreature: Kann Kreatur nicht finden.\n");
+ throw ERROR;
+ }
+
+ try{
+ CheckWeight(CreatureID, Type, Value, 0);
+ }catch(RESULT r){
+ return Create(GetMapContainer(Creature->CrObject), Type, Value);
+ }
+
+ Object Obj = NONE;
+ bool CheckContainers = Type.getFlag(MOVEMENTEVENT);
+ for(int i = 0; i < 2; i += 1){
+ bool TooHeavy = false;
+ for(int Position = INVENTORY_FIRST;
+ Position <= INVENTORY_LAST;
+ Position += 1){
+ try{
+ Object BodyObj = GetBodyObject(CreatureID, Position);
+ if(CheckContainers){
+ if(BodyObj != NONE && BodyObj.getObjectType().getFlag(CONTAINER)){
+ Obj = Create(BodyObj, Type, Value);
+ break;
+ }
+ }else{
+ if(BodyObj == NONE){
+ Obj = Create(GetBodyContainer(CreatureID, Position), Type, Value);
+ break;
+ }
+ }
+ }catch(RESULT r){
+ // TODO(fusion): Is this even possible if we're checking the
+ // weight before hand?
+ if(r == TOOHEAVY){
+ TooHeavy = true;
+ break;
+ }
+ }
+ }
+
+ if(Obj != NONE || TooHeavy){
+ break;
+ }
+
+ CheckContainers = !CheckContainers;
+ }
+
+ if(Obj == NONE){
+ Obj = Create(GetMapContainer(Creature->CrObject), Type, Value);
+ }
+
+ return Obj;
+}
+
+void DeleteAtCreature(uint32 CreatureID, ObjectType Type, int Amount, uint32 Value){
+ while(Amount > 0){
+ Object Obj = GetInventoryObject(CreatureID, Type, Value);
+ if(Obj == NONE){
+ error("DeleteAtCreature: Kein Objekt gefunden.\n");
+ throw ERROR;
+ }
+
+ if(Type.getFlag(CUMULATIVE)){
+ int ObjAmount = (int)Obj.getAttribute(AMOUNT);
+ if(ObjAmount < Amount){
+ Delete(Obj, -1);
+ Amount -= ObjAmount;
+ }else{
+ Change(Obj, AMOUNT, (ObjAmount - Amount));
+ Amount = 0;
+ }
+ }else{
+ Delete(Obj, -1);
+ Amount -= 1;
+ }
+ }
+}
+
+void ProcessCronSystem(void){
+ while(true){
+ Object Obj = CronCheck();
+ if(Obj == NONE){
+ break;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ ObjectType ExpireTarget = ObjType.getAttribute(EXPIRETARGET);
+ if(ObjType.getFlag(CONTAINER)){
+ int Remainder = 0;
+ if(!ExpireTarget.isMapContainer() && ExpireTarget.getFlag(CONTAINER)){
+ Remainder = (int)ExpireTarget.getAttribute(CAPACITY);
+ }
+
+ Empty(Obj, Remainder);
+ }
+
+ Change(Obj, ExpireTarget, 0);
+ }
+}
+
+bool SectorRefreshable(int SectorX, int SectorY, int SectorZ){
+ // TODO(fusion): Have the sector size defined as a constant in `map.hh`?
+ //constexpr int SectorSize = 32;
+ int SearchRadiusX = 32 - 1;
+ int SearchRadiusY = 32 - 1;
+ int SearchCenterX = SectorX * 32 + (32 / 2);
+ int SearchCenterY = SectorY * 32 + (32 / 2);
+ TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_PLAYERS);
+ while(true){
+ uint32 CharacterID = Search.getNext();
+ if(CharacterID == 0){
+ break;
+ }
+
+ TPlayer *Player = GetPlayer(CharacterID);
+ if(Player == NULL){
+ error("SectorRefreshable: Kreatur existiert nicht.\n");
+ continue;
+ }
+
+ // TODO(fusion): Maybe an inlined function to check whether a player
+ // can see some floor. All floors above ground, when above ground. Or
+ // two floors up and down, when underground.
+ if(Player->posz <= 7){
+ if(SectorZ <= 7){
+ return false;
+ }
+ }else{
+ if(std::abs(Player->posz - SectorZ) <= 2){
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void RefreshSector(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Count){
+ if(!SectorRefreshable(SectorX, SectorY, SectorZ)){
+ return;
+ }
+
+ TReadBuffer Buffer(Data, Count);
+ RefreshSector(SectorX, SectorY, SectorZ, &Buffer);
+
+ // TODO(fusion): This function is very similar to `ApplyPatch`.
+ int SearchRadiusX = 32 / 2;
+ int SearchRadiusY = 32 / 2;
+ int SearchCenterX = SectorX * 32 + (32 / 2);
+ int SearchCenterY = SectorY * 32 + (32 / 2);
+ TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_ALL);
+ while(true){
+ uint32 CreatureID = Search.getNext();
+ if(CreatureID == 0){
+ break;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("RefreshSector: Kreatur existiert nicht.\n");
+ continue;
+ }
+
+ if(Creature->posz != SectorZ){
+ continue;
+ }
+
+ bool FieldBlocked = false;
+ int FieldX = Creature->posx;
+ int FieldY = Creature->posy;
+ int FieldZ = Creature->posz;
+ Object Obj = GetFirstObject(FieldX, FieldY, FieldZ);
+ while(Obj != NONE){
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.isCreatureContainer() && ObjType.getFlag(UNPASS)){
+ FieldBlocked = true;
+ break;
+ }
+ Obj = Obj.getNextObject();
+ }
+
+ if(FieldBlocked){
+ try{
+ if(!SearchFreeField(&FieldX, &FieldY, &FieldZ, 1, 0, false)){
+ if(Creature->Type == NPC){
+ print(2, "NPC auf [%d,%d,%d] muß auf seinen Start zurückgesetzt werden.\n", FieldX, FieldY, FieldZ);
+ FieldX = Creature->startx;
+ FieldY = Creature->starty;
+ FieldZ = Creature->startz;
+ }else if(Creature->Type == MONSTER){
+ print(2, "Monster auf [%d,%d,%d] muß gelöscht werden.\n", FieldX, FieldY, FieldZ);
+ delete Creature;
+ continue;
+ }else{
+ error("Spieler auf [%d,%d,%d] ist von Refresh betroffen.\n", FieldX, FieldY, FieldZ);
+ continue;
+ }
+ }
+
+ Object MapCon = GetMapContainer(FieldX, FieldY, FieldZ);
+ Move(0, Creature->CrObject, MapCon, -1, false, NONE);
+ }catch(RESULT r){
+ error("RefreshSector: Exception %d beim Neusetzen des Monsters.\n", r);
+ }
+ }
+ }
+}
+
+void RefreshMap(void){
+ TDynamicWriteBuffer HelpBuffer(0x10000);
+ for(int SectorZ = SectorZMin; SectorZ <= SectorZMax; SectorZ += 1)
+ for(int SectorY = SectorYMin; SectorY <= SectorYMax; SectorY += 1)
+ for(int SectorX = SectorXMin; SectorX <= SectorXMax; SectorX += 1){
+ if(!SectorRefreshable(SectorX, SectorY, SectorZ)){
+ continue;
+ }
+
+ char FileName[4096];
+ snprintf(FileName, sizeof(FileName), "%s/%04u-%04u-%02u.sec",
+ ORIGMAPPATH, SectorX, SectorY, SectorZ);
+ if(!FileExists(FileName)){
+ continue;
+ }
+
+ bool Refreshable = false;
+ int OffsetX = -1;
+ int OffsetY = -1;
+ HelpBuffer.reset();
+ try{
+ TReadScriptFile Script;
+ Script.open(FileName);
+ while(true){
+ Script.nextToken();
+ if(Script.Token == ENDOFFILE){
+ Script.close();
+ break;
+ }
+
+ if(Script.Token == SPECIAL && Script.getSpecial() == ','){
+ continue;
+ }
+
+ if(Script.Token == BYTES){
+ uint8 *SectorOffset = Script.getBytesequence();
+ OffsetX = (int)SectorOffset[0];
+ OffsetY = (int)SectorOffset[1];
+ Script.readSymbol(':');
+ continue;
+ }
+
+ // TODO(fusion): We don't enforce the token to be an identifier
+ // here as we do when loading any sector file in `map.cc`.
+ if(Script.Token == IDENTIFIER){
+ if(OffsetX == -1 || OffsetY == -1){
+ Script.error("coordinate expected");
+ }
+
+ const char *Identifier = Script.getIdentifier();
+ if(strcmp(Identifier, "refresh") == 0){
+ Refreshable = true;
+ }else if(strcmp(Identifier, "content") == 0){
+ Script.readSymbol('=');
+ if(Refreshable){
+ HelpBuffer.writeByte((uint8)OffsetX);
+ HelpBuffer.writeByte((uint8)OffsetY);
+ }
+ LoadObjects(&Script, &HelpBuffer, !Refreshable);
+ }
+ }
+ }
+
+ if(HelpBuffer.Position > 0){
+ TReadBuffer ReadBuffer(HelpBuffer.Data, HelpBuffer.Position);
+ RefreshSector(SectorX, SectorY, SectorZ, &ReadBuffer);
+ }
+ }catch(const char *str){
+ error("RefreshMap: Fehler beim Bearbeiten der Datei (%s).\n", str);
+ }
+ }
+}
+
+void RefreshCylinders(void){
+ // TODO(fusion): `RefreshedCylinders` is the number of cylinders we attempt to
+ // refresh in this function, which is called every minute or so by `AdvanceGame`.
+ // We should probably rename it to something more clear.
+
+ // TODO(fusion): This might be on purpose but `RefreshX` and `RefreshY` will be
+ // way below `SectorXMin` and `SectorYMin` the first N times this function is
+ // called and depending on the value of `RefreshedCylinders`, could take a few
+ // hours before we even start refreshing the map.
+ // If the intent is to delay refreshing cylinders until some time after startup,
+ // we should change how this function is called by `AdvanceGame` instead.
+
+ static int RefreshX = -1;
+ static int RefreshY = -1;
+ for(int i = 0; i < RefreshedCylinders; i += 1){
+ if(RefreshX < SectorXMax){
+ RefreshX += 1;
+ }else{
+ RefreshX = SectorXMin;
+ if(RefreshY < SectorYMax){
+ RefreshY += 1;
+ }else{
+ RefreshY = SectorYMin;
+ }
+ }
+
+ for(int RefreshZ = SectorZMin;
+ RefreshZ <= SectorZMax;
+ RefreshZ += 1){
+ if(SectorRefreshable(RefreshX, RefreshY, RefreshZ)){
+ LoadSectorOrder(RefreshX, RefreshY, RefreshZ);
+ }
+ }
+ }
+}
+
+void ApplyPatch(int SectorX, int SectorY, int SectorZ,
+ bool FullSector, TReadScriptFile *Script, bool SaveHouses){
+ if(SectorX < SectorXMin || SectorX > SectorXMax
+ || SectorY < SectorYMin || SectorY > SectorYMax
+ || SectorZ < SectorZMin || SectorZ > SectorZMax){
+ return;
+ }
+
+ PrepareHouseCleanup();
+ PatchSector(SectorX, SectorY, SectorZ, FullSector, Script, SaveHouses);
+ FinishHouseCleanup();
+
+ // TODO(fusion): Similar to `SectorRefreshable` but with a reduced radius.
+ int SearchRadiusX = 32 / 2;
+ int SearchRadiusY = 32 / 2;
+ int SearchCenterX = SectorX * 32 + (32 / 2);
+ int SearchCenterY = SectorY * 32 + (32 / 2);
+ TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_ALL);
+ while(true){
+ uint32 CreatureID = Search.getNext();
+ if(CreatureID == 0){
+ break;
+ }
+
+ TCreature *Creature = GetCreature(CreatureID);
+ if(Creature == NULL){
+ error("ApplyPatch: Kreatur existiert nicht.\n");
+ continue;
+ }
+
+ if(Creature->posz != SectorZ){
+ continue;
+ }
+
+ bool FieldBlocked = false;
+ int FieldX = Creature->posx;
+ int FieldY = Creature->posy;
+ int FieldZ = Creature->posz;
+ Object Obj = GetFirstObject(FieldX, FieldY, FieldZ);
+ while(Obj != NONE){
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.isCreatureContainer() && ObjType.getFlag(UNPASS)){
+ FieldBlocked = true;
+ break;
+ }
+ Obj = Obj.getNextObject();
+ }
+
+ if(!FieldBlocked){
+ // TODO(fusion): Not sure why we're moving the creature to the same
+ // field, specially with `MoveObject`. Does `PatchSector` leave
+ // creatures on invalid indices?
+ Object MapCon = GetMapContainer(FieldX, FieldY, FieldZ);
+ MoveObject(Creature->CrObject, MapCon);
+ }else{
+ try{
+ if(!SearchFreeField(&FieldX, &FieldY, &FieldZ, 1, 0, false)){
+ if(Creature->Type == NPC){
+ print(2, "NPC auf [%d,%d,%d] muß auf seinen Start zurückgesetzt werden.\n", FieldX, FieldY, FieldZ);
+ FieldX = Creature->startx;
+ FieldY = Creature->starty;
+ FieldZ = Creature->startz;
+ }else if(Creature->Type == MONSTER){
+ print(2, "Monster auf [%d,%d,%d] muß gelöscht werden.\n", FieldX, FieldY, FieldZ);
+ Delete(Creature->CrObject, -1);
+ Creature->StartLogout(false, false);
+ continue;
+ }else{
+ error("Spieler auf [%d,%d,%d] ist von Patch betroffen.\n", FieldX, FieldY, FieldZ);
+ continue;
+ }
+ }
+
+ Object MapCon = GetMapContainer(FieldX, FieldY, FieldZ);
+ Move(0, Creature->CrObject, MapCon, -1, false, NONE);
+ }catch(RESULT r){
+ error("ApplyPatch: Exception %d beim Neusetzen des Monsters.\n", r);
+ }
+ }
+ }
+}
+
+void ApplyPatches(void){
+ // TODO(fusion): We don't handle any script exceptions in here which could
+ // lead to `PatchDir` being leaked. It may not be a problem overall because
+ // this function is only called at startup by `InitAll`.
+
+ char FileName[4096];
+ bool SaveHouses = false;
+ snprintf(FileName, sizeof(FileName), "%s/save-houses", SAVEPATH);
+ if(FileExists(FileName)){
+ SaveHouses = true;
+ print(2, "Häuser werden nicht gepatcht.\n");
+ unlink(FileName);
+ }
+
+ DIR *PatchDir = opendir(SAVEPATH);
+ if(PatchDir == NULL){
+ error("ApplyPatches: Unterverzeichnis %s nicht gefunden.\n", SAVEPATH);
+ return;
+ }
+
+ int MaxPatch = -1;
+ while(dirent *DirEntry = readdir(PatchDir)){
+ if(DirEntry->d_type != DT_REG){
+ continue;
+ }
+
+ const char *FileExt = findLast(DirEntry->d_name, '.');
+ if(FileExt == NULL){
+ continue;
+ }
+
+ if(strcmp(FileExt, ".pat") == 0){
+ int Patch;
+ if(sscanf(DirEntry->d_name, "%d.pat", &Patch) == 1){
+ if(MaxPatch < Patch){
+ MaxPatch = Patch;
+ }
+ }
+ }else if(strcmp(FileExt, ".sec") == 0){
+ int SectorX, SectorY, SectorZ;
+ if(sscanf(DirEntry->d_name, "%d-%d-%d.sec", &SectorX, &SectorY, &SectorZ) == 3){
+ print(2,"Patche kompletten Sektor %d/%d/%d ...\n", SectorX, SectorY, SectorZ);
+ snprintf(FileName, sizeof(FileName), "%s/%s", SAVEPATH, DirEntry->d_name);
+
+ TReadScriptFile Script;
+ Script.open(FileName);
+ ApplyPatch(SectorX, SectorY, SectorZ, true, &Script, SaveHouses);
+ Script.close();
+ unlink(FileName);
+ }
+ }
+ }
+
+ closedir(PatchDir);
+
+ for(int Patch = 0; Patch <= MaxPatch; Patch += 1){
+ snprintf(FileName, sizeof(FileName), "%s/%03d.pat", SAVEPATH, Patch);
+ if(FileExists(FileName)){
+ TReadScriptFile Script;
+ Script.open(FileName);
+ if(strcmp(Script.readIdentifier(), "sector") != 0){
+ Script.error("Sector expected");
+ }
+
+ int SectorX = Script.readNumber();
+ Script.readSymbol(',');
+ int SectorY = Script.readNumber();
+ Script.readSymbol(',');
+ int SectorZ = Script.readNumber();
+
+ print(2, "Patche Teile von Sektor %d/%d/%d (Patch %d) ...\n",
+ SectorX, SectorY, SectorZ, Patch);
+ ApplyPatch(SectorX, SectorY, SectorZ, false, &Script, false);
+ Script.close();
+ unlink(FileName);
+ }
+ }
+}
+
+// Communication Logging
+// =============================================================================
+uint32 LogCommunication(uint32 CreatureID, int Mode, int Channel, const char *Text){
+ static uint32 StatementID = 0;
+
+ if(Text == NULL){
+ error("LogCommunication: Text ist NULL.\n");
+ return 0;
+ }
+
+ if(CreatureID == 0){
+ error("LogCommunication: CharacterID ist Null.\n");
+ return 0;
+ }
+
+ StatementID += 1;
+
+ TStatement *Statement = Statements.append();
+ Statement->StatementID = StatementID;
+ Statement->TimeStamp = (uint32)time(NULL);
+ Statement->CharacterID = CreatureID;
+ Statement->Mode = Mode;
+ Statement->Channel = Channel;
+ Statement->Text = AddDynamicString(Text);
+ Statement->Reported = false;
+ return StatementID;
+}
+
+uint32 LogListener(uint32 StatementID, TPlayer *Player){
+ if(StatementID == 0 || Player == NULL
+ || !CheckRight(Player->ID, LOG_COMMUNICATION)){
+ return 0;
+ }
+
+ TListener *Listener = Listeners.append();
+ Listener->StatementID = StatementID;
+ Listener->CharacterID = Player->ID;
+ return StatementID;
+}
+
+void ProcessCommunicationControl(void){
+ // NOTE(fusion): Remove statements older than 30 minutes.
+ int Now = (int)time(NULL);
+ uint32 Limit = 0;
+ while(true){
+ TStatement *Statement = Statements.next();
+ if(Statement == NULL || Now <= (Statement->TimeStamp + 1800)){
+ if(Statement != NULL){
+ Limit = Statement->StatementID;
+ }
+ break;
+ }
+
+ DeleteDynamicString(Statement->Text);
+ Statements.remove();
+ }
+
+ // TODO(fusion): If there are no statements left we'll end up with `Limit`
+ // equal to zero which will prevent any listeners entry from being removed.
+ while(true){
+ TListener *Listener = Listeners.next();
+ if(Listener == NULL || Listener->StatementID >= Limit){
+ break;
+ }
+
+ Listeners.remove();
+ }
+}
+
+int GetCommunicationContext(uint32 CharacterID, uint32 StatementID,
+ int *NumberOfStatements, vector<TReportedStatement> **ReportedStatements){
+ TStatement *Statement = NULL;
+ int StatementsIter = Statements.iterFirst();
+ while(true){
+ Statement = Statements.iterNext(&StatementsIter);
+ if(Statement == NULL || Statement->StatementID == StatementID){
+ break;
+ }
+ }
+
+ if(Statement == NULL){
+ return 1; // STATEMENT_UNKNOWN ?
+ }
+
+ if(CharacterID == 0){
+ bool ChannelMode = Statement->Mode == TALK_CHANNEL_CALL
+ || Statement->Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Statement->Mode == TALK_HIGHLIGHT_CHANNELCALL;
+
+ bool ReportableChannel = Statement->Channel == 2 // CHANNEL_TUTOR
+ || Statement->Channel == 4 // CHANNEL_GAME
+ || Statement->Channel == 5 // CHANNEL_TRADE
+ || Statement->Channel == 6 // CHANNEL_RLCHAT
+ || Statement->Channel == 7; // CHANNEL_HELP
+
+ if(!ChannelMode || !ReportableChannel){
+ error("GetCommunicationContext: Äußerung dürfte nicht gemeldet werden.\n");
+ return 1; // STATEMENT_UNKNOWN ?
+ }
+ }
+
+ if(Statement->Reported){
+ return 2; // STATEMENT_ALREADY_REPORTED ?
+ }
+
+ // TODO(fusion): `FreeSpace` limits the amount of data that is gathered. It
+ // seems to grow/shrink with the size of the text plus an extra 46 bytes for
+ // each statement entry. This flat memory overhead of 46 bytes could be some
+ // compilation/decompilation artifact so I've left it out for now.
+ // The end point of this data is `ProcessPunishmentOrder` which may record
+ // statements into the database so it may be related to that.
+
+ bool StatementContained = false;
+ int FreeSpace = KB(16);
+ *NumberOfStatements = 0;
+ *ReportedStatements = new vector<TReportedStatement>(0, 100, 100);
+ StatementsIter = Statements.iterLast();
+ while(true){
+ TStatement *Current = Statements.iterPrev(&StatementsIter);
+ if(Current == NULL){
+ break;
+ }
+
+ if(Current->TimeStamp < (Statement->TimeStamp - 180)
+ || Current->TimeStamp > (Statement->TimeStamp + 60)){
+ continue;
+ }
+
+ if(FreeSpace <= 0 && Current->TimeStamp > Statement->TimeStamp){
+ error("GetCommunicationContext: Kontext wird zu groß. Schneide Ende ab.\n");
+ break;
+ }
+
+ if(CharacterID == 0){
+ bool ChannelMode = Current->Mode == TALK_CHANNEL_CALL
+ || Current->Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Current->Mode == TALK_HIGHLIGHT_CHANNELCALL;
+ if(!ChannelMode || Current->Channel != Statement->Channel){
+ continue;
+ }
+ }else{
+ // NOTE(fusion): Check if the character listened to the current statement.
+ TListener *Listener = NULL;
+ int ListenersIter = Listeners.iterLast();
+ while(true){
+ Listener = Listeners.iterPrev(&ListenersIter);
+ if(Listener == NULL
+ || Listener->StatementID > Current->StatementID
+ || (Listener->StatementID == Current->StatementID
+ && Listener->CharacterID == CharacterID)){
+ break;
+ }
+ }
+
+ if(Listener == NULL || Listener->StatementID != Current->StatementID){
+ continue;
+ }
+ }
+
+ TReportedStatement *Entry = (*ReportedStatements)->at(*NumberOfStatements);
+ Entry->StatementID = Current->StatementID;
+ Entry->TimeStamp = Current->TimeStamp;
+ Entry->CharacterID = Current->CharacterID;
+ Entry->Mode = Current->Mode;
+ Entry->Channel = Current->Channel;
+ if(Current->Text != 0){
+ // TODO(fusion): OOF SIZE: Large.
+ strcpy(Entry->Text, GetDynamicString(Current->Text));
+ }else{
+ Entry->Text[0] = 0;
+ }
+ *NumberOfStatements += 1;
+ FreeSpace -= (int)strlen(Entry->Text);
+
+ if(Current->StatementID == StatementID){
+ StatementContained = true;
+ }
+ }
+
+ if(FreeSpace < 0){
+ error("GetCommunicationContext: Kontext wird um %d Bytes zu groß. Lösche Anfang.\n", -FreeSpace);
+
+ for(int i = 0; i < *NumberOfStatements && FreeSpace < 0; i += 1){
+ TReportedStatement *Entry = (*ReportedStatements)->at(i);
+ if(Entry->StatementID != StatementID){
+ Entry->StatementID = 0;
+ FreeSpace += (int)strlen(Entry->Text);
+ }
+ }
+
+ if(FreeSpace < 0){
+ error("GetCommunicationContext: FreeSpace ist immer noch negativ (%d).\n", FreeSpace);
+ }
+ }
+
+ if(!StatementContained){
+ error("GetCommunicationContext: Statement ist nicht im Kontext enthalten.\n");
+ delete *ReportedStatements;
+ *NumberOfStatements = 0;
+ *ReportedStatements = NULL;
+ return 1; // STATEMENT_UNKNOWN ?
+ }
+
+ Statement->Reported = true;
+ return 0; // STATEMENT_REPORTED ?
+}
+
+// Channel
+// =============================================================================
+TChannel::TChannel(void) : Subscriber(0, 10, 10), InvitedPlayer(0, 10, 10) {
+ this->Moderator = 0;
+ this->ModeratorName[0] = 0;
+ this->Subscribers = 0;
+ this->InvitedPlayers = 0;
+}
+
+TChannel::TChannel(const TChannel &Other) : TChannel() {
+ this->operator=(Other);
+}
+
+void TChannel::operator=(const TChannel &Other){
+ this->Subscribers = Other.Subscribers;
+ for(int i = 0; i < Other.Subscribers; i += 1){
+ *this->Subscriber.at(i) = Other.Subscriber.copyAt(i);
+ }
+
+ this->InvitedPlayers = Other.InvitedPlayers;
+ for(int i = 0; i < Other.InvitedPlayers; i += 1){
+ *this->InvitedPlayer.at(i) = Other.InvitedPlayer.copyAt(i);
+ }
+}
+
+bool ChannelActive(int ChannelID){
+ if(ChannelID < 0 || ChannelID >= Channels){
+ error("ChannelActive: Ungültige Kanalnummer %d.\n", ChannelID);
+ return false;
+ }
+
+ return ChannelID <= 7 || Channel.at(ChannelID)->Moderator != 0;
+}
+
+const char *GetChannelName(int ChannelID, uint32 CharacterID){
+ static char ChannelName[40];
+
+ if(!ChannelActive(ChannelID)){
+ return "Unknown";
+ }
+
+ TPlayer *Player = GetPlayer(CharacterID);
+ if(Player == NULL){
+ error("GetChannelName: Spieler existiert nicht.\n");
+ return "Unknown";
+ }
+
+ switch(ChannelID){
+ case 0: return Player->Guild;
+ case 1: return "Gamemaster";
+ case 2: return "Tutor";
+ case 3: return "Rule Violations";
+ case 4: return "Game-Chat";
+ case 5: return "Trade";
+ case 6: return "RL-Chat";
+ case 7: return "Help";
+ default:{
+ if(ChannelID > 7){
+ snprintf(ChannelName, sizeof(ChannelName), "%s\'s Channel",
+ Channel.at(ChannelID)->ModeratorName);
+ return ChannelName;
+ }else{
+ error("GetChannelName: Unbenutzter Kanal %d.\n", ChannelID);
+ return "Unknown";
+ }
+ }
+ }
+}
+
+// Party
+// =============================================================================
+TParty::TParty(void) : Member(0, 10, 10), InvitedPlayer(0, 10, 10) {
+ this->Leader = 0;
+ this->Members = 0;
+ this->InvitedPlayers = 0;
+}
+
+TParty::TParty(const TParty &Other) : TParty() {
+ this->operator=(Other);
+}
+
+void TParty::operator=(const TParty &Other){
+ this->Members = Other.Members;
+ for(int i = 0; i < Other.Members; i += 1){
+ *this->Member.at(i) = Other.Member.copyAt(i);
+ }
+
+ this->InvitedPlayers = Other.InvitedPlayers;
+ for(int i = 0; i < Other.InvitedPlayers; i += 1){
+ *this->InvitedPlayer.at(i) = Other.InvitedPlayer.copyAt(i);
+ }
+}
diff --git a/src/operate.hh b/src/operate.hh
index 7d137fd..0c370a2 100644
--- a/src/operate.hh
+++ b/src/operate.hh
@@ -2,6 +2,8 @@
#define TIBIA_OPERATE_HH_ 1
#include "common.hh"
+#include "containers.hh"
+#include "cr.hh"
#include "map.hh"
enum : int {
@@ -20,6 +22,74 @@ enum : int {
OBJECT_MOVED = 3,
};
+struct TChannel {
+ TChannel(void);
+
+ // TODO(fusion): `TChannel` will primarily live inside the `Channel` vector,
+ // which needs to resize its internal array as needed. To resize, it needs
+ // to copy/swap elements, which would be impossible since `TChannel` itself
+ // owns a few vectors which were made NON-COPYABLE to prevent memory bugs.
+ // To fix this problem and allow `TChannel` to be copyable, we need to
+ // implement the copy constructor and assignment manually. They're annoying
+ // and expensive but should allow everything to compile again.
+ // This problem arises from the fact that our unconventional `vector` type
+ // has a weird interface but still manages its underlying memory. If we are
+ // to resolve this completely, we'd need to re-implement `vector` properly
+ // and preferably with move semantics (if we want to follow the C++ route,
+ // which we may not).
+ TChannel(const TChannel &Other);
+ void operator=(const TChannel &Other);
+
+ // DATA
+ // =================
+ uint32 Moderator;
+ char ModeratorName[30];
+ vector<uint32> Subscriber;
+ int Subscribers;
+ vector<uint32> InvitedPlayer;
+ int InvitedPlayers;
+};
+
+struct TParty {
+ TParty(void);
+
+ // TODO(fusion): Same as `TChannel`.
+ TParty(const TParty &Other);
+ void operator=(const TParty &Other);
+
+ // DATA
+ // =================
+ uint32 Leader;
+ vector<uint32> Member;
+ int Members;
+ vector<uint32> InvitedPlayer;
+ int InvitedPlayers;
+};
+
+struct TStatement {
+ uint32 StatementID;
+ int TimeStamp;
+ uint32 CharacterID;
+ int Mode;
+ int Channel;
+ uint32 Text;
+ bool Reported;
+};
+
+struct TListener {
+ uint32 StatementID;
+ uint32 CharacterID;
+};
+
+struct TReportedStatement {
+ uint32 StatementID;
+ int TimeStamp;
+ uint32 CharacterID;
+ int Mode;
+ int Channel;
+ char Text[256];
+};
+
void AnnounceMovingCreature(uint32 CreatureID, Object Con);
void AnnounceChangedCreature(uint32 CreatureID, int Type);
void AnnounceChangedField(Object Obj, int Type);
@@ -61,5 +131,31 @@ 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);
+void Look(uint32 CreatureID, Object Obj);
+void Talk(uint32 CreatureID, int Mode, const char *Addressee, const char *Text, bool CheckSpamming);
+void Use(uint32 CreatureID, Object Obj1, Object Obj2, uint8 Info);
+void Turn(uint32 CreatureID, Object Obj);
+void CreatePool(Object Con, ObjectType Type, uint32 Value);
+void EditText(uint32 CreatureID, Object Obj, const char *Text);
+Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value);
+void DeleteAtCreature(uint32 CreatureID, ObjectType Type, int Amount, uint32 Value);
+
+void ProcessCronSystem(void);
+bool SectorRefreshable(int SectorX, int SectorY, int SectorZ);
+void RefreshSector(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Count);
+void RefreshMap(void);
+void RefreshCylinders(void);
+void ApplyPatch(int SectorX, int SectorY, int SectorZ,
+ bool FullSector, TReadScriptFile *Script, bool SaveHouses);
+void ApplyPatches(void);
+
+uint32 LogCommunication(uint32 CreatureID, int Mode, int Channel, const char *Text);
+uint32 LogListener(uint32 StatementID, TPlayer *Player);
+void ProcessCommunicationControl(void);
+int GetCommunicationContext(uint32 CharacterID, uint32 StatementID,
+ int *NumberOfStatements, vector<TReportedStatement> **ReportedStatements);
+
+uint32 GetFirstSubscriber(int Channel);
+uint32 GetNextSubscriber(void);
#endif //TIBIA_OPERATE_HH_
diff --git a/src/stubs.hh b/src/stubs.hh
index cb06608..df270ff 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -19,14 +19,11 @@ extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void ChangeNPCState(TCreature *Npc, int NewState, bool Stimulus);
extern void CharacterDeathOrder(TCreature *Creature, int OldLevel,
uint32 Offender, const char *Remark, bool Unjustified);
-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 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 GetExitPosition(uint16 HouseID, int *x, int *y, int *z);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
@@ -39,22 +36,18 @@ extern void InitLog(const char *ProtocolName);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);
extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures);
extern bool LagDetected(void);
-extern void LoadMonsterRaid(const char *FileName, int Start,
- bool *Type, int *Date, int *Interval, int *Duration);
+extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
extern void LogoutAllPlayers(void);
extern void NetLoadCheck(void);
extern void NetLoadSummary(void);
-extern void ProcessCommunicationControl(void);
+extern void PrepareHouseCleanup(void);
+extern void FinishHouseCleanup(void);
extern void ProcessConnections(void);
-extern void ProcessCronSystem(void);
extern void ProcessMonsterhomes(void);
extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails);
extern void ProcessWriterThreadReplies(void);
extern void ReceiveData(void);
-extern void RefreshCylinders(void);
-extern void RefreshMap(void);
-extern void RefreshSector(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Size);
extern void SavePlayerDataOrder(void);
extern void SendAll(void);
extern void SendAmbiente(TConnection *Connection);
@@ -92,13 +85,32 @@ extern void SendPlayerSkills(TConnection *Connection);
extern void SendPlayerState(TConnection *Connection, uint8 State);
extern void SendResult(TConnection *Connection, RESULT r);
extern void SendSnapback(TConnection *Connection);
+extern void SendTalk(TConnection *Connection, uint32 StatementID,
+ const char *Sender, int Mode, const char *Text, int Data);
+extern void SendTalk(TConnection *Connection, uint32 StatementID,
+ const char *Sender, int Mode, int Channel, const char *Text);
+extern void SendTalk(TConnection *Connection, uint32 StatementID,
+ const char *Sender, int Mode, int x,int y,int z, const char *Text);
extern void SendTradeOffer(TConnection *Connection, const char *Name, bool OwnOffer, Object Obj);
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 Turn(uint32 CreatureID, Object Obj);
-extern void Use(uint32 CreatureID, Object Obj1, Object Object2, uint8 Info);
+
+// moveuse.cc
+extern void UseContainer(uint32 CreatureID, Object Con, uint8 ContainerNr);
+extern void UseChest(uint32 CreatureID, Object Chest);
+extern void UseLiquidContainer(uint32 CreatureID, Object Obj, Object Dest);
+extern void UseFood(uint32 CreatureID, Object Obj);
+extern void UseTextObject(uint32 CreatureID, Object Obj);
+extern void UseAnnouncer(uint32 CreatureID, Object Obj);
+extern void UseKeyDoor(uint32 CreatureID, Object Key, Object Door);
+extern void UseNameDoor(uint32 CreatureID, Object Door);
+extern void UseLevelDoor(uint32 CreatureID, Object Door);
+extern void UseQuestDoor(uint32 CreatureID, Object Door);
+extern void UseWeapon(uint32 CreatureID, Object Weapon, Object Target);
+extern void UseChangeObject(uint32 CreatureID, Object Obj);
+extern void UseObject(uint32 CreatureID, Object Obj);
+extern void UseObjects(uint32 CreatureID, Object Obj1, Object Obj2);
extern void MovementEvent(Object Obj, Object Start, Object Dest);
extern void CollisionEvent(Object Obj, Object Dest);
extern void SeparationEvent(Object Obj, Object Start);