diff --git a/reference/game.c b/reference/game.c index d430658..bb0c72f 100644 --- a/reference/game.c +++ b/reference/game.c @@ -12325,1813 +12325,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -char * GetName(Object *Obj) - -{ - bool bVar1; - char *Help; - TCreature *pTVar2; - ulong uVar3; - char *pcVar4; - Object local_6c [4]; - char local_5c [4]; - char ObjectName [50]; - - local_5c[0] = '\0'; - Object::getObjectType(local_6c); - if (local_6c[0].ObjectID == 99) { - local_6c[0] = (Object)Obj->ObjectID; - pTVar2 = GetCreature(local_6c); - if (pTVar2 == (TCreature *)0x0) { - uVar3 = Object::getCreatureID(Obj); - error("GetName: Kreatur %d existiert nicht.\n",uVar3); - } - else { - snprintf(local_5c,0x32,"%s",pTVar2->Name); - } - } - else { - Object::getObjectType(local_6c); - pcVar4 = ObjectType::getName((ObjectType *)local_6c); - if (pcVar4 != (char *)0x0) { - strcpy(local_5c,pcVar4); - } - Object::getObjectType(local_6c); - bVar1 = ObjectType::getFlag((ObjectType *)local_6c,LIQUIDCONTAINER); - if ((bVar1) && (uVar3 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE), uVar3 != 0)) { - strcat(local_5c," of "); - uVar3 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE); - pcVar4 = GetLiquidName(uVar3); - strcat(local_5c,pcVar4); - } - Object::getObjectType(local_6c); - bVar1 = ObjectType::getFlag((ObjectType *)local_6c,LIQUIDPOOL); - if ((bVar1) && (uVar3 = Object::getAttribute(Obj,POOLLIQUIDTYPE), uVar3 != 0)) { - strcat(local_5c," of "); - uVar3 = Object::getAttribute(Obj,POOLLIQUIDTYPE); - pcVar4 = GetLiquidName(uVar3); - strcat(local_5c,pcVar4); - } - } - Object::getObjectType(local_6c); - bVar1 = ObjectType::getFlag((ObjectType *)local_6c,CUMULATIVE); - if (bVar1) { - uVar3 = Object::getAttribute(Obj,AMOUNT); - } - else { - uVar3 = 1; - } - pcVar4 = Plural(local_5c,uVar3); - return pcVar4; -} - - - -char * GetInfo(Object *Obj) - -{ - bool bVar1; - char *pcVar2; - Object local_1c [4]; - - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(local_1c); - pcVar2 = ObjectType::getDescription((ObjectType *)local_1c); - } - else { - error(&DAT_080f6c00); - pcVar2 = (char *)0x0; - } - return pcVar2; -} - - - -int GetWeight(Object *Obj,int Count) - -{ - bool bVar1; - ulong uVar2; - int Weight; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,TAKE); - if (bVar1) { - Object::getObjectType(local_2c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_2c,WEIGHT); - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CUMULATIVE); - if (!bVar1) { - return uVar2; - } - if (Count == -1) { - Count = Object::getAttribute(Obj,AMOUNT); - } - return uVar2 * Count; - } - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0xb58) { - return 0x4c2c; - } - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0xd82) { - return 50000; - } - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0xdb6) { - return 0x5910; - } - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0x10d7) { - return 80000; - } - Object::getObjectType(local_2c); - error("GetWeight: Objekttyp %d ist nicht nehmbar.\n",local_2c[0].ObjectID); - } - else { - error(&DAT_080f6c40); - } - return 0; -} - - - -int GetRowWeight(Object *Obj) - -{ - bool bVar1; - int iVar2; - int iVar3; - int Weight_1; - int local_50; - int Weight; - Object local_3c [4]; - Object local_2c [7]; - - local_3c[0] = (Object)Obj->ObjectID; - local_50 = 0; - if (local_3c[0].ObjectID != NONE.ObjectID) { - local_50 = 0; - if (local_3c[0].ObjectID != NONE.ObjectID) { - do { - local_2c[0].ObjectID = local_3c[0].ObjectID; - iVar2 = GetWeight(local_2c,-1); - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { -LAB_0806e37e: - GetFirstContainerObject(local_2c); - iVar3 = GetRowWeight(local_2c); - iVar2 = iVar2 + iVar3; - } - else { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST); - if (bVar1) goto LAB_0806e37e; - } - local_50 = local_50 + iVar2; - Object::getNextObject(local_3c); - Obj->ObjectID = (ulong)local_3c[0]; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - } - return local_50; -} - - - -int GetCompleteWeight(Object *Obj) - -{ - bool bVar1; - int iVar2; - int iVar3; - int Weight; - Object local_2c [7]; - - local_2c[0] = (Object)Obj->ObjectID; - iVar2 = GetWeight(local_2c,-1); - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (!bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST); - if (!bVar1) { - return iVar2; - } - } - GetFirstContainerObject(local_2c); - iVar3 = GetRowWeight(local_2c); - return iVar2 + iVar3; -} - - - -ulong GetObjectCreatureID(Object *Obj) - -{ - bool bVar1; - ulong uVar2; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - if (bVar1) { - while( true ) { - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 99) break; - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0) goto LAB_0806e4f4; - Object::getContainer(local_3c); - local_2c[0].ObjectID = local_3c[0].ObjectID; - Obj->ObjectID = (ulong)local_3c[0]; - } - uVar2 = Object::getCreatureID(Obj); - } - else { - error(&DAT_080f6cc0); -LAB_0806e4f4: - uVar2 = 0; - } - return uVar2; -} - - - -int GetObjectBodyPosition(Object *Obj) - -{ - bool bVar1; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - if (bVar1) { - while( true ) { - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0) break; - Object::getObjectType(local_2c); - bVar1 = false; - if ((0 < (int)local_2c[0].ObjectID) && ((int)local_2c[0].ObjectID < 0xb)) { - bVar1 = true; - } - if (bVar1) break; - Object::getContainer(local_3c); - local_2c[0].ObjectID = local_3c[0].ObjectID; - Obj->ObjectID = (ulong)local_3c[0]; - } - Object::getObjectType(local_3c); - } - else { - error(&DAT_080f6d00); - local_3c[0].ObjectID = 0; - } - return local_3c[0].ObjectID; -} - - - -int GetObjectRNum(Object *Obj) - -{ - bool bVar1; - int Count; - int iVar2; - char *Text; - Object local_3c [4]; - Object local_2c; - Object Search; - - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(&local_2c); - if (local_2c.ObjectID == 0) { - Text = "GetObjectRNum: Objekt ist MapContainer.\n"; - } - else { - iVar2 = 0; - Object::getContainer(local_3c); - GetFirstContainerObject(&local_2c); - local_3c[0] = (Object)Obj->ObjectID; - if (local_2c.ObjectID == local_3c[0].ObjectID) { - return 0; - } - while (local_2c.ObjectID != NONE.ObjectID) { - iVar2 = iVar2 + 1; - Object::getNextObject(local_3c); - local_2c.ObjectID = local_3c[0].ObjectID; - bVar1 = local_3c[0].ObjectID == Obj->ObjectID; - local_3c[0].ObjectID = Obj->ObjectID; - if (bVar1) { - return iVar2; - } - } - Text = "GetObjectRNum: Objekt liegt nicht in Container\n"; - } - } - else { - Text = &DAT_080f6d40; - } - error(Text); - return 0; -} - - - -bool ObjectInRange(ulong CreatureID,Object *Obj,int Range) - -{ - bool bVar1; - TCreature *pTVar2; - uint uVar3; - TCreature *cr; - int local_38; - int x; - int y; - int z; - - pTVar2 = GetCreature(CreatureID); - if (pTVar2 == (TCreature *)0x0) { - error(&DAT_080f6e40,CreatureID); - } - else { - bVar1 = Object::exists(Obj); - if (bVar1) { - z = Obj->ObjectID; - GetObjectCoordinates((Object *)&z,&local_38,&x,&y); - uVar3 = pTVar2->posx - local_38; - if (0x7fffffff < uVar3) { - uVar3 = -uVar3; - } - if (Range < (int)uVar3) { - return false; - } - uVar3 = pTVar2->posy - x; - if (0x7fffffff < uVar3) { - uVar3 = -uVar3; - } - if (Range < (int)uVar3) { - return false; - } - if (pTVar2->posz != y) { - return false; - } - return true; - } - error(&DAT_080f6e00); - } - return false; -} - - - -// WARNING: Type propagation algorithm not settling - -bool ObjectAccessible(ulong CreatureID,Object *Obj,int Range) - -{ - bool bVar1; - bool bVar2; - TCreature *pTVar3; - ulong uVar4; - char *Text; - TCreature *cr; - int local_38; - int x; - int y; - int z; - - bVar1 = Object::exists(Obj); - if (!bVar1) { - Text = &DAT_080f6e80; -LAB_0806e7be: - error(Text); - return false; - } - Object::getObjectType((Object *)&z); - if (z == 99) { - uVar4 = 0; - } - else { - z = Obj->ObjectID; - uVar4 = GetObjectCreatureID((Object *)&z); - } - if (uVar4 == CreatureID) { - return true; - } - if (uVar4 != 0) { - return false; - } - Object::getObjectType((Object *)&z); - bVar1 = ObjectType::getFlag((ObjectType *)&z,HANG); - if (bVar1) { - z = Obj->ObjectID; - GetObjectCoordinates((Object *)&z,&local_38,&x,&y); - bVar1 = false; - bVar2 = CoordinateFlag(); - if ((bVar2) || (bVar2 = CoordinateFlag(), bVar2)) { - bVar1 = true; - } - if (bVar1) { - pTVar3 = GetCreature(CreatureID); - if (pTVar3 == (TCreature *)0x0) { - Text = "ObjectAccessible: Kreatur existiert nicht.\n"; - goto LAB_0806e7be; - } - bVar1 = CoordinateFlag(); - if (bVar1) { - bVar1 = false; - if ((x <= pTVar3->posy) && (pTVar3->posy <= Range + x)) { - bVar1 = true; - } - if (!bVar1) { - return false; - } - if (pTVar3->posx < local_38 - Range || Range + local_38 < pTVar3->posx) { - return false; - } - } - bVar1 = CoordinateFlag(); - if (bVar1) { - bVar1 = false; - if ((local_38 <= pTVar3->posx) && (pTVar3->posx <= Range + local_38)) { - bVar1 = true; - } - if (!bVar1) { - return false; - } - bVar1 = false; - if ((x - Range <= pTVar3->posy) && (pTVar3->posy <= x + Range)) { - bVar1 = true; - } - if (!bVar1) { - return false; - } - } - } - } - z = Obj->ObjectID; - bVar1 = ObjectInRange(CreatureID,(Object *)&z,Range); - return bVar1; -} - - - -char * GetLiquidName(ulong nr) - -{ - char *pcVar1; - - switch(nr) { - case 0: - pcVar1 = "nothing"; - break; - case 1: - pcVar1 = "water"; - break; - case 2: - pcVar1 = "wine"; - break; - case 3: - pcVar1 = "beer"; - break; - case 4: - pcVar1 = "mud"; - break; - case 5: - pcVar1 = "blood"; - break; - case 6: - pcVar1 = "slime"; - break; - case 7: - pcVar1 = "oil"; - break; - case 8: - pcVar1 = "urine"; - break; - case 9: - pcVar1 = "milk"; - break; - case 10: - pcVar1 = "manafluid"; - break; - case 0xb: - pcVar1 = "lifefluid"; - break; - case 0xc: - pcVar1 = "lemonade"; - break; - default: - error(&DAT_080f6f00,nr); - pcVar1 = "unknown"; - } - return pcVar1; -} - - - -uchar GetLiquidColor(ulong nr) - -{ - uchar uVar1; - - switch(nr) { - case 1: - uVar1 = '\x01'; - break; - case 2: - case 10: - uVar1 = '\a'; - break; - case 3: - case 4: - case 7: - uVar1 = '\x03'; - break; - case 5: - case 0xb: - uVar1 = '\x02'; - break; - case 6: - uVar1 = '\x04'; - break; - case 8: - case 0xc: - uVar1 = '\x05'; - break; - case 9: - uVar1 = '\x06'; - break; - default: - error(&DAT_080f6f40,nr); - case 0: - uVar1 = '\0'; - } - return uVar1; -} - - - -int ObjectDistance(Object *Obj1,Object *Obj2) - -{ - bool bVar1; - int iVar2; - int *piVar3; - int local_4c; - int local_48; - int local_44; - int x2; - int y2; - int z2; - int x1; - int y1; - int z1; - - bVar1 = Object::exists(Obj1); - if ((bVar1) && (bVar1 = Object::exists(Obj2), bVar1)) { - z1 = Obj1->ObjectID; - GetObjectCoordinates((Object *)&z1,&z2,&x1,&y1); - z1 = Obj2->ObjectID; - GetObjectCoordinates((Object *)&z1,&local_44,&x2,&y2); - if (y1 == y2) { - local_44 = z2 - local_44; - local_48 = -local_44; - if (-1 < local_44) { - local_48 = local_44; - } - iVar2 = x1 - x2; - local_4c = -iVar2; - if (-1 < iVar2) { - local_4c = iVar2; - } - piVar3 = &local_4c; - if (local_4c <= local_48) { - piVar3 = &local_48; - } - return *piVar3; - } - } - else { - error(&DAT_080f6f80); - } - return 0x7fffffff; -} - - - -Object GetBodyContainer(ulong CreatureID,int Position) - -{ - bool bVar1; - TCreature *Window; - TCreature *cr; - int in_stack_0000000c; - char *Text; - Object local_3c [4]; - ulong local_2c; - - if (((in_stack_0000000c < 1) || (in_stack_0000000c - 0xbU < 0x35)) || (0x4f < in_stack_0000000c) - ) { - Text = &DAT_080f6fc0; - } - else { - Window = GetCreature(Position); - if (Window != (TCreature *)0x0) { - local_2c = (Window->CrObject).ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - if (local_2c == NONE.ObjectID) { - *(ulong *)CreatureID = NONE.ObjectID; - return (Object)CreatureID; - } - if (in_stack_0000000c < 0x40) { - local_3c[0].ObjectID = (Window->CrObject).ObjectID; - bVar1 = Object::exists(local_3c); - if (!bVar1) { - error("GetBodyContainer: Kreatur-Objekt von %s existiert nicht (Pos %d).\n", - Window->Name); - } - local_3c[0].ObjectID = (Window->CrObject).ObjectID; - GetContainerObject((Object *)CreatureID,(int)local_3c); - return (Object)CreatureID; - } - if (Window->Type == PLAYER) { - TPlayer::GetOpenContainer((TPlayer *)CreatureID,(int)Window); - return (Object)CreatureID; - } - error("GetBodyContainer: Nur Spieler haben offene Container.\n"); - goto LAB_0806ec66; - } - Text = "GetBodyContainer: Kreatur %d existiert nicht.\n"; - } - error(Text); -LAB_0806ec66: - *(ulong *)CreatureID = NONE.ObjectID; - return (Object)CreatureID; -} - - - -Object GetBodyObject(ulong CreatureID,int Position) - -{ - int in_stack_0000000c; - ulong local_1c; - Object BodyCon; - - if (in_stack_0000000c - 1U < 10) { - GetBodyContainer((ulong)&local_1c,Position); - if (local_1c != NONE.ObjectID) { - GetFirstContainerObject((Object *)CreatureID); - return (Object)CreatureID; - } - } - else { - error(&DAT_080f70e0); - } - *(ulong *)CreatureID = NONE.ObjectID; - return (Object)CreatureID; -} - - - -Object GetTopObject(int x,int y,int z,bool Move) - -{ - bool bVar1; - char in_stack_00000014; - Object OStack_4c; - bool Move_local; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - GetFirstObject(); - if (local_2c != NONE.ObjectID) { - do { - OStack_4c.ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getNextObject(&stack0xffffffb4); - local_3c[0].ObjectID = NONE.ObjectID; - if (OStack_4c.ObjectID == NONE.ObjectID) { -LAB_0806ef27: - *(ulong *)x = local_2c; - return (Object)x; - } - Object::getObjectType(&stack0xffffffb4); - bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,BANK); - if (!bVar1) { - Object::getObjectType(&stack0xffffffb4); - bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,CLIP); - if (!bVar1) { - Object::getObjectType(&stack0xffffffb4); - bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,BOTTOM); - if (!bVar1) { - Object::getObjectType(&stack0xffffffb4); - bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,TOP); - if ((!bVar1) && - ((in_stack_00000014 == '\0' || - (Object::getObjectType(&stack0xffffffb4), OStack_4c.ObjectID != 99)))) - goto LAB_0806ef27; - } - } - } - Object::getNextObject(local_3c); - local_2c = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - *(ulong *)x = NONE.ObjectID; - return (Object)x; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -Object GetContainer(void) - -{ - ulong in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - - if (in_stack_0000000c == 0xffff) { - GetBodyContainer(in_stack_00000004,in_stack_00000008); - } - else { - GetMapContainer(in_stack_00000004,in_stack_0000000c,in_stack_00000010); - } - return (Object)in_stack_00000004; -} - - - -Object GetObject(ulong CreatureID,int x,int y,int z,int RNum,ObjectType *Type) - -{ - ulong uVar1; - Object OVar2; - TCreature *Window; - TCreature *cr; - Object *pOVar3; - bool bVar4; - ulong *in_stack_0000001c; - Object local_6c; - ObjectType Disguise; - Object local_5c [4]; - ulong local_4c; - _func_int_varargs **local_3c; - Object Con; - Object local_2c; - Object Obj; - - local_2c.ObjectID = 0; - if (y == 0xffff) { - OVar2.ObjectID = NONE.ObjectID; - if (z == 0) goto LAB_0806f160; - if ((z - 0xbU < 0x35) || (0x4f < z)) { - error(&DAT_080f7120,0xffff,z,RNum,Type,*in_stack_0000001c); - OVar2 = NONE; - goto LAB_0806f160; - } - if (z < 0x40) { - GetBodyObject((ulong)local_5c,x); - goto LAB_0806f1ca; - } - Window = GetCreature(x); - if (Window == (TCreature *)0x0) { - error("GetObject: Kreatur %d existiert nicht.\n",x); - OVar2 = NONE; - goto LAB_0806f0e4; - } - if (Window->Type != PLAYER) { - error("GetObject: Nur Spieler haben offene Container.\n"); - OVar2 = NONE; - goto LAB_0806f160; - } - TPlayer::GetOpenContainer((TPlayer *)&local_3c,(int)Window); - local_4c = NONE.ObjectID; - OVar2 = NONE; - if (local_3c == (_func_int_varargs **)NONE.ObjectID) goto LAB_0806f0e4; - local_6c.ObjectID = (ulong)local_3c; - GetContainerObject(local_5c,(int)&local_6c); - local_2c.ObjectID = local_5c[0].ObjectID; - } - else if (Type == (ObjectType *)0xffffffff) { - GetTopObject((int)local_5c,y,z,SUB41(RNum,0)); -LAB_0806f1ca: - local_2c.ObjectID = local_5c[0].ObjectID; - } - else { - GetFirstObject(); - bVar4 = local_5c[0].ObjectID != NONE.ObjectID; - local_2c.ObjectID = local_5c[0].ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - if (bVar4) { - do { - local_6c.ObjectID = NONE.ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(&local_6c); - bVar4 = ObjectType::getFlag((ObjectType *)&local_6c,DISGUISE); - if (bVar4) { - Object::getObjectType(local_5c); - uVar1 = ObjectType::getAttribute((ObjectType *)local_5c,DISGUISETARGET); - ObjectType::setTypeID((ObjectType *)&local_6c,uVar1); - uVar1 = *in_stack_0000001c; - } - else { - Object::getObjectType(&local_6c); - uVar1 = *in_stack_0000001c; - } - ObjectType::setTypeID((ObjectType *)local_5c,uVar1); - if (local_6c.ObjectID == local_5c[0].ObjectID) break; - Object::getNextObject(local_5c); - local_2c.ObjectID = local_5c[0].ObjectID; - bVar4 = local_5c[0].ObjectID != NONE.ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - } while (bVar4); - } - } - if (local_2c.ObjectID == NONE.ObjectID) { - *(ulong *)CreatureID = NONE.ObjectID; - return (Object)CreatureID; - } - local_6c.ObjectID = NONE.ObjectID; - ObjectType::setTypeID((ObjectType *)&local_6c,0); - OVar2.ObjectID = local_2c.ObjectID; - if (*in_stack_0000001c == local_6c.ObjectID) { -LAB_0806f0e4: - *(ulong *)CreatureID = OVar2.ObjectID; - return (Object)CreatureID; - } - Object::getObjectType(&local_6c); - bVar4 = ObjectType::getFlag((ObjectType *)&local_6c,DISGUISE); - if (bVar4) { - Object::getObjectType(local_5c); - uVar1 = ObjectType::getAttribute((ObjectType *)local_5c,DISGUISETARGET); - ObjectType::setTypeID((ObjectType *)&local_6c,uVar1); - } - else { - Object::getObjectType(&local_6c); - } - ObjectType::setTypeID((ObjectType *)local_5c,*in_stack_0000001c); - pOVar3 = &NONE; - if (local_6c.ObjectID == local_5c[0].ObjectID) { - pOVar3 = &local_2c; - } - OVar2.ObjectID = pOVar3->ObjectID; -LAB_0806f160: - *(ulong *)CreatureID = OVar2.ObjectID; - return (Object)CreatureID; -} - - - -Object __regparm1 GetRowObject(Object *Obj,ObjectType *Type,ulong Value,bool Recurse) - -{ - bool bVar1; - ulong uVar2; - undefined3 in_stack_0000000d; - ulong in_stack_00000010; - char in_stack_00000014; - Object OStack_5c; - bool Recurse_local; - Object local_4c [4]; - Object local_3c; - Object Help; - Object local_2c [7]; - - local_2c[0].ObjectID = NONE.ObjectID; - local_3c.ObjectID = NONE.ObjectID; - if (*(ulong *)Value != NONE.ObjectID) { - do { - NONE.ObjectID = local_2c[0].ObjectID; - local_3c.ObjectID = local_2c[0].ObjectID; - if (in_stack_00000014 != '\0') { - Object::getObjectType(&local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER); - if (bVar1) { - ObjectType::setTypeID((ObjectType *)local_2c,_Recurse->TypeID); - // WARNING: Load size is inaccurate - OStack_5c.ObjectID = *Value; - GetFirstContainerObject(local_4c); - GetRowObject(local_2c,(ObjectType *)&local_3c,(ulong)local_4c,SUB41(local_2c,0)) - ; - OStack_5c = (Object)NONE.ObjectID; - local_4c[0].ObjectID = OStack_5c.ObjectID; - if (local_3c.ObjectID != NONE.ObjectID) break; - } - } - Object::getObjectType(&stack0xffffffa4); - ObjectType::setTypeID((ObjectType *)local_4c,_Recurse->TypeID); - ObjectType::setTypeID((ObjectType *)&local_3c,local_4c[0].ObjectID); - if (((OStack_5c.ObjectID == local_3c.ObjectID) && - ((bVar1 = ObjectType::getFlag(_Recurse,LIQUIDCONTAINER), !bVar1 || - (uVar2 = Object::getAttribute((Object *)Value,CONTAINERLIQUIDTYPE), - uVar2 == in_stack_00000010)))) && - ((bVar1 = ObjectType::getFlag(_Recurse,KEY), !bVar1 || - (uVar2 = Object::getAttribute((Object *)Value,KEYNUMBER), uVar2 == in_stack_00000010 - )))) { - Type->TypeID = *(int *)Value; - return (Object)(ulong)Type; - } - Object::getNextObject(local_4c); - OStack_5c.ObjectID = local_4c[0].ObjectID; - *(ulong *)Value = local_4c[0].ObjectID; - local_2c[0] = (Object)NONE.ObjectID; - local_3c = NONE; - } while (local_4c[0].ObjectID != NONE.ObjectID); - } - Type->TypeID = local_3c.ObjectID; - return (Object)(ulong)Type; -} - - - -Object GetInventoryObject(ulong CreatureID,ObjectType *Type,ulong Value) - -{ - bool bVar1; - bool bVar2; - TCreature *pTVar3; - Object OVar4; - TCreature *cr; - Object *in_stack_00000010; - Object local_8c; - Object BodyCon_1; - Object local_7c; - Object Obj_1; - Object local_6c [4]; - Object local_5c; - Object Obj; - Object local_4c; - Object BodyObj; - Object local_2c; - Object BodyCon; - - pTVar3 = GetCreature((ulong)Type); - if (pTVar3 == (TCreature *)0x0) { - error("GetInventoryObject: Kreatur %d existiert nicht.\n",Type); - *(ulong *)CreatureID = NONE.ObjectID; - } - else { - GetFirstContainerObject(&local_2c); - if (local_2c.ObjectID != NONE.ObjectID) { - do { - local_4c.ObjectID = NONE.ObjectID; - GetFirstContainerObject(&local_4c); - bVar1 = false; - local_5c.ObjectID = NONE.ObjectID; - if (local_4c.ObjectID != NONE.ObjectID) { - Object::getObjectType(&local_5c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_5c,CONTAINER); - if (bVar2) { - bVar1 = true; - } - } - if (bVar1) { - ObjectType::setTypeID((ObjectType *)local_6c,*(int *)Value); - local_8c.ObjectID = local_4c.ObjectID; - GetFirstContainerObject(&local_7c); - GetRowObject(&local_7c,(ObjectType *)&local_5c,(ulong)&local_7c, - SUB41(local_6c,0)); - local_8c.ObjectID = NONE.ObjectID; - local_7c.ObjectID = NONE.ObjectID; - OVar4.ObjectID = local_5c.ObjectID; - if (local_5c.ObjectID != NONE.ObjectID) goto LAB_0806f6c8; - } - Object::getNextObject(&local_7c); - local_8c.ObjectID = local_7c.ObjectID; - local_2c.ObjectID = local_7c.ObjectID; - } while (local_7c.ObjectID != NONE.ObjectID); - } - local_7c.ObjectID = (pTVar3->CrObject).ObjectID; - local_4c.ObjectID = NONE.ObjectID; - GetFirstContainerObject(&local_8c); - OVar4 = NONE; - if (local_8c.ObjectID != NONE.ObjectID) { - do { - local_7c.ObjectID = NONE.ObjectID; - local_6c[0].ObjectID = NONE.ObjectID; - ObjectType::setTypeID((ObjectType *)local_6c,*(int *)Value); - local_4c.ObjectID = local_8c.ObjectID; - GetFirstContainerObject(&local_5c); - GetRowObject(in_stack_00000010,(ObjectType *)&local_7c,(ulong)&local_5c, - SUB41(local_6c,0)); - local_6c[0].ObjectID = NONE.ObjectID; - local_5c.ObjectID = NONE.ObjectID; - OVar4.ObjectID = local_7c.ObjectID; - if (local_7c.ObjectID != NONE.ObjectID) break; - Object::getNextObject(local_6c); - local_8c.ObjectID = local_6c[0].ObjectID; - OVar4 = NONE; - } while (local_6c[0].ObjectID != NONE.ObjectID); - } -LAB_0806f6c8: - *(ulong *)CreatureID = OVar4.ObjectID; - } - return (Object)CreatureID; -} - - - -int CountObjectsInContainer(Object *Con) - -{ - bool bVar1; - int iVar2; - int Count; - Object local_3c [4]; - Object local_2c; - Object Search; - - bVar1 = Object::exists(Con); - if (bVar1) { - local_3c[0] = (Object)Con->ObjectID; - iVar2 = 0; - GetFirstContainerObject(&local_2c); - if (local_2c.ObjectID != NONE.ObjectID) { - do { - iVar2 = iVar2 + 1; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getNextObject(local_3c); - local_2c.ObjectID = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - } - else { - error("CountObjectsInContainer: Container existiert nicht.\n"); - iVar2 = 0; - } - return iVar2; -} - - - -int CountObjects(Object *Obj) - -{ - bool bVar1; - int iVar2; - int iVar3; - int count; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - iVar3 = 0; - if (bVar1) { - iVar3 = 1; - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { - local_4c[0] = (Object)Obj->ObjectID; - GetFirstContainerObject(local_3c); - Obj->ObjectID = (ulong)local_3c[0]; - local_2c[0].ObjectID = local_3c[0].ObjectID; - if (local_3c[0].ObjectID != NONE.ObjectID) { - do { - local_4c[0] = (Object)Obj->ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - iVar2 = CountObjects(local_4c); - iVar3 = iVar3 + iVar2; - Object::getNextObject(local_3c); - Obj->ObjectID = (ulong)local_3c[0]; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - } - } - return iVar3; -} - - - -int CountObjects(Object *Obj,ObjectType *Type,ulong Value) - -{ - bool bVar1; - ulong uVar2; - int iVar3; - int local_50; - int count; - Object local_3c [4]; - Object local_2c [7]; - - local_50 = 0; - bVar1 = Object::exists(Obj); - iVar3 = 0; - if ((bVar1) && (iVar3 = local_50, Obj->ObjectID != NONE.ObjectID)) { - do { - local_3c[0].ObjectID = NONE.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER); - if (bVar1) { - ObjectType::setTypeID((ObjectType *)local_3c,Type->TypeID); - count = Obj->ObjectID; - GetFirstContainerObject(local_2c); - iVar3 = CountObjects(local_2c,(ObjectType *)local_3c,0); - local_50 = local_50 + iVar3; - } - Object::getObjectType((Object *)&count); - ObjectType::setTypeID((ObjectType *)local_3c,Type->TypeID); - ObjectType::setTypeID((ObjectType *)local_2c,local_3c[0].ObjectID); - if (((count == local_2c[0].ObjectID) && - ((bVar1 = ObjectType::getFlag(Type,LIQUIDCONTAINER), !bVar1 || - (uVar2 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE), uVar2 == Value)))) && - ((bVar1 = ObjectType::getFlag(Type,KEY), !bVar1 || - (uVar2 = Object::getAttribute(Obj,KEYNUMBER), uVar2 == Value)))) { - Object::getObjectType((Object *)&count); - bVar1 = ObjectType::getFlag((ObjectType *)&count,CUMULATIVE); - if (bVar1) { - uVar2 = Object::getAttribute(Obj,AMOUNT); - local_50 = uVar2 + local_50; - } - else { - local_50 = local_50 + 1; - } - } - Object::getNextObject(local_3c); - count = local_3c[0].ObjectID; - Obj->ObjectID = (ulong)local_3c[0]; - iVar3 = local_50; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - return iVar3; -} - - - -int CountInventoryObjects(ulong CreatureID,ObjectType *Type,ulong Value) - -{ - TCreature *pTVar1; - int iVar2; - TCreature *cr; - ObjectType local_3c [4]; - Object local_2c [7]; - - pTVar1 = GetCreature(CreatureID); - if (pTVar1 == (TCreature *)0x0) { - error("CountInventoryObjects: Kreatur %d existiert nicht; Objekttyp %d.\n",CreatureID, - Type->TypeID); - } - else { - local_2c[0].ObjectID = (pTVar1->CrObject).ObjectID; - local_3c[0].TypeID = NONE.ObjectID; - if (local_2c[0].ObjectID != NONE.ObjectID) { - ObjectType::setTypeID(local_3c,Type->TypeID); - GetFirstContainerObject(local_2c); - iVar2 = CountObjects(local_2c,local_3c,Value); - return iVar2; - } - error("CountInventoryObjects: Kreatur %s hat kein Kreatur-Objekt.\n",pTVar1->Name); - } - return 0; -} - - - -int CountMoney(Object *Obj) - -{ - bool bVar1; - int iVar2; - ulong uVar3; - int local_40; - int count; - Object local_2c [7]; - - local_40 = 0; - bVar1 = Object::exists(Obj); - iVar2 = 0; - if ((bVar1) && (iVar2 = local_40, Obj->ObjectID != NONE.ObjectID)) { - do { - count = NONE.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - Object::getObjectType((Object *)&count); - GetSpecialObject((SPECIALMEANING)local_2c); - if (count == local_2c[0].ObjectID) { - uVar3 = Object::getAttribute(Obj,AMOUNT); - local_40 = local_40 + uVar3; - } - Object::getObjectType((Object *)&count); - GetSpecialObject((SPECIALMEANING)local_2c); - if (count == local_2c[0].ObjectID) { - uVar3 = Object::getAttribute(Obj,AMOUNT); - local_40 = local_40 + uVar3 * 100; - } - Object::getObjectType((Object *)&count); - GetSpecialObject((SPECIALMEANING)local_2c); - if (count == local_2c[0].ObjectID) { - uVar3 = Object::getAttribute(Obj,AMOUNT); - local_40 = local_40 + uVar3 * 10000; - } - Object::getObjectType((Object *)&count); - bVar1 = ObjectType::getFlag((ObjectType *)&count,CONTAINER); - if (bVar1) { - local_2c[0] = (Object)Obj->ObjectID; - GetFirstContainerObject((Object *)&count); - iVar2 = CountMoney((Object *)&count); - local_40 = local_40 + iVar2; - } - Object::getNextObject(local_2c); - Obj->ObjectID = (ulong)local_2c[0]; - iVar2 = local_40; - } while (local_2c[0].ObjectID != NONE.ObjectID); - } - return iVar2; -} - - - -int CountInventoryMoney(ulong CreatureID) - -{ - TCreature *pTVar1; - int iVar2; - TCreature *cr; - char *Text; - Object local_2c [4]; - ulong local_1c; - - pTVar1 = GetCreature(CreatureID); - if (pTVar1 == (TCreature *)0x0) { - Text = "CountInventoryMoney: Kreatur %d existiert nicht.\n"; - } - else { - local_1c = (pTVar1->CrObject).ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - if (local_1c != NONE.ObjectID) { - local_1c = (pTVar1->CrObject).ObjectID; - GetFirstContainerObject(local_2c); - iVar2 = CountMoney(local_2c); - return iVar2; - } - Text = "CountInventoryMoney: Kreatur %s hat kein Kreatur-Objekt.\n"; - CreatureID = (ulong)pTVar1->Name; - } - error(Text,CreatureID); - return 0; -} - - - -void CalculateChange(int Amount,int *Gold,int *Platinum,int *Crystal) - -{ - int iVar1; - int Rest; - int iVar2; - int iVar3; - int iVar4; - char *Text; - int iVar5; - int iVar6; - - iVar6 = *Crystal; - print(); - iVar5 = *Platinum; - iVar3 = *Crystal; - iVar4 = *Gold; - if (iVar3 * 10000 + iVar5 * 100 + iVar4 < Amount) { - Text = &DAT_080f7440; - } - else { - iVar1 = Amount / 10000; - iVar2 = Amount % 10000; - if (iVar5 * 100 + iVar4 < iVar2) { - *Crystal = iVar1 + 1; - *Platinum = (iVar2 + -10000) / 100; - *Gold = (iVar2 + -10000) % 100; - } - else { - if (iVar3 < iVar1) { - iVar2 = Amount + iVar3 * -10000; - } - else { - *Crystal = iVar1; - iVar4 = *Gold; - } - iVar5 = iVar2 / 100; - iVar3 = iVar2 % 100; - if (iVar4 < iVar3) { - *Platinum = iVar5 + 1; - *Gold = iVar3 + -100; - } - else if (*Platinum < iVar5) { - *Gold = iVar2 + *Platinum * -100; - } - else { - *Platinum = iVar5; - *Gold = iVar3; - } - } - print(); - iVar5 = *Platinum; - iVar3 = *Crystal; - iVar4 = *Gold; - if (iVar3 * 10000 + iVar5 * 100 + iVar4 == Amount) { - return; - } - Text = &DAT_080f73e0; - } - error(Text,iVar4,iVar5,iVar3,Amount,iVar6); - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -int GetHeight(void) - -{ - bool bVar1; - ulong uVar2; - int Height; - int iVar3; - Object local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - iVar3 = 0; - GetFirstObject(); - if (local_2c != NONE.ObjectID) { - do { - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(local_4c); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,HEIGHT); - if (bVar1) { - Object::getObjectType(local_4c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_4c,ELEVATION); - iVar3 = iVar3 + uVar2; - } - Object::getNextObject(local_3c); - local_2c = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - return iVar3; -} - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -bool FieldPossible(void) - -{ - bool bVar1; - bool bVar2; - int in_stack_00000010; - Object local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - GetFirstObject(); - bVar1 = false; - local_3c[0].ObjectID = NONE.ObjectID; - if (local_2c != NONE.ObjectID) { - Object::getObjectType(local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)local_4c,BANK); - if (bVar2) goto LAB_080701d5; - } - bVar1 = true; -LAB_080701d5: - bVar2 = false; - if (!bVar1) { - if (local_2c != NONE.ObjectID) { - do { - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(local_4c); - if (local_4c[0].ObjectID != 99) { - Object::getObjectType(local_4c); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,UNPASS); - if (bVar1) { - return false; - } - } - Object::getObjectType(local_4c); - if (local_4c[0].ObjectID != 99) { - Object::getObjectType(local_4c); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,UNLAY); - if (bVar1) { - return false; - } - } - if (in_stack_00000010 - 4U < 2) { - Object::getObjectType(local_4c); - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,UNPASS); - if (bVar1) { - return false; - } - } - Object::getNextObject(local_3c); - local_2c = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - bVar2 = true; - } - return bVar2; -} - - -bool SearchLoginField(int *x,int *y,int *z,int Distance,bool Player) - -{ - bool bVar1; - bool bVar2; - ushort HouseID_00; - ushort uVar3; - int Direction; - uint uVar4; - int iStack_60; - bool BankThere; - int dy; - int dx; - int Dist; - ushort HouseID; - Object OStack_4c; - bool Player_local; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - HouseID_00 = GetHouseID(*x,*y,*z); - bVar1 = SearchFreeField(x,y,z,Distance,HouseID_00,false); - if ((!bVar1) || ((Player && (bVar1 = IsNoLogoutField(), bVar1)))) { - dx = 0; - uVar4 = 4; - dy = 0; - iStack_60 = 0; - do { - GetFirstObject(); - bVar1 = false; - local_3c[0].ObjectID = NONE.ObjectID; - if (((local_2c != NONE.ObjectID) && ((!Player || (bVar2 = IsNoLogoutField(), !bVar2)))) - && ((bVar2 = IsHouse(dy + *x,iStack_60 + *y,*z), !bVar2 || - ((HouseID_00 != 0 && - (uVar3 = GetHouseID(dy + *x,iStack_60 + *y,*z), uVar3 == HouseID_00)))))) { - if (local_2c != NONE.ObjectID) { - do { - OStack_4c.ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(&stack0xffffffb4); - bVar2 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,BANK); - if (bVar2) { - bVar1 = true; - } - Object::getObjectType(&stack0xffffffb4); - if (OStack_4c.ObjectID == 99) goto LAB_08070740; - Object::getObjectType(&stack0xffffffb4); - bVar2 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,UNPASS); - if (bVar2) { - Object::getObjectType(&stack0xffffffb4); - bVar2 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,UNMOVE); - if (bVar2) goto LAB_08070740; - } - if (!Player) { - Object::getObjectType(&stack0xffffffb4); - bVar2 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,AVOID); - if (bVar2) { - Object::getObjectType(&stack0xffffffb4); - bVar2 = ObjectType::getFlag((ObjectType *)&stack0xffffffb4,UNMOVE); - if (bVar2) goto LAB_08070740; - } - } - Object::getNextObject(local_3c); - local_2c = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - OStack_4c.ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - if (bVar1) { - *x = *x + dy; - *y = *y + iStack_60; - goto LAB_0807063b; - } - } -LAB_08070740: - if (uVar4 == 2) { - dy = dy + -1; - if (dy + dx == 0) { - uVar4 = 3; - } - } - else if (uVar4 < 3) { - if ((uVar4 == 1) && (iStack_60 = iStack_60 + -1, iStack_60 + dx == 0)) { - uVar4 = 2; - } - } - else if (uVar4 == 3) { - iStack_60 = iStack_60 + 1; - if (iStack_60 == dx) { - uVar4 = 4; - } - } - else if ((uVar4 == 4) && (dy = dy + 1, dy == dx + 1)) { - uVar4 = 1; - dx = dy; - } - bVar1 = false; - } while (dx <= Distance); - } - else { -LAB_0807063b: - bVar1 = true; - } - return bVar1; -} - - - -bool SearchSpawnField(int *x,int *y,int *z,int Distance,bool Player) - -{ - bool bVar1; - bool bVar2; - bool bVar3; - bool bVar4; - bool bVar5; - bool bVar6; - ushort uVar7; - ushort uVar8; - int iVar9; - undefined4 *puVar10; - int iVar11; - int *piVar12; - long lVar13; - int NewTieBreaker; - int iVar14; - int iVar15; - int dy; - int iVar16; - int iVar17; - int dx; - int xmax; - int iVar18; - int local_b0; - int ddy; - int ddx; - bool LoginBad; - bool LoginPossible; - bool ExpansionPossible; - bool Found; - bool Expanded; - int Pass; - int TieBreaker; - int BestY; - int BestX; - ushort HouseID; - bool Minimize; - Object OStack_6c; - bool Player_local; - Object local_5c [4]; - ulong local_4c; - Object Obj; - undefined1 local_3c [4]; - matrix Map; - - xmax = Distance; - if (0x7fffffff < (uint)Distance) { - xmax = -Distance; - } - iVar16 = -xmax; - uVar7 = GetHouseID(*x,*y,*z); - iVar18 = iVar16; - matrix::matrix((matrix *)local_3c,iVar16,xmax,iVar16,xmax); - if (-xmax == xmax || iVar16 < xmax) { - do { - iVar17 = -xmax; - if (-xmax == xmax || iVar17 < xmax) { - do { - iVar9 = iVar17 - Map.xmin; - iVar14 = iVar16 - (int)local_3c; - if ((((iVar14 < 0) || (Map.ymin <= iVar14)) || (iVar9 < 0)) || (Map.dx <= iVar9) - ) { - // try { // try from 08070a0d to 08071018 has its CatchHandler @ 08071071 - error("matrix::operator(): Ungueltiger Index %d/%d.\n", - iVar14 + (int)local_3c,iVar9 + Map.xmin); - puVar10 = (undefined4 *)Map.dy; - } - else { - puVar10 = (undefined4 *)(Map.dy + (iVar14 + iVar9 * Map.ymin) * 4); - } - *puVar10 = 0x7fffffff; - iVar17 = iVar17 + 1; - } while (iVar17 <= xmax); - } - iVar16 = iVar16 + 1; - } while (iVar16 <= xmax); - } - if ((((int)local_3c < 1) && (-(int)local_3c < Map.ymin)) && - ((Map.xmin < 1 && (-Map.xmin < Map.dx)))) { - puVar10 = (undefined4 *)(Map.dy + (-Map.xmin * Map.ymin + -(int)local_3c) * 4); - } - else { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",0,0); - puVar10 = (undefined4 *)Map.dy; - } - *puVar10 = 0; - BestY = 0; - TieBreaker = 0; - Pass = -1; - _LoginPossible = 0; - while( true ) { - bVar1 = false; - iVar16 = -xmax; - bVar4 = false; - if (-xmax == xmax || iVar16 < xmax) { - do { - iVar17 = -xmax; - if (-xmax == xmax || iVar17 < xmax) { - do { - iVar9 = iVar17 - Map.xmin; - iVar14 = iVar16 - (int)local_3c; - if (((iVar14 < 0) || (Map.ymin <= iVar14)) || - ((iVar9 < 0 || (Map.dx <= iVar9)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n", - iVar14 + (int)local_3c,iVar9 + Map.xmin,iVar18); - piVar12 = (int *)Map.dy; - } - else { - piVar12 = (int *)(Map.dy + (iVar14 + iVar9 * Map.ymin) * 4); - } - if (((*piVar12 == _LoginPossible) && - ((bVar5 = IsHouse(*x + iVar16,*y + iVar17,*z), !bVar5 || - ((uVar7 != 0 && - (uVar8 = GetHouseID(*x + iVar16,*y + iVar17,*z), uVar8 == uVar7)))))) - && ((Player || (bVar5 = IsProtectionZone(), !bVar5)))) { - iVar18 = *z; - GetFirstObject(); - local_5c[0] = (Object)NONE.ObjectID; - if (local_4c != NONE.ObjectID) { - bVar5 = true; - bVar2 = true; - bVar3 = false; - if (local_4c != NONE.ObjectID) { - do { - OStack_6c.ObjectID = NONE.ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(&stack0xffffff94); - if (OStack_6c.ObjectID == 99) { - bVar2 = false; - } - Object::getObjectType(&stack0xffffff94); - bVar6 = ObjectType::getFlag((ObjectType *)&stack0xffffff94, - UNPASS); - if (bVar6) { - Object::getObjectType(&stack0xffffff94); - bVar6 = ObjectType::getFlag((ObjectType *) - &stack0xffffff94,UNMOVE); - if (bVar6) { - bVar5 = false; - bVar2 = false; - } - else { - bVar3 = true; - } - } - Object::getObjectType(&stack0xffffff94); - bVar6 = ObjectType::getFlag((ObjectType *)&stack0xffffff94, - AVOID); - if (bVar6) { - Object::getObjectType(&stack0xffffff94); - bVar6 = ObjectType::getFlag((ObjectType *) - &stack0xffffff94,UNMOVE); - bVar3 = bVar2; - if (bVar6) { - bVar5 = false; - bVar3 = false; - if ((bVar2) && (!Player)) { - bVar3 = true; - } - } - bVar2 = bVar3; - bVar3 = true; - } - Object::getNextObject(local_5c); - local_4c = local_5c[0].ObjectID; - } while (local_5c[0].ObjectID != NONE.ObjectID); - } - OStack_6c.ObjectID = NONE.ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - if ((bVar5) || (_LoginPossible == 0)) { - ddy = -1; - do { - local_b0 = -1; - iVar9 = ddy + iVar16; - do { - bVar1 = false; - if ((-xmax <= iVar9) && (iVar9 <= xmax)) { - bVar1 = true; - } - if (bVar1) { - bVar1 = false; - iVar14 = local_b0 + iVar17; - if ((-xmax <= iVar14) && (iVar14 <= xmax)) { - bVar1 = true; - } - if (bVar1) { - iVar11 = iVar14 - Map.xmin; - iVar15 = iVar9 - (int)local_3c; - if ((((iVar15 < 0) || (Map.ymin <= iVar15)) || - (iVar11 < 0)) || (Map.dx <= iVar11)) { - error( - "matrix::operator(): Ungueltiger Index %d/%d.\n", - iVar15 + (int)local_3c,iVar11 + Map.xmin,iVar18); - piVar12 = (int *)Map.dy; - } - else { - piVar12 = (int *)(Map.dy + (iVar15 + iVar11 * - Map.ymin) * 4); - } - if (_LoginPossible < *piVar12) { - iVar14 = iVar14 - Map.xmin; - iVar11 = iVar9 - (int)local_3c; - if (((iVar11 < 0) || (Map.ymin <= iVar11)) || - ((iVar14 < 0 || (Map.dx <= iVar14)))) { - error( - "matrix::operator(): Ungueltiger Index %d/%d.\n", - iVar11 + (int)local_3c,iVar14 + Map.xmin); - piVar12 = (int *)Map.dy; - } - else { - piVar12 = (int *)(Map.dy + (iVar11 + iVar14 * - Map.ymin) * 4); - } - iVar14 = -ddy; - if (-1 < ddy) { - iVar14 = ddy; - } - iVar11 = -local_b0; - if (-1 < local_b0) { - iVar11 = local_b0; - } - *piVar12 = iVar14 + _LoginPossible + iVar11; - } - } - } - local_b0 = local_b0 + 1; - } while (local_b0 < 2); - ddy = ddy + 1; - } while (ddy < 2); - bVar1 = true; - } - if ((bVar2) && ((bVar5 = IsNoLogoutField(), !bVar5 || (!Player)))) { - lVar13 = random(); - if (!bVar3) { - lVar13 = lVar13 + 100; - } - if (Pass < lVar13) { - bVar4 = true; - Pass = lVar13; - TieBreaker = iVar17; - BestY = iVar16; - } - } - } - } - iVar17 = iVar17 + 1; - } while (iVar17 <= xmax); - } - iVar16 = iVar16 + 1; - } while (iVar16 <= xmax); - } - if (((bVar4) && (-1 < Distance)) || (!bVar1)) break; - _LoginPossible = _LoginPossible + 1; - } - if (Pass < 0) { - if (Map.dy != 0) { - operator_delete__((void *)Map.dy); - } - bVar4 = false; - } - else { - *x = *x + BestY; - *y = *y + TieBreaker; - if (Map.dy != 0) { - operator_delete__((void *)Map.dy); - } - bVar4 = true; - } - return bVar4; -} - - - // WARNING: Unknown calling convention -- yet parameter storage is locked bool SearchFlightField(void) @@ -14932,28 +13125,6 @@ char * GetBanishmentReason(int Reason) return pcVar1; } - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitInfo(void) - -{ - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ExitInfo(void) - -{ - return; -} - - - // WARNING: Unknown calling convention -- yet parameter storage is locked void _GLOBAL__I__Z7GetName6Object(void) diff --git a/src/cr.hh b/src/cr.hh index 5ad1676..92521bd 100644 --- a/src/cr.hh +++ b/src/cr.hh @@ -798,6 +798,9 @@ void LoadMonsterRaid(const char *FileName, int Start, void LoadMonsterRaids(void); void ProcessMonsterRaids(void); +void InitCr(void); +void ExitCr(void); + // crskill.cc // ============================================================================= int GetSkillByName(const char *Name); diff --git a/src/cract.cc b/src/cract.cc index 3d56aa2..22e5b93 100644 --- a/src/cract.cc +++ b/src/cract.cc @@ -1,5 +1,6 @@ #include "cr.hh" #include "config.hh" +#include "info.hh" #include "operate.hh" #include "stubs.hh" @@ -497,7 +498,7 @@ void TCreature::Move(Object Obj, int DestX, int DestY, int DestZ, uint8 Count){ if(DestY >= INVENTORY_FIRST && DestY <= INVENTORY_LAST){ DestCon = GetBodyContainer(this->ID, DestY); DestObj = GetBodyObject(this->ID, DestY); - }else if(DestY >= 64 && DestY < 80){ + }else if(DestY >= CONTAINER_FIRST && DestY <= CONTAINER_LAST){ DestCon = GetBodyContainer(this->ID, DestY); if(DestZ < 254){ // TODO(fusion): The last argument to `GetObject` is the object diff --git a/src/crcombat.cc b/src/crcombat.cc index 25fff0e..c1f27a4 100644 --- a/src/crcombat.cc +++ b/src/crcombat.cc @@ -1,5 +1,6 @@ #include "cr.hh" #include "config.hh" +#include "info.hh" #include "magic.hh" #include "stubs.hh" diff --git a/src/enums.hh b/src/enums.hh index 6efcf61..5f7810c 100644 --- a/src/enums.hh +++ b/src/enums.hh @@ -242,6 +242,10 @@ enum InventorySlot: int { // NOTE(fusion): For iterating over hand slots. INVENTORY_HAND_FIRST = INVENTORY_RIGHTHAND, INVENTORY_HAND_LAST = INVENTORY_LEFTHAND, + + // NOTE(fusion): For iterating over container slots. + CONTAINER_FIRST = 64, + CONTAINER_LAST = 79, }; enum KNOWNCREATURESTATE: int { @@ -250,17 +254,33 @@ enum KNOWNCREATURESTATE: int { KNOWNCREATURE_OUTDATED = 2 }; +// NOTE(fusion): Not in debug symbols. +enum LiquidColor: uint8 { + LIQUID_COLORLESS = 0, + LIQUID_BLUE = 1, + LIQUID_RED = 2, + LIQUID_BROWN = 3, + LIQUID_GREEN = 4, + LIQUID_YELLOW = 5, + LIQUID_WHITE = 6, + LIQUID_PURPLE = 7, +}; + +// NOTE(fusion): Not in debug symbols. enum LiquidType: int { - LIQUID_NONE = 0, - LIQUID_WATER = 1, - LIQUID_WINE = 2, - LIQUID_BEER = 3, - LIQUID_MUD = 4, - LIQUID_BLOOD = 5, - LIQUID_SLIME = 6, - LIQUID_MANA = 10, - LIQUID_LIFE = 11, - LIQUID_LEMONADE = 12, + LIQUID_NONE = 0, + LIQUID_WATER = 1, + LIQUID_WINE = 2, + LIQUID_BEER = 3, + LIQUID_MUD = 4, + LIQUID_BLOOD = 5, + LIQUID_SLIME = 6, + LIQUID_OIL = 7, + LIQUID_URINE = 8, + LIQUID_MILK = 9, + LIQUID_MANA = 10, + LIQUID_LIFE = 11, + LIQUID_LEMONADE = 12, }; // NOTE(fusion): Not in debug symbols. diff --git a/src/info.cc b/src/info.cc index 808133b..fc1df61 100644 --- a/src/info.cc +++ b/src/info.cc @@ -3,6 +3,681 @@ #include "stubs.hh" +const char *GetLiquidName(int LiquidType){ + const char *LiquidName; + switch(LiquidType) { + case LIQUID_NONE: LiquidName = "nothing"; break; + case LIQUID_WATER: LiquidName = "water"; break; + case LIQUID_WINE: LiquidName = "wine"; break; + case LIQUID_BEER: LiquidName = "beer"; break; + case LIQUID_MUD: LiquidName = "mud"; break; + case LIQUID_BLOOD: LiquidName = "blood"; break; + case LIQUID_SLIME: LiquidName = "slime"; break; + case LIQUID_OIL: LiquidName = "oil"; break; + case LIQUID_URINE: LiquidName = "urine"; break; + case LIQUID_MILK: LiquidName = "milk"; break; + case LIQUID_MANA: LiquidName = "manafluid"; break; + case LIQUID_LIFE: LiquidName = "lifefluid"; break; + case LIQUID_LEMONADE: LiquidName = "lemonade"; break; + default:{ + error("GetLiquidName: Ungültiger Flüssigkeitstyp %d\n", LiquidType); + LiquidName = "unknown"; + break; + } + } + return LiquidName; +} + +uint8 GetLiquidColor(int LiquidType){ + uint8 LiquidColor; + switch(LiquidType){ + case LIQUID_NONE: LiquidColor = LIQUID_COLORLESS; break; + case LIQUID_WATER: LiquidColor = LIQUID_BLUE; break; + case LIQUID_WINE: LiquidColor = LIQUID_PURPLE; break; + case LIQUID_BEER: LiquidColor = LIQUID_BROWN; break; + case LIQUID_MUD: LiquidColor = LIQUID_BROWN; break; + case LIQUID_BLOOD: LiquidColor = LIQUID_RED; break; + case LIQUID_SLIME: LiquidColor = LIQUID_GREEN; break; + case LIQUID_OIL: LiquidColor = LIQUID_BROWN; break; + case LIQUID_URINE: LiquidColor = LIQUID_YELLOW; break; + case LIQUID_MILK: LiquidColor = LIQUID_WHITE; break; + case LIQUID_MANA: LiquidColor = LIQUID_PURPLE; break; + case LIQUID_LIFE: LiquidColor = LIQUID_RED; break; + case LIQUID_LEMONADE: LiquidColor = LIQUID_YELLOW; break; + default:{ + error("GetLiquidColor: Ungültiger Flüssigkeitstyp %d\n", LiquidType); + LiquidColor = LIQUID_COLORLESS; + break; + } + } + return LiquidColor; +} + +const char *GetName(Object Obj){ + char ObjectName[50] = {}; + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + if(Creature != NULL){ + snprintf(ObjectName, sizeof(ObjectName), "%s", Creature->Name); + }else{ + error("GetName: Kreatur %d existiert nicht.\n", Obj.getCreatureID()); + } + }else{ + // IMPORTANT(fusion): `ObjectType::getName` returns the same static buffer + // from `Plural`. + const char *TypeName = ObjType.getName(1); + if(TypeName != NULL){ + strcpy(ObjectName, TypeName); + } + + int LiquidType = LIQUID_NONE; + if(ObjType.getFlag(LIQUIDCONTAINER)){ + LiquidType = (int)Obj.getAttribute(CONTAINERLIQUIDTYPE); + }else if(ObjType.getFlag(LIQUIDPOOL)){ + LiquidType = (int)Obj.getAttribute(POOLLIQUIDTYPE); + } + + if(LiquidType != LIQUID_NONE){ + strcat(ObjectName, " of "); + strcat(ObjectName, GetLiquidName(LiquidType)); + } + } + + int Count = 1; + if(ObjType.getFlag(CUMULATIVE)){ + Count = (int)Obj.getAttribute(AMOUNT); + } + + // IMPORTANT(fusion): `Plural` will return a static buffer. + return Plural(ObjectName, Count); +} + +const char *GetInfo(Object Obj){ + if(!Obj.exists()){ + error("GetInfo: Übergebenes Objekt existiert nicht.\n"); + return NULL; + } + + return Obj.getObjectType().getDescription(); +} + +int GetWeight(Object Obj, int Count){ + if(!Obj.exists()){ + error("GetWeight: Übergebenes Objekt existiert nicht.\n"); + return 0; + } + + // TODO(fusion): Why do some UNTAKE items have weight, and even worse, hardcoded? + + int Result = 0; + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(TAKE)){ + int Weight = (int)ObjType.getAttribute(WEIGHT); + if(!ObjType.getFlag(CUMULATIVE)){ + Count = 1; + }else if(Count == -1){ + Count = (int)Obj.getAttribute(AMOUNT); + } + Result = Weight * Count; + }else if(ObjType.TypeID == 2904){ // LARGE AMPHORA + Result = 19500; + }else if(ObjType.TypeID == 3458){ // ANVIL + Result = 50000; + }else if(ObjType.TypeID == 3510){ // COAL BASIN + Result = 22800; + }else if(ObjType.TypeID == 4311){ // DEAD HUMAN + Result = 80000; + }else{ + error("GetWeight: Objekttyp %d ist nicht nehmbar.\n", ObjType.TypeID); + } + return Result; +} + +int GetCompleteWeight(Object Obj){ + int Result = GetWeight(Obj, -1); + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CONTAINER) || ObjType.getFlag(CHEST)){ + Object Help = GetFirstContainerObject(Obj); + Result += GetRowWeight(Help); + } + return Result; +} + +int GetRowWeight(Object Obj){ + int Result = 0; + while(Obj != NONE){ + // TODO(fusion): This is probably `GetCompleteWeight` inlined. + Result += GetWeight(Obj, -1); + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CONTAINER) || ObjType.getFlag(CHEST)){ + Object Help = GetFirstContainerObject(Obj); + Result += GetRowWeight(Help); + } + Obj = Obj.getNextObject(); + } + return Result; +} + +uint32 GetObjectCreatureID(Object Obj){ + if(!Obj.exists()){ + error("GetObjectCreatureID: Übergebenes Objekt existiert nicht.\n"); + return 0; + } + + uint32 CreatureID = 0; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer()){ + CreatureID = Obj.getCreatureID(); + break; + }else if(ObjType.isMapContainer()){ + break; + } + Obj = Obj.getContainer(); + } + return CreatureID; +} + +int GetObjectBodyPosition(Object Obj){ + if(!Obj.exists()){ + error("GetObjectBodyPosition: Übergebenes Objekt existiert nicht.\n"); + return 0; + } + + int Position = 0; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isBodyContainer()){ + // NOTE(fusion): Body container type ids match inventory slots exactly. + Position = ObjType.TypeID; + break; + }else if(ObjType.isMapContainer()){ + break; + } + Obj = Obj.getContainer(); + } + return Position; +} + +int GetObjectRNum(Object Obj){ + if(!Obj.exists()){ + error("GetObjectRNum: Übergebenes Objekt existiert nicht.\n"); + return 0; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isMapContainer()){ + error("GetObjectRNum: Objekt ist MapContainer.\n"); + return 0; + } + + int Result = 0; + Object Con = Obj.getContainer(); + Object Help = GetFirstContainerObject(Con); + while(Help != NONE && Help != Obj){ + Result += 1; + Help = Help.getNextObject(); + } + + if(Help != Obj){ + error("GetObjectRNum: Objekt liegt nicht in Container\n"); + Result = 0; + } + + return Result; +} + +bool ObjectInRange(uint32 CreatureID, Object Obj, int Range){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("ObjectInRange: Ungültige Kreatur CreatureID=%d übergeben.\n", CreatureID); + return false; + } + + if(!Obj.exists()){ + error("ObjectInRange: Übergebenes Objekt existiert nicht.\n"); + return false; + } + + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + return Creature->posz == ObjZ + && std::abs(Creature->posx - ObjX) <= Range + && std::abs(Creature->posy - ObjY) <= Range; +} + +bool ObjectAccessible(uint32 CreatureID, Object Obj, int Range){ + if(!Obj.exists()){ + error("ObjectAccessible: Übergebenes Objekt existiert nicht.\n"); + return false; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.isCreatureContainer()){ + uint32 OwnerID = GetObjectCreatureID(Obj); + if(OwnerID != 0){ + return OwnerID == CreatureID; + } + } + + if(ObjType.getFlag(HANG)){ + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + + bool HookSouth = CoordinateFlag(ObjX, ObjY, ObjZ, HOOKSOUTH); + bool HookEast = CoordinateFlag(ObjX, ObjY, ObjZ, HOOKEAST); + if(HookSouth || HookEast){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("ObjectAccessible: Kreatur existiert nicht.\n"); + return false; + } + + if(HookSouth){ + if(Creature->posy < ObjY + || Creature->posy > (ObjY + Range) + || Creature->posx < (ObjX - Range) + || Creature->posx > (ObjX + Range)){ + return false; + } + } + + if(HookEast){ + if(Creature->posx < ObjX + || Creature->posx > (ObjX + Range) + || Creature->posy < (ObjY - Range) + || Creature->posy > (ObjY + Range)){ + return false; + } + } + } + } + + return ObjectInRange(CreatureID, Obj, Range); +} + +int ObjectDistance(Object Obj1, Object Obj2){ + if(!Obj1.exists() || !Obj2.exists()){ + error("ObjectDistance: Übergebene Objekte existieren nicht.\n"); + return INT_MAX; + } + + int Distance = INT_MAX; + int ObjX1, ObjY1, ObjZ1; + int ObjX2, ObjY2, ObjZ2; + GetObjectCoordinates(Obj1, &ObjX1, &ObjY1, &ObjZ1); + GetObjectCoordinates(Obj2, &ObjX2, &ObjY2, &ObjZ2); + if(ObjZ1 == ObjZ2){ + Distance = std::max( + std::abs(ObjX1 - ObjX2), + std::abs(ObjY1 - ObjY2)); + } + return Distance; +} + +Object GetBodyContainer(uint32 CreatureID, int Position){ + if((Position < INVENTORY_FIRST || Position > INVENTORY_LAST) + && (Position < CONTAINER_FIRST || Position > CONTAINER_LAST)){ + error("GetBodyContainer: ungültige Position: %d\n", Position); + return NONE; + } + + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("GetBodyContainer: Kreatur %d existiert nicht.\n", CreatureID); + return NONE; + } + + if(Position >= INVENTORY_FIRST && Position <= INVENTORY_LAST){ + if(!Creature->CrObject.exists()){ + error("GetBodyContainer: Kreatur-Objekt von %s existiert nicht (Pos %d).\n", + Creature->Name, Position); + return NONE; + } + + return GetContainerObject(Creature->CrObject, Position - INVENTORY_FIRST); + }else{ + if(Creature->Type != PLAYER){ + error("GetBodyContainer: Nur Spieler haben offene Container.\n"); + return NONE; + } + + return ((TPlayer*)Creature)->GetOpenContainer(Position - CONTAINER_FIRST); + } +} + +Object GetBodyObject(uint32 CreatureID, int Position){ + if(Position < INVENTORY_FIRST || Position > INVENTORY_LAST){ + error("GetBodyObject: ungültige Position %d\n", Position); + return NONE; + } + + Object Obj = NONE; + Object Con = GetBodyContainer(CreatureID, Position); + if(Con != NONE){ + Obj = GetFirstContainerObject(Con); + } + return Obj; +} + +Object GetTopObject(int x, int y, int z, bool Move){ + Object Obj = GetFirstObject(x, y, z); + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.getFlag(BANK) + && !ObjType.getFlag(CLIP) + && !ObjType.getFlag(BOTTOM) + && !ObjType.getFlag(TOP) + && (!Move || !ObjType.isCreatureContainer())){ + break; + } + Obj = Obj.getNextObject(); + } + return Obj; +} + +Object GetContainer(uint32 CreatureID, int x, int y, int z){ + if(x == 0xFFFF){ // SPECIAL_COORDINATE ? + return GetBodyContainer(CreatureID, y); + }else{ + return GetMapContainer(x, y, z); + } +} + +Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type){ + Object Obj = NONE; + if(x == 0xFFFF){ // SPECIAL_COORDINATE ? + if(y >= INVENTORY_FIRST && y <= INVENTORY_LAST){ + Obj = GetBodyObject(CreatureID, y); + }else if(y >= CONTAINER_FIRST && y <= CONTAINER_LAST){ + Object Con = GetBodyContainer(CreatureID, y); + if(Con != NONE){ + Obj = GetContainerObject(Con, RNum); + } + }else if(y != 0){ + error("GetObject: Ungültiger ContainerCode x=%d,y=%d,z=%d,RNum=%d,Type=%d.\n", + x, y, z, RNum, Type.TypeID); + } + }else if(RNum == -1){ + Obj = GetTopObject(x, y, z, false); + }else{ + Obj = GetFirstObject(x, y, z); + while(Obj != NONE){ + if(Obj.getObjectType().getDisguise() == Type){ + break; + } + Obj = Obj.getNextObject(); + } + } + + // NOTE(fusion): `Type` can be a map container (TypeID = 0) as a wildcard for + // any object found. + if(Obj != NONE && !Type.isMapContainer() + && Obj.getObjectType().getDisguise() != Type){ + Obj = NONE; + } + + return Obj; +} + +Object GetRowObject(Object Obj, ObjectType Type, uint32 Value, bool Recurse){ + Object Result = NONE; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(Recurse && ObjType.getFlag(CONTAINER)){ + Object Help = GetFirstContainerObject(Obj); + Result = GetRowObject(Help, Type, Value, Recurse); + if(Result != NONE){ + break; + } + } + + if(ObjType == Type + && (!ObjType.getFlag(LIQUIDCONTAINER) || Obj.getAttribute(CONTAINERLIQUIDTYPE) == Value) + && (!ObjType.getFlag(KEY) || Obj.getAttribute(KEYNUMBER) == Value)){ + Result = Obj; + break; + } + + Obj = Obj.getNextObject(); + } + return Result; +} + +Object GetInventoryObject(uint32 CreatureID, ObjectType Type, uint32 Value){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("GetInventoryObject: Kreatur %d existiert nicht.\n",CreatureID); + return NONE; + } + + Object Result = NONE; + + // NOTE(fusion): Search inventory containers. + { + Object BodyCon = GetFirstContainerObject(Creature->CrObject); + while(BodyCon != NONE){ + Object BodyObj = GetFirstContainerObject(BodyCon); + if(BodyObj != NONE && BodyObj.getObjectType().getFlag(CONTAINER)){ + Object Help = GetFirstContainerObject(BodyObj); + Result = GetRowObject(Help, Type, Value, true); + if(Result != NONE){ + break; + } + } + BodyCon = BodyCon.getNextObject(); + } + } + + // NOTE(fusion): Search inventory slots. + if(Result == NONE){ + Object BodyCon = GetFirstContainerObject(Creature->CrObject); + while(BodyCon != NONE){ + Object BodyObj = GetFirstContainerObject(BodyCon); + Result = GetRowObject(BodyObj, Type, Value, false); + if(Result != NONE){ + break; + } + BodyCon = BodyCon.getNextObject(); + } + } + + return Result; +} + +int CountObjectsInContainer(Object Con){ + if(!Con.exists()){ + error("CountObjectsInContainer: Container existiert nicht.\n"); + return 0; + } + + int Count = 0; + Object Obj = GetFirstContainerObject(Con); + while(Obj != NONE){ + Count += 1; + Obj = Obj.getNextObject(); + } + return Count; +} + +int CountObjects(Object Obj){ + if(!Obj.exists()){ + return 0; + } + + int Count = 1; + if(Obj.getObjectType().getFlag(CONTAINER)){ + Object Help = GetFirstContainerObject(Obj); + while(Help != NONE){ + Count += CountObjects(Help); + Help = Help.getNextObject(); + } + } + return Count; +} + +int CountObjects(Object Obj, ObjectType Type, uint32 Value){ + if(!Obj.exists()){ + return 0; + } + + // TODO(fusion): This is different from the other `CountObjects` as it does + // check other objects in the chain. + int Count = 0; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CONTAINER)){ + Object Help = GetFirstContainerObject(Obj); + // BUG(fusion): We probably meant to pass `Value` down the the call stack? + Count += CountObjects(Help, Type, 0); + } + + if(ObjType == Type + && (!ObjType.getFlag(LIQUIDCONTAINER) || Obj.getAttribute(CONTAINERLIQUIDTYPE) == Value) + && (!ObjType.getFlag(KEY) || Obj.getAttribute(KEYNUMBER) == Value)){ + if(ObjType.getFlag(CUMULATIVE)){ + Count += (int)Obj.getAttribute(AMOUNT); + }else{ + Count += 1; + } + } + + Obj = Obj.getNextObject(); + } + return Count; +} + +int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("CountInventoryObjects: Kreatur %d existiert nicht; Objekttyp %d.\n", + CreatureID, Type.TypeID); + return 0; + } + + if(Creature->CrObject == NONE){ + error("CountInventoryObjects: Kreatur %s hat kein Kreatur-Objekt.\n", + Creature->Name); + return 0; + } + + Object Help = GetFirstContainerObject(Help); + return CountObjects(Help, Type, Value); +} + +int CountMoney(Object Obj){ + if(!Obj.exists()){ + return 0; + } + + int Result = 0; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CONTAINER)){ + Object Help = GetFirstContainerObject(Obj); + Result += CountMoney(Help); + } + + // TODO(fusion): This was three different if statements but I don't think + // we'd want the same object type to be all special money objects. + if(ObjType == GetSpecialObject(MONEY_ONE)){ + Result += (int)Obj.getAttribute(AMOUNT); + }else if(ObjType == GetSpecialObject(MONEY_HUNDRED)){ + Result += (int)Obj.getAttribute(AMOUNT) * 100; + }else if(ObjType == GetSpecialObject(MONEY_TENTHOUSAND)){ + Result += (int)Obj.getAttribute(AMOUNT) * 10000; + } + + Obj = Obj.getNextObject(); + } + return Result; +} + +int CountInventoryMoney(uint32 CreatureID){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature == NULL){ + error("CountInventoryMoney: Kreatur %d existiert nicht.\n", CreatureID); + return 0; + } + + if(Creature->CrObject == NONE){ + error("CountInventoryMoney: Kreatur %s hat kein Kreatur-Objekt.\n", Creature->Name); + return 0; + } + + Object Help = GetFirstContainerObject(Creature->CrObject); + return CountMoney(Help); +} + +void CalculateChange(int Amount, int *Gold, int *Platinum, int *Crystal){ + // TODO(fusion): This function is kind of a mess. We should simplify or + // get rid of it entirely. It is used when removing gold from a creature + // but doesnt doesn't report errors outside from the `error` logging. It + // expects the caller to also check whether the amount of gold, platinum, + // and crystal is sufficient? We'll see when it gets applied. + + int Go = *Gold; + int Pl = *Platinum; + int Cr = *Crystal; + + print(3, "Zahle %d mit %d/%d/%d Münzen...\n", Amount, Go, Pl, Cr); + if((Cr * 10000 + Pl * 100 + Go) < Amount){ + error("CalculateChange: %d/%d/%d Münzen reichen nicht zur Bezahlung von %d.\n", + Go, Pl, Cr, Amount); + return; + } + + int AmountCr = Amount / 10000; + int AmountRem = Amount % 10000; + if((Pl * 100 + Go) < AmountRem){ + Cr = AmountCr + 1; + Pl = (AmountRem - 10000) / 100; + Go = (AmountRem - 10000) % 100; + }else{ + if(Cr < AmountCr){ + AmountRem = Amount - Cr * 10000; + }else{ + Cr = AmountCr; + } + + int AmountPl = AmountRem / 100; + int AmountGo = AmountRem % 100; + if(Go < AmountGo){ + Pl = AmountPl + 1; + Go = AmountGo - 100; + }else if(Pl < AmountPl){ + Go = AmountRem - Pl * 100; + }else{ + Pl = AmountPl; + Go = AmountGo; + } + } + + print(3, "Verwende %d/%d/%d Münzen.\n", Go, Pl, Cr); + *Gold = Go; + *Platinum = Pl; + *Crystal = Cr; + + if((Cr * 10000 + Pl * 100 + Go) != Amount){ + error("CalculateChange: Fehlerhafte Berechnung: %d/%d/%d Münzen für %d.\n", + Go, Pl, Cr, Amount); + } +} + +int GetHeight(int x, int y, int z){ + int Result = 0; + Object Obj = GetFirstObject(x, y, z); + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(HEIGHT)){ + Result += (int)ObjType.getAttribute(ELEVATION); + } + Obj = Obj.getNextObject(); + } + return Result; +} + bool JumpPossible(int x, int y, int z, bool AvoidPlayers){ bool HasBank = false; Object Obj = GetFirstObject(x, y, z); @@ -29,6 +704,39 @@ bool JumpPossible(int x, int y, int z, bool AvoidPlayers){ return HasBank; } +bool FieldPossible(int x, int y, int z, int FieldType){ + Object Obj = GetFirstObject(x, y, z); + + // NOTE(fusion): Only the first object on a given coordinate can be a bank + // on regular circumstances, so it makes sense to check it right away to + // determine whether a bank is present. + if(Obj == NONE || !Obj.getObjectType().getFlag(BANK)){ + return false; + } + + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.isCreatureContainer()){ + if(ObjType.getFlag(UNPASS)){ + return false; + } + + if(ObjType.getFlag(UNLAY)){ + return false; + } + } + + if(FieldType == FIELD_TYPE_MAGICWALL || FieldType == FIELD_TYPE_WILDGROWTH){ + if(ObjType.getFlag(UNPASS)){ + return false; + } + } + + Obj = Obj.getNextObject(); + } + return true; +} + bool SearchFreeField(int *x, int *y, int *z, int Distance, uint16 HouseID, bool Jump){ int OffsetX = 0; int OffsetY = 0; @@ -55,8 +763,9 @@ bool SearchFreeField(int *x, int *y, int *z, int Distance, uint16 HouseID, bool } if(MovePossible){ - if(HouseID == HOUSEID_ANY || !IsHouse(FieldX, FieldY, FieldZ) - || (HouseID != 0 && HouseID == GetHouseID(FieldX, FieldY, FieldZ))){ + if(HouseID == HOUSEID_ANY + || !IsHouse(FieldX, FieldY, FieldZ) + || GetHouseID(FieldX, FieldY, FieldZ) == HouseID){ *x = FieldX; *y = FieldY; return true; @@ -95,3 +804,220 @@ bool SearchFreeField(int *x, int *y, int *z, int Distance, uint16 HouseID, bool return false; } + +// TODO(fusion): This is a helper function for `SearchLoginField`. Perhaps we +// should try to merge it there? +static bool LoginPossible(int x, int y, int z, uint16 HouseID, bool Player){ + Object Obj = GetFirstObject(x, y, z); + if(Obj == NONE){ + return false; + } + + if(Player && IsNoLogoutField(x, y, z)){ + return false; + } + + if(IsHouse(x, y, z) && GetHouseID(x, y, z) != HouseID){ + return false; + } + + bool HasBank = false; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(BANK)){ + HasBank = true; + } + + if(ObjType.isCreatureContainer()){ + return false; + } + + if(ObjType.getFlag(UNPASS) && ObjType.getFlag(UNMOVE)){ + return false; + } + + if(!Player && ObjType.getFlag(AVOID) && ObjType.getFlag(UNMOVE)){ + return false; + } + + Obj = Obj.getNextObject(); + } + return HasBank; +} + +bool SearchLoginField(int *x, int *y, int *z, int Distance, bool Player){ + uint16 HouseID = GetHouseID(*x, *y, *z); + if(SearchFreeField(x, y, z, Distance, HouseID, false) + && (!Player || !IsNoLogoutField(*x, *y, *z))){ + return true; + } + + int OffsetX = 0; + int OffsetY = 0; + int CurrentDistance = 0; + int CurrentDirection = DIRECTION_EAST; + while(CurrentDistance <= Distance){ + int FieldX = *x + OffsetX; + int FieldY = *y + OffsetY; + int FieldZ = *z; + + if(LoginPossible(FieldX, FieldY, FieldZ, HouseID, Player)){ + *x = FieldX; + *y = FieldY; + return true; + } + + // NOTE(fusion): Same as `SearchFreeField`. + if(CurrentDirection == DIRECTION_NORTH){ + OffsetY -= 1; + if(OffsetY <= -CurrentDistance){ + CurrentDirection = DIRECTION_WEST; + } + }else if(CurrentDirection == DIRECTION_WEST){ + OffsetX -= 1; + if(OffsetX <= -CurrentDistance){ + CurrentDirection = DIRECTION_SOUTH; + } + }else if(CurrentDirection == DIRECTION_SOUTH){ + OffsetY += 1; + if(OffsetY >= CurrentDistance){ + CurrentDirection = DIRECTION_EAST; + } + }else{ + ASSERT(CurrentDirection == DIRECTION_EAST); + OffsetX += 1; + if(OffsetX > CurrentDistance){ + CurrentDistance = OffsetX; + CurrentDirection = DIRECTION_NORTH; + } + } + } + return false; +} + +bool SearchSpawnField(int *x, int *y, int *z, int Distance, bool Player){ + // TODO(fusion): It seems `Distance` can be a negative number to do some + // extended search? + bool Minimize = true; + if(Distance < 0){ + Minimize = false; + Distance = -Distance; + } + + uint16 HouseID = GetHouseID(*x, *y, *z); + matrix Map(-Distance, Distance, -Distance, Distance, INT_MAX); + *Map.at(0, 0) = 0; + + + int BestX = 0; + int BestY = 0; + int BestTieBreaker = -1; + int ExpansionPhase = 0; + while(true){ + bool Found = false; + bool Expanded = false; + for(int OffsetY = -Distance; OffsetY <= Distance; OffsetY += 1) + for(int OffsetX = -Distance; OffsetX <= Distance; OffsetX += 1){ + if(*Map.at(OffsetX, OffsetY) != ExpansionPhase){ + continue; + } + + int FieldX = *x + OffsetX; + int FieldY = *y + OffsetY; + int FieldZ = *z; + if(IsHouse(FieldX, FieldY, FieldZ) && GetHouseID(FieldX, FieldY, FieldZ) != HouseID){ + continue; + } + + if(!Player && IsProtectionZone(FieldX, FieldY, FieldZ)){ + continue; + } + + Object Obj = GetFirstObject(FieldX, FieldY, FieldZ); + if(Obj == NONE){ + continue; + } + + bool ExpansionPossible = true; + bool LoginPossible = true; + bool LoginBad = false; + while(Obj != NONE){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer()){ + LoginPossible = false; + } + + if(ObjType.getFlag(UNPASS)){ + if(ObjType.getFlag(UNMOVE)){ + ExpansionPossible = false; + LoginPossible = false; + }else{ + LoginBad = true; + } + } + + if(ObjType.getFlag(AVOID)){ + if(ObjType.getFlag(UNMOVE)){ + ExpansionPossible = false; + LoginPossible = LoginPossible && !Player; + }else{ + LoginBad = true; + } + } + + Obj = Obj.getNextObject(); + } + + if(ExpansionPossible || ExpansionPhase == 0){ + for(int NeighborOffsetY = OffsetY - 1; NeighborOffsetY <= OffsetY + 1; NeighborOffsetY += 1) + for(int NeighborOffsetX = OffsetX - 1; NeighborOffsetX <= OffsetX + 1; NeighborOffsetX += 1){ + if(-Distance <= NeighborOffsetX && NeighborOffsetX <= Distance + && -Distance <= NeighborOffsetY && NeighborOffsetY <= Distance){ + int *NeighborPhase = Map.at(NeighborOffsetX, NeighborOffsetY); + if(*NeighborPhase > ExpansionPhase){ + *NeighborPhase = ExpansionPhase + + std::abs(NeighborOffsetX - OffsetX) + + std::abs(NeighborOffsetY - OffsetY); + } + } + } + } + + if(LoginPossible && (!Player || !IsNoLogoutField(FieldX, FieldY, FieldZ))){ + int TieBreaker = random(0, 99); + if(!LoginBad){ + TieBreaker += 100; + } + + if(TieBreaker > BestTieBreaker){ + BestX = FieldX; + BestY = FieldY; + BestTieBreaker = TieBreaker; + } + } + } + + if((Found && Minimize) || !Expanded){ + break; + } + + ExpansionPhase += 1; + } + + bool Result = false; + if(BestTieBreaker >= 0){ + *x = BestX; + *y = BestY; + Result = true; + } + + return Result; +} + +void InitInfo(void){ + // no-op +} + +void ExitInfo(void){ + // no-op +} diff --git a/src/info.hh b/src/info.hh index d3bd625..3cb6399 100644 --- a/src/info.hh +++ b/src/info.hh @@ -12,7 +12,39 @@ enum HouseList: uint8 { DOORLIST = 3, }; +const char *GetLiquidName(int LiquidType); +uint8 GetLiquidColor(int LiquidType); +const char *GetName(Object Obj); +int GetWeight(Object Obj, int Count); +int GetCompleteWeight(Object Obj); +int GetRowWeight(Object Obj); +uint32 GetObjectCreatureID(Object Obj); +int GetObjectBodyPosition(Object Obj); +int GetObjectRNum(Object Obj); +bool ObjectInRange(uint32 CreatureID, Object Obj, int Range); +bool ObjectAccessible(uint32 CreatureID, Object Obj, int Range); +int ObjectDistance(Object Obj1, Object Obj2); +Object GetBodyContainer(uint32 CreatureID, int Position); +Object GetBodyObject(uint32 CreatureID, int Position); +Object GetTopObject(int x, int y, int z, bool Move); +Object GetContainer(uint32 CreatureID, int x, int y, int z); +Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type); +Object GetRowObject(Object Obj, ObjectType Type, uint32 Value, bool Recurse); +Object GetInventoryObject(uint32 CreatureID, ObjectType Type, uint32 Value); +int CountObjectsInContainer(Object Con); +int CountObjects(Object Obj); +int CountObjects(Object Obj, ObjectType Type, uint32 Value); +int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value); +int CountMoney(Object Obj); +int CountInventoryMoney(uint32 CreatureID); +void CalculateChange(int Amount, int *Gold, int *Platinum, int *Crystal); +int GetHeight(int x, int y, int z); bool JumpPossible(int x, int y, int z, bool AvoidPlayers); +bool FieldPossible(int x, int y, int z, int FieldType); bool SearchFreeField(int *x, int *y, int *z, int Distance, uint16 HouseID, bool Jump); +bool SearchLoginField(int *x, int *y, int *z, int Distance, bool Player); +bool SearchSpawnField(int *x, int *y, int *z, int Distance, bool Player); +void InitInfo(void); +void ExitInfo(void); #endif //TIBIA_INFO_HH_ diff --git a/src/magic.cc b/src/magic.cc index 46da798..28c1aa5 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -2487,11 +2487,7 @@ void ObjectIllusion(TCreature *Actor, int ManaPoints, int SoulPoints, Object Tar CheckMana(Actor, ManaPoints, SoulPoints, 1000); if(Actor->Skills[SKILL_ILLUSION]->Get() == 0){ Actor->Outfit.OutfitID = 0; - if(TargetType.getFlag(DISGUISE)){ - Actor->Outfit.ObjectType = (uint16)TargetType.getAttribute(DISGUISETARGET); - }else{ - Actor->Outfit.ObjectType = (uint16)TargetType.TypeID; - } + Actor->Outfit.ObjectType = (uint16)TargetType.getDisguise().TypeID; Actor->SetTimer(SKILL_ILLUSION, 1, Duration, Duration, -1); } diff --git a/src/magic.hh b/src/magic.hh index 8946153..adc648f 100644 --- a/src/magic.hh +++ b/src/magic.hh @@ -197,5 +197,7 @@ int CheckForSpell(uint32 CreatureID, const char *Text); void UseMagicItem(uint32 CreatureID, Object Obj, Object Dest); void DrinkPotion(uint32 CreatureID, Object Obj); +void InitMagic(void); +void ExitMagic(void); #endif //TIBIA_MAGIC_HH_ diff --git a/src/main.cc b/src/main.cc index 3925b04..bbdebf1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,8 @@ #include "common.hh" #include "config.hh" +#include "info.hh" #include "map.hh" +#include "magic.hh" #include "objects.hh" #include "stubs.hh" @@ -230,10 +232,10 @@ static void InitAll(void){ //InitReader(); InitObjects(); InitMap(); - //InitInfo(); + InitInfo(); //InitMoveUse(); - //InitMagic(); - //InitCr(); + InitMagic(); + InitCr(); //InitHouses(); InitTime(); //ApplyPatches(); @@ -248,10 +250,10 @@ static void ExitAll(void){ EndGame(); ExitTime(); - //ExitCr(); - //ExitMagic(); + ExitCr(); + ExitMagic(); //ExitMoveUse(); - //ExitInfo(); + ExitInfo(); //ExitHouses(); ExitMap(SaveMapOn); ExitObjects(); diff --git a/src/objects.hh b/src/objects.hh index 48dbedf..3d312ac 100644 --- a/src/objects.hh +++ b/src/objects.hh @@ -62,6 +62,14 @@ struct ObjectType { || this->getFlag(WAND); } + ObjectType getDisguise(void){ + if(this->getFlag(DISGUISE)){ + return (int)this->getAttribute(DISGUISETARGET); + }else{ + return *this; + } + } + bool operator==(const ObjectType &Other) const { return this->TypeID == Other.TypeID; } diff --git a/src/operate.cc b/src/operate.cc index ef1ba01..cb4819d 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -1,4 +1,5 @@ #include "operate.hh" +#include "info.hh" #include "stubs.hh" diff --git a/src/stubs.hh b/src/stubs.hh index c2ca289..63615d7 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -26,26 +26,15 @@ 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 int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value); -extern int CountObjects(Object Obj); -extern int CountObjectsInContainer(Object Con); extern Object Create(Object Con, ObjectType Type, uint32 Value); extern Object CreateAtCreature(uint32 CreatureID, ObjectType Type, uint32 Value); extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); extern void CreatePlayerList(bool Online); extern void CreatePool(Object Con, ObjectType Type, uint32 Value); extern void Delete(Object Obj, int Count); -extern bool FieldPossible(int x, int y, int z, int FieldType); -extern Object GetBodyObject(uint32 CreatureID, int Position); -extern Object GetBodyContainer(uint32 CreatureID, int Position); -extern int GetObjectBodyPosition(Object Obj); extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z); extern TConnection *GetFirstConnection(void); -extern int GetHeight(int x, int y, int z); extern TConnection *GetNextConnection(void); -extern const char *GetName(Object Obj); -extern Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type); -extern uint32 GetObjectCreatureID(Object Obj); extern TPlayer *GetPlayer(uint32 CreatureID); extern void GraphicalEffect(int x, int y, int z, int Type); extern void GraphicalEffect(Object Obj, int Type); @@ -64,9 +53,6 @@ extern void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMe extern void NetLoadCheck(void); extern void NetLoadSummary(void); extern void NotifyAllCreatures(Object Obj, int Type, Object OldCon); -extern bool ObjectAccessible(uint32 CreatureID, Object Obj, int Range); -extern int ObjectDistance(Object Obj1, Object Obj2); -extern bool ObjectInRange(uint32 CreatureID, Object Obj, int Range); extern void ProcessCommunicationControl(void); extern void ProcessConnections(void); extern void ProcessCronSystem(void); @@ -79,7 +65,6 @@ extern void RefreshMap(void); extern void RefreshSector(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Size); extern void SavePlayerDataOrder(void); extern bool SearchFlightField(uint32 FugitiveID, uint32 PursuerID, int *x, int *y, int *z); -extern bool SearchLoginField(int *x, int *y, int *z, int Distance, bool Player); extern bool SearchSummonField(int *x, int *y, int *z, int Distance); extern void SendAll(void); extern void SendAmbiente(TConnection *Connection);