diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-15 17:35:06 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-15 17:35:06 -0300 |
| commit | 3cc587ab8df80d42d9dab1a73a37701f565a3499 (patch) | |
| tree | ea10cae94a9ef7a3c9b4080746a9697287e8991b | |
| parent | 33464579f6b8b079597617593d2bb733e982db8f (diff) | |
| download | game-3cc587ab8df80d42d9dab1a73a37701f565a3499.tar.gz game-3cc587ab8df80d42d9dab1a73a37701f565a3499.zip | |
more work on `operate.cc`
| -rw-r--r-- | reference/game.c | 1987 | ||||
| -rw-r--r-- | reference/types.hh | 41 | ||||
| -rw-r--r-- | src/connection.hh | 2 | ||||
| -rw-r--r-- | src/containers.hh | 37 | ||||
| -rw-r--r-- | src/cr.hh | 3 | ||||
| -rw-r--r-- | src/crmain.cc | 23 | ||||
| -rw-r--r-- | src/crplayer.cc | 1 | ||||
| -rw-r--r-- | src/info.hh | 1 | ||||
| -rw-r--r-- | src/main.cc | 3 | ||||
| -rw-r--r-- | src/objects.hh | 11 | ||||
| -rw-r--r-- | src/operate.cc | 1025 | ||||
| -rw-r--r-- | src/operate.hh | 96 | ||||
| -rw-r--r-- | src/stubs.hh | 38 |
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. @@ -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); |
