From e59667ec6be0a21ce702ce077154357a1c7f7c04 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Fri, 27 Jun 2025 18:57:29 -0300 Subject: `moveuse.cc` --- TODO.md | 14 +- reference/enums.hh | 70 - reference/game.c | 5733 ---------------------------------------------------- reference/types.hh | 30 - src/crcombat.cc | 4 +- src/crmain.cc | 109 +- src/crnonpl.cc | 6 +- src/crplayer.cc | 1 + src/enums.hh | 31 - src/info.cc | 3 + src/magic.cc | 2 +- src/main.cc | 5 +- src/map.cc | 54 +- src/moveuse.cc | 3039 +++++++++++++++++++++++++++- src/moveuse.hh | 186 ++ src/operate.cc | 18 +- src/stubs.hh | 23 +- 17 files changed, 3336 insertions(+), 5992 deletions(-) diff --git a/TODO.md b/TODO.md index fe5db50..dce0e29 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,4 @@ ## TODO NEXT -- CRNONPL.CC <- GAME -- MOVEUSE.CC <- GAME - HOUSES.CC <- GAME - QUERY.CC - READER.CC @@ -13,11 +11,19 @@ `ObjectType` to be used as an alias when pertinent. - Make some `TNonplayer` random step function? One version that does a random step and another that does a random step keeping some distance from a certain position. +- I realized that `Change` with an `ObjectType` parameter was being called where + the version with `INSTANCEATTRIBUTE` parameter was expected due to `ObjectType` + having an implicit conversion constructor from `int`. I think it is best to make + all converting constructors explicit to avoid these types of errors, although + there aren't that many function overloads. + +- Define a few constants like `MAX_NAME_LENGTH`, `MAX_SKILLS`, and `MAX_OPEN_CONTAINERS` instead of relying on `NARRAY`. + ## Stack allocations Any functions that use `alloca` or some other form of dynamic stack allocations will cause decompiled functions to be an absolute mess. It usually shows up in the decompiled code as both a size computation like `-(VAR + CONST & 0xfffffff0)`, followed by some assignment. It doesn't make total sense without looking at the disassembly. I've encountered ~30 such computations and expect the functions containing them to be amongt the most challenging/annoying to be properly decompiled. ## Exceptions -I didn't dive into how exceptions are handled, but it seems that the ones related to creature actions have the outter most endpoint at `TCreature::Execute`. There can also be some checkpoints in between to modify a `RESULT` value or handle a failure. +It's absolute hell. ## Synchronization I'm not sure whether synchronization is done properly. The implementation of the first few `crplayer.cc` functions left me with a taste of race conditions although integer loads on x86 are generally atomic. @@ -31,6 +37,8 @@ We'll have to address this BEFORE trying to run the server. The decompiled file has ~115K lines of C. If we take ~15K lines to be rubbish, this can be round to ~100K. Considering a low estimate of 200 lines per day, the whole process could take up to 500 days which is quite a bit but not impossible. Now considering a high estimate of 1K lines per day, it could take 100 days which is also quite a bit. ## TODO AFTER FIRST PASS +- Remove VTABLE comments. +- Split NPC, Monster, and Player into separate header files. - Review dividing comments. I feel like the current "//========" blends in too easily, making it hard to see. - Trim rough edges. - Replace unsafe libc functions like `strcpy`, `strncpy`, `strcat`, `sprintf` etc... diff --git a/reference/enums.hh b/reference/enums.hh index 6834e5a..d54a03f 100644 --- a/reference/enums.hh +++ b/reference/enums.hh @@ -1,51 +1,4 @@ -enum ActionType: int { - ACTION_CREATEONMAP=0, - ACTION_CREATE=1, - ACTION_MONSTERONMAP=2, - ACTION_MONSTER=3, - ACTION_EFFECTONMAP=4, - ACTION_EFFECT=5, - ACTION_TEXTONMAP=6, - ACTION_TEXT=7, - ACTION_CHANGEONMAP=8, - ACTION_CHANGE=9, - ACTION_CHANGEREL=10, - ACTION_SETATTRIBUTE=11, - ACTION_CHANGEATTRIBUTE=12, - ACTION_SETQUESTVALUE=13, - ACTION_DAMAGE=14, - ACTION_SETSTART=15, - ACTION_WRITENAME=16, - ACTION_WRITETEXT=17, - ACTION_LOGOUT=18, - ACTION_MOVEALLONMAP=19, - ACTION_MOVEALL=20, - ACTION_MOVEALLREL=21, - ACTION_MOVETOPONMAP=22, - ACTION_MOVETOP=23, - ACTION_MOVETOPREL=24, - ACTION_MOVE=25, - ACTION_MOVEREL=26, - ACTION_RETRIEVE=27, - ACTION_DELETEALLONMAP=28, - ACTION_DELETETOPONMAP=29, - ACTION_DELETEONMAP=30, - ACTION_DELETE=31, - ACTION_DELETEININVENTORY=32, - ACTION_DESCRIPTION=33, - ACTION_LOADDEPOT=34, - ACTION_SAVEDEPOT=35, - ACTION_SENDMAIL=36, - ACTION_NOP=37 -}; - -enum ModifierType: int { - MODIFIER_NORMAL=0, - MODIFIER_INVERT=1, - MODIFIER_TRUE=2 -}; - enum TWriterThreadReplyType: int { REPLY_BROADCAST=0, REPLY_DIRECT=1, @@ -76,29 +29,6 @@ enum CHANNEL: int { HELP_CHANNEL=7 }; -enum EventType: int { - EVENT_USE=0, - EVENT_MULTIUSE=1, - EVENT_MOVEMENT=2, - EVENT_COLLISION=3, - EVENT_SEPARATION=4 -}; - -enum ParameterType: int { - PARAMETER_OBJECT=0, - PARAMETER_TYPE=1, - PARAMETER_FLAG=2, - PARAMETER_TYPEATTRIBUTE=3, - PARAMETER_INSTANCEATTRIBUTE=4, - PARAMETER_COORDINATE=5, - PARAMETER_VECTOR=6, - PARAMETER_RIGHT=7, - PARAMETER_SKILL=8, - PARAMETER_NUMBER=9, - PARAMETER_TEXT=10, - PARAMETER_COMPARISON=11 -}; - enum TReaderThreadOrderType: int { ORDER_TERMINATE=0, ORDER_LOADSECTOR=1, diff --git a/reference/game.c b/reference/game.c index 4b7b5b7..b6cd717 100644 --- a/reference/game.c +++ b/reference/game.c @@ -12110,5739 +12110,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -Object GetEventObject(void) - -{ - Object OVar1; - ulong *in_stack_00000004; - undefined4 in_stack_00000008; - ulong *in_stack_0000000c; - ulong *in_stack_00000010; - ulong *in_stack_00000014; - ulong *in_stack_00000018; - - switch(in_stack_00000008) { - case 1: - in_stack_00000018 = in_stack_00000010; - break; - case 2: - in_stack_00000018 = in_stack_00000014; - break; - case 3: - in_stack_00000018 = in_stack_0000000c; - break; - case 4: - break; - default: - error("GetEventObject: Unbekannte Nummer %d.\n"); - case 0: - OVar1.ObjectID = NONE.ObjectID; - goto LAB_08072475; - } - OVar1.ObjectID = *in_stack_00000018; -LAB_08072475: - *in_stack_00000004 = OVar1.ObjectID; - return (Object)(ulong)in_stack_00000004; -} - - - -bool Compare(int Value1,int Operator,int Value2) - -{ - bool bVar1; - - switch(Operator) { - case 0x3c: - bVar1 = Value1 < Value2; - break; - case 0x3d: - bVar1 = Value1 == Value2; - break; - case 0x3e: - bVar1 = Value2 < Value1; - break; - default: - error(&DAT_080f79e0,Operator); - bVar1 = false; - break; - case 0x47: - bVar1 = Value2 <= Value1; - break; - case 0x4c: - bVar1 = Value1 <= Value2; - break; - case 0x4e: - bVar1 = Value1 != Value2; - } - return bVar1; -} - - - -bool CheckCondition(EventType param_1,TMoveUseCondition *Condition,Object *User,Object *Obj1, - Object *Obj2,Object *Temp) - -{ - ModifierType MVar1; - FLAG Flag; - TYPEATTRIBUTE Attribute; - byte bVar2; - char cVar3; - bool bVar4; - ushort HouseID; - TCreature *pTVar5; - char *__s2; - char *__s1; - int iVar6; - int iVar7; - ObjectType *pOVar8; - TPlayer *pTVar9; - ulong uVar10; - ulong uVar11; - long lVar12; - Object *pOVar13; - undefined4 uVar14; - ulong *puVar15; - ulong *puVar16; - ulong *puVar17; - bool local_a7; - bool local_a6; - bool local_a5; - int iStack_a4; - bool fulfilled; - int x2; - int y2; - int z2; - int x1; - int y1; - int z1; - Object local_7c [4]; - ObjectType local_6c [4]; - ulong local_5c [4]; - ulong local_4c [4]; - ulong local_3c [4]; - Object local_2c; - Object Obj; - - local_a5 = false; - local_2c.ObjectID = 0; - switch(Condition->Condition) { - case CONDITION_ISPOSITION: - local_5c[0] = Temp->ObjectID; - local_6c[0].TypeID = Obj2->ObjectID; - local_7c[0] = (Object)Obj1->ObjectID; - z1 = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_4c[0]; - local_3c[0] = local_4c[0]; - UnpackAbsoluteCoordinate(); - z1 = local_2c.ObjectID; - GetObjectCoordinates((Object *)&z1,&stack0xffffff5c,&x2,&y2); - local_a5 = false; - if ((z2 == iStack_a4) && (x1 == x2)) { - bVar4 = y1 == y2; -LAB_08072693: - local_a5 = false; - if (bVar4) { -LAB_08072695: - local_a5 = true; - } - } - break; - case CONDITION_ISTYPE: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - local_a5 = z1 == Condition->Parameters[1]; - break; - case CONDITION_ISCREATURE: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - local_a5 = z1 == 99; - break; - case CONDITION_ISPLAYER: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; -LAB_08072828: - pTVar5 = GetCreature((Object *)&z1); - local_a5 = false; - if (pTVar5 != (TCreature *)0x0) { - bVar4 = pTVar5->Type == PLAYER; - goto LAB_08072693; - } - } - break; - case CONDITION_HASFLAG: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Flag = Condition->Parameters[1]; - Object::getObjectType((Object *)&z1); - local_a5 = ObjectType::getFlag((ObjectType *)&z1,Flag); - break; - case CONDITION_HASTYPEATTRIBUTE: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Attribute = Condition->Parameters[1]; - Object::getObjectType((Object *)&z1); - uVar11 = ObjectType::getAttribute((ObjectType *)&z1,Attribute); - iVar7 = Condition->Parameters[2]; - uVar10 = Condition->Parameters[3]; - switch(iVar7) { - case 0x3c: -switchD_0807323b_caseD_3c: - local_a5 = (int)uVar11 < (int)uVar10; - break; - case 0x3d: -switchD_0807323b_caseD_3d: - local_a5 = uVar11 == uVar10; - break; - case 0x3e: -switchD_0807323b_caseD_3e: - local_a5 = (int)uVar10 < (int)uVar11; - break; - default: -switchD_0807323b_caseD_3f: - error(&DAT_080f79e0,iVar7,puVar16,puVar17); - local_a5 = false; - break; - case 0x47: -switchD_0807323b_caseD_47: - local_a5 = (int)uVar10 <= (int)uVar11; - break; - case 0x4c: -switchD_0807323b_caseD_4c: - local_a5 = (int)uVar11 <= (int)uVar10; - break; - case 0x4e: -switchD_0807323b_caseD_4e: - local_a5 = uVar11 != uVar10; - } - break; - case CONDITION_HASINSTANCEATTRIBUTE: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - uVar11 = Object::getAttribute(&local_2c,Condition->Parameters[1]); - iVar7 = Condition->Parameters[2]; - uVar10 = Condition->Parameters[3]; - switch(iVar7) { - case 0x3c: - goto switchD_0807323b_caseD_3c; - case 0x3d: - goto switchD_0807323b_caseD_3d; - case 0x3e: - goto switchD_0807323b_caseD_3e; - default: - goto switchD_0807323b_caseD_3f; - case 0x47: - goto switchD_0807323b_caseD_47; - case 0x4c: - goto switchD_0807323b_caseD_4c; - case 0x4e: - goto switchD_0807323b_caseD_4e; - } - case CONDITION_HASTEXT: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - __s2 = GetDynamicString(Condition->Parameters[1]); - uVar10 = Object::getAttribute(&local_2c,TEXTSTRING); - __s1 = GetDynamicString(uVar10); - iVar7 = strcmp(__s1,__s2); - local_a5 = iVar7 == 0; - break; - case CONDITION_ISPEACEFUL: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - pOVar8 = local_6c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - puVar15 = local_5c; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - pOVar13 = &local_2c; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar5 = GetCreature((Object *)&z1); - local_a5 = false; - if (pTVar5 != (TCreature *)0x0) { - iVar7 = (*pTVar5->_vptr_TCreature[4])(pTVar5,pOVar13,puVar16,puVar17,puVar15,pOVar8) - ; - cVar3 = (char)iVar7; -LAB_08072b84: - local_a5 = false; - if (cVar3 != '\0') goto LAB_08072695; - } - } - break; - case CONDITION_MAYLOGOUT: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar5 = GetCreature((Object *)&z1); - local_a5 = false; - if ((pTVar5 != (TCreature *)0x0) && (pTVar5->Type == PLAYER)) { - iVar7 = TCreature::LogoutPossible(pTVar5); - bVar4 = iVar7 == 0; - goto LAB_08072693; - } - } - break; - case CONDITION_HASPROFESSION: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar9 = (TPlayer *)GetCreature((Object *)&z1); - local_a5 = false; - if ((pTVar9 != (TPlayer *)0x0) && ((pTVar9->super_TCreature).Type == PLAYER)) { - bVar2 = TPlayer::GetEffectiveProfession(pTVar9); - bVar4 = (uint)bVar2 == Condition->Parameters[1]; - goto LAB_08072693; - } - } - break; - case CONDITION_HASLEVEL: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - puVar15 = local_5c; - local_3c[0] = User->ObjectID; - pOVar8 = local_6c; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar5 = GetCreature((Object *)&z1); - local_a6 = false; - if (pTVar5 != (TCreature *)0x0) { - iVar6 = TSkill::Get((pTVar5->super_TSkillBase).Skills[0]); - iVar7 = Condition->Parameters[2]; - switch(Condition->Parameters[1]) { - case 0x3c: - bVar4 = iVar6 < iVar7; - break; - case 0x3d: - bVar4 = iVar6 == iVar7; - break; - case 0x3e: - bVar4 = iVar7 < iVar6; - break; - default: - error(&DAT_080f79e0,Condition->Parameters[1],puVar16,puVar17,puVar15,pOVar8); - bVar4 = false; - break; - case 0x47: - bVar4 = iVar7 <= iVar6; - break; - case 0x4c: - bVar4 = iVar6 <= iVar7; - break; - case 0x4e: - bVar4 = iVar6 != iVar7; - } - if (bVar4) { - local_a6 = true; - } - } - local_a5 = local_a6; - } - break; - case CONDITION_HASRIGHT: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar5 = GetCreature((Object *)&z1); - local_a5 = false; - if ((pTVar5 != (TCreature *)0x0) && (pTVar5->Type == PLAYER)) { - cVar3 = CheckRight(pTVar5->ID,Condition->Parameters[1]); - goto LAB_08072b84; - } - } - break; - case CONDITION_HASQUESTVALUE: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - puVar16 = local_5c; - local_5c[0] = Obj2->ObjectID; - puVar15 = local_3c; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - pOVar8 = local_6c; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar9 = (TPlayer *)GetCreature((Object *)&z1); - local_a7 = false; - if ((pTVar9 != (TPlayer *)0x0) && ((pTVar9->super_TCreature).Type == PLAYER)) { - iVar6 = TPlayer::GetQuestValue(pTVar9,Condition->Parameters[1]); - iVar7 = Condition->Parameters[3]; - switch(Condition->Parameters[2]) { - case 0x3c: - bVar4 = iVar6 < iVar7; - break; - case 0x3d: - bVar4 = iVar6 == iVar7; - break; - case 0x3e: - bVar4 = iVar7 < iVar6; - break; - default: - error(&DAT_080f79e0,Condition->Parameters[2],puVar15,puVar17,puVar16,pOVar8); - bVar4 = false; - break; - case 0x47: - bVar4 = iVar7 <= iVar6; - break; - case 0x4c: - bVar4 = iVar6 <= iVar7; - break; - case 0x4e: - bVar4 = iVar6 != iVar7; - } - if (bVar4) { - local_a7 = true; - } - } - local_a5 = local_a7; - } - break; - case CONDITION_TESTSKILL: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - pOVar8 = local_6c; - puVar16 = local_5c; - local_5c[0] = Obj2->ObjectID; - puVar15 = local_3c; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar5 = GetCreature((Object *)&z1); - bVar4 = false; - iVar7 = Condition->Parameters[1]; - if ((-1 < iVar7) && (iVar7 < 0x19)) { - bVar4 = true; - } - if (bVar4) { - local_a5 = false; - if (pTVar5 != (TCreature *)0x0) { - iVar7 = (*(pTVar5->super_TSkillBase).Skills[iVar7]->_vptr_TSkill[9]) - ((pTVar5->super_TSkillBase).Skills[iVar7], - Condition->Parameters[2],Condition->Parameters[3],1); - cVar3 = (char)iVar7; - goto LAB_08072b84; - } - } - else { - error(&DAT_080f7a20,iVar7,puVar15,puVar17,puVar16,pOVar8); - } - } - break; - case CONDITION_COUNTOBJECTS: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - GetMapContainer((Object *)&z1); - uVar11 = CountObjectsInContainer((Object *)&z1); - iVar7 = Condition->Parameters[1]; - uVar10 = Condition->Parameters[2]; - switch(iVar7) { - case 0x3c: - goto switchD_0807323b_caseD_3c; - case 0x3d: - goto switchD_0807323b_caseD_3d; - case 0x3e: - goto switchD_0807323b_caseD_3e; - default: - goto switchD_0807323b_caseD_3f; - case 0x47: - goto switchD_0807323b_caseD_47; - case 0x4c: - goto switchD_0807323b_caseD_4c; - case 0x4e: - goto switchD_0807323b_caseD_4e; - } - case CONDITION_COUNTOBJECTSONMAP: - UnpackAbsoluteCoordinate(); - GetMapContainer((int)&z1,z2,x1); - uVar11 = CountObjectsInContainer((Object *)&z1); - iVar7 = Condition->Parameters[1]; - uVar10 = Condition->Parameters[2]; - puVar16 = (ulong *)x1; - puVar17 = (ulong *)y1; - switch(iVar7) { - case 0x3c: - goto switchD_0807323b_caseD_3c; - case 0x3d: - goto switchD_0807323b_caseD_3d; - case 0x3e: - goto switchD_0807323b_caseD_3e; - default: - goto switchD_0807323b_caseD_3f; - case 0x47: - goto switchD_0807323b_caseD_47; - case 0x4c: - goto switchD_0807323b_caseD_4c; - case 0x4e: - goto switchD_0807323b_caseD_4e; - } - case CONDITION_ISOBJECTTHERE: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID(local_6c,Condition->Parameters[1]); - goto LAB_080732ab; - case CONDITION_ISCREATURETHERE: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID(local_6c,99); -LAB_080732ab: - GetFirstSpecObject(); -LAB_080732b0: - Temp->ObjectID = (ulong)local_7c[0]; - local_a5 = Temp->ObjectID != NONE.ObjectID; - break; - case CONDITION_ISPLAYERTHERE: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID(local_6c,99); - GetFirstSpecObject(); - Temp->ObjectID = (ulong)local_7c[0]; - z1 = Temp->ObjectID; - if (z1 != NONE.ObjectID) goto LAB_08072828; - break; - case CONDITION_ISOBJECTININVENTORY: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 != 99) break; - ObjectType::setTypeID(local_6c,Condition->Parameters[1]); - pOVar8 = (ObjectType *)Object::getCreatureID(&local_2c); - GetInventoryObject((ulong)local_7c,pOVar8,(ulong)local_6c); - goto LAB_080732b0; - case CONDITION_ISPROTECTIONZONE: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - GetObjectCoordinates((Object *)&z1,&z2,&x1,&y1); - local_a5 = IsProtectionZone(); - break; - case CONDITION_ISHOUSE: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - GetObjectCoordinates((Object *)&z1,&z2,&x1,&y1); - local_a5 = IsHouse(z2,x1,y1); - break; - case CONDITION_ISHOUSEOWNER: - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - GetObjectCoordinates((Object *)&z1,&z2,&x1,&y1); - local_6c[0].TypeID = Temp->ObjectID; - local_5c[0] = Obj2->ObjectID; - local_4c[0] = Obj1->ObjectID; - local_3c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - if (z1 == 99) { - z1 = local_2c.ObjectID; - pTVar9 = (TPlayer *)GetCreature((Object *)&z1); - local_a5 = false; - if ((pTVar9 != (TPlayer *)0x0) && ((pTVar9->super_TCreature).Type == PLAYER)) { - HouseID = GetHouseID(z2,x1,y1); - cVar3 = IsOwner(HouseID,pTVar9); - goto LAB_08072b84; - } - } - break; - case CONDITION_ISDRESSED: - local_6c[0].TypeID = Temp->ObjectID; - puVar17 = local_4c; - local_5c[0] = Obj2->ObjectID; - puVar16 = local_3c; - local_4c[0] = Obj1->ObjectID; - puVar15 = local_5c; - local_3c[0] = User->ObjectID; - pOVar8 = local_6c; - GetEventObject(); - local_2c.ObjectID = local_7c[0].ObjectID; - z1 = local_7c[0].ObjectID; - Object::getObjectType((Object *)&z1); - uVar14 = 0x2e; - bVar4 = ObjectType::getFlag((ObjectType *)&z1,CLOTHES); - if (bVar4) { - z1 = local_2c.ObjectID; - uVar10 = GetObjectBodyPosition((Object *)&z1); - Object::getObjectType(local_7c); - uVar11 = ObjectType::getAttribute((ObjectType *)local_7c,BODYPOSITION); - local_a5 = uVar10 == uVar11; - } - else { - error(&DAT_080f7a60,uVar14,puVar16,puVar17,puVar15,pOVar8); - } - break; - case CONDITION_RANDOM: - lVar12 = random(); - local_a5 = lVar12 <= Condition->Parameters[0]; - break; - default: - error("CheckCondition: Unbekannte Bedingung %d.\n",Condition->Condition); - goto LAB_08072659; - } - MVar1 = Condition->Modifier; - if (MVar1 == MODIFIER_INVERT) { - local_a5 = (bool)(local_a5 ^ 1); - } - else { - if ((int)MVar1 < 2) { - if (MVar1 == MODIFIER_NORMAL) { - return local_a5; - } - } - else if (MVar1 == MODIFIER_TRUE) { - return true; - } -LAB_08072659: - local_a5 = false; - } - return local_a5; -} - - - -Object CreateObject(Object *Con,ObjectType *Type,ulong Value) - -{ - bool bVar1; - ObjectType *Type_00; - RESULT r; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 08073896 to 08073934 has its CatchHandler @ 08073937 - Object::getObjectType(local_2c); - bVar1 = false; - if ((0 < (int)local_2c[0].ObjectID) && ((int)local_2c[0].ObjectID < 0xb)) { - bVar1 = true; - } - if (bVar1) { - ObjectType::setTypeID((ObjectType *)local_2c,*(int *)Value); - local_3c[0].ObjectID = Type->TypeID; - Type_00 = (ObjectType *)GetObjectCreatureID(local_3c); - CreateAtCreature((ulong)Con,Type_00,(ulong)local_2c); - } - else { - ObjectType::setTypeID((ObjectType *)local_3c,*(int *)Value); - local_2c[0].ObjectID = Type->TypeID; - Create(Con,(ObjectType *)local_2c,(ulong)local_3c); - } - return (Object)(ulong)Con; -} - - - -void ChangeObject(Object *Obj,ObjectType *NewType,ulong Value) - -{ - bool bVar1; - ulong uVar2; - RESULT r; - char *Text; - int iVar3; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object Con; - - // try { // try from 08073a18 to 08073a5c has its CatchHandler @ 08073ce0 - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getContainer(&local_2c); - bVar1 = Object::exists(Obj); - if (bVar1) { - // try { // try from 08073a6f to 08073b27 has its CatchHandler @ 08073b42 - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE); - if ((bVar1) && (uVar2 = Object::getAttribute(Obj,AMOUNT), 1 < uVar2)) { - local_3c[0].ObjectID = NONE.ObjectID; - uVar2 = Object::getAttribute(Obj,AMOUNT); - local_4c[0].ObjectID = local_2c.ObjectID; - local_5c[0] = (Object)Obj->ObjectID; - Move(0,local_5c,local_4c,uVar2 - 1,true,local_3c); - } - ObjectType::setTypeID((ObjectType *)local_5c,NewType->TypeID); - local_4c[0] = (Object)Obj->ObjectID; - Change(local_4c,(ObjectType *)local_5c,Value); - return; - } - iVar3 = NewType->TypeID; - Text = &DAT_080f7ba0; - } - else { - iVar3 = NewType->TypeID; - Text = &DAT_080f7b40; - } - error(Text,iVar3); - return; -} - - - -void MoveOneObject(Object *Obj,Object *Con) - -{ - bool bVar1; - RESULT r; - char *Text; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - if (bVar1) { - bVar1 = Object::exists(Con); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { - Object::getObjectType(local_2c); - if ((local_2c[0].ObjectID != 99) || - (Object::getObjectType(local_2c), local_2c[0].ObjectID == 0)) { - // try { // try from 08073da1 to 08073e39 has its CatchHandler @ 08073e4c - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,LIQUIDPOOL); - if (!bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,MAGICFIELD); - if (!bVar1) { - local_2c[0].ObjectID = NONE.ObjectID; - local_3c[0] = (Object)Con->ObjectID; - z = Obj->ObjectID; - Move(0,(Object *)&z,local_3c,-1,true,local_2c); - return; - } - } - local_2c[0] = (Object)Obj->ObjectID; - Delete(local_2c,-1); - return; - } - Text = "MoveOneObject: \"Con\" ist kein MapContainer.\n"; - goto LAB_08073d18; - } - } - Text = "MoveOneObject: \"Con\" ist kein Container.\n"; - } - else { - Text = &DAT_080f7c60; - } -LAB_08073d18: - error(Text); - return; -} - - - -void MoveAllObjects(Object *Obj,Object *Dest,Object *Exclude,bool MoveUnmovable) - -{ - bool bVar1; - Object *pOVar2; - bool MoveUnmovable_local; - int x; - int y; - int z; - Object local_4c; - ObjectType Type; - Object local_3c [4]; - Object local_2c [7]; - - local_2c[0].ObjectID = NONE.ObjectID; - if (Obj->ObjectID != NONE.ObjectID) { - pOVar2 = Dest; - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID == 0) { - local_2c[0] = (Object)Exclude->ObjectID; - local_3c[0] = (Object)Dest->ObjectID; - Object::getNextObject(&local_4c); - MoveAllObjects(&local_4c,local_3c,local_2c,MoveUnmovable); - local_4c = (Object)Exclude->ObjectID; - if (Obj->ObjectID != local_4c.ObjectID) { - Object::getObjectType(&local_4c); - // try { // try from 08073fb1 to 0807408e has its CatchHandler @ 08074094 - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,LIQUIDPOOL); - if (!bVar1) { - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,MAGICFIELD); - if (!bVar1) { - if (!MoveUnmovable) { - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,UNMOVE); - if (bVar1) { - return; - } - } - local_3c[0].ObjectID = NONE.ObjectID; - local_2c[0] = (Object)Dest->ObjectID; - z = Obj->ObjectID; - Move(0,(Object *)&z,local_2c,-1,true,local_3c); - return; - } - } - local_3c[0] = (Object)Obj->ObjectID; - Delete(local_3c,-1); - } - } - else { - error("MoveAllObjects: \"Dest\" ist kein Mapcontainer.\n",pOVar2); - } - } - return; -} - - - -void DeleteAllObjects(Object *Obj,Object *Exclude,bool DeleteUnmovable) - -{ - bool bVar1; - RESULT r; - int iStack_48; - bool DeleteUnmovable_local; - int x; - int y; - int z; - Object local_2c [7]; - - if (Obj->ObjectID != NONE.ObjectID) { - local_2c[0] = (Object)Exclude->ObjectID; - Object::getNextObject((Object *)&z); - DeleteAllObjects((Object *)&z,local_2c,DeleteUnmovable); - z = Exclude->ObjectID; - if (Obj->ObjectID != z) { - Object::getObjectType((Object *)&z); - if (z == 99) { - z = Obj->ObjectID; - GetObjectCoordinates((Object *)&z,&stack0xffffffb8,&x,&y); - error(&DAT_080f7e00,iStack_48,x,y); - } - else { - if (!DeleteUnmovable) { - // try { // try from 080741bb to 08074244 has its CatchHandler @ 0807429b - Object::getObjectType((Object *)&z); - bVar1 = ObjectType::getFlag((ObjectType *)&z,UNMOVE); - if (bVar1) { - Object::getObjectType((Object *)&z); - bVar1 = ObjectType::getFlag((ObjectType *)&z,LIQUIDPOOL); - if (!bVar1) { - Object::getObjectType((Object *)&z); - bVar1 = ObjectType::getFlag((ObjectType *)&z,MAGICFIELD); - if (!bVar1) { - return; - } - } - } - } - z = Obj->ObjectID; - Delete((Object *)&z,-1); - } - } - } - return; -} - - - -void ClearField(Object *Obj,Object *Exclude) - -{ - bool bVar1; - bool bVar2; - Object *this; - Object *Exclude_00; - int local_58; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c [7]; - - bVar1 = Object::exists(Obj); - if (!bVar1) { - error("ClearField: Objekt existiert nicht.\n"); - return; - } - local_2c[0] = (Object)Obj->ObjectID; - GetObjectCoordinates(local_2c,&local_58,&x,&y); - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { - this = (Object *)&z; - local_2c[0] = (Object)Exclude->ObjectID; - GetMapContainer((int)local_3c,local_58 + 1,x); - Object::getNextObject(this); - Exclude_00 = local_2c; - goto LAB_080743c6; - } - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { -LAB_08074550: - z = Exclude->ObjectID; - x = x + 1; -LAB_0807449d: - GetMapContainer((int)local_3c,local_58,x); - Object::getNextObject(local_2c); - } - else { - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { -LAB_08074594: - z = Exclude->ObjectID; - local_58 = local_58 + -1; - goto LAB_0807449d; - } - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { - z = Exclude->ObjectID; - x = x + -1; - goto LAB_0807449d; - } - bVar1 = JumpPossible(local_58 + 1,x,y,false); - if (bVar1) { - z = Exclude->ObjectID; - local_58 = local_58 + 1; - goto LAB_0807449d; - } - bVar1 = JumpPossible(local_58,x + 1,y,false); - if (bVar1) goto LAB_08074550; - bVar1 = JumpPossible(local_58 + -1,x,y,false); - if (bVar1) goto LAB_08074594; - bVar1 = JumpPossible(local_58,x + -1,y,false); - if (!bVar1) { - return; - } - z = Exclude->ObjectID; - GetMapContainer((int)local_3c,local_58,x + -1); - Object::getNextObject(local_2c); - } - Exclude_00 = (Object *)&z; - this = local_2c; -LAB_080743c6: - MoveAllObjects(this,local_3c,Exclude_00,true); - return; -} - - - -void LoadDepotBox(ulong CreatureID,int Nr,Object *Con) - -{ - bool bVar1; - TCreature *pTVar2; - int iVar3; - int iVar4; - TCreature *cr; - char *pcVar5; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 0807470b to 08074872 has its CatchHandler @ 08074890 - pTVar2 = GetCreature(CreatureID); - if (pTVar2 == (TCreature *)0x0) { - pcVar5 = "moveuse::LoadDepotBox: Kreatur nicht gefunden.\n"; - } - else { - bVar1 = Object::exists(Con); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { - if (pTVar2->Type == PLAYER) { - local_2c[0] = (Object)Con->ObjectID; - LoadDepot((TPlayerData *)pTVar2[1].super_TSkillBase.TimerList[10],Nr,local_2c); - local_2c[0] = (Object)Con->ObjectID; - pTVar2[1].super_TSkillBase.TimerList[6] = (TSkill *)local_2c[0].ObjectID; - pTVar2[1].super_TSkillBase.TimerList[7] = (TSkill *)Nr; - local_3c[0] = (Object)Con->ObjectID; - iVar3 = CountObjects(local_3c); - iVar3 = iVar3 + -1; - bVar1 = CheckRight(pTVar2->ID,PREMIUM_ACCOUNT); - iVar4 = GetDepotSize(Nr,bVar1); - pTVar2[1].super_TSkillBase.TimerList[8] = (TSkill *)(iVar4 - iVar3); - print(); - pcVar5 = "s"; - if (iVar3 == 1) { - pcVar5 = ""; - } - SendMessage(pTVar2->Connection,0x15,"Your depot contains %d item%s.",iVar3, - pcVar5); - if (-1 < (int)pTVar2[1].super_TSkillBase.TimerList[8]) { - return; - } - SendMessage(pTVar2->Connection,0x16, - "Your depot is full. Remove surplus items before storing new ones.", - iVar3,pcVar5); - return; - } - pcVar5 = "moveuse::LoadDepotBox: Kreatur ist kein Spieler.\n"; - } - else { - pcVar5 = &DAT_080f8020; - } - } - else { - pcVar5 = &DAT_080f7ee0; - } - } - error(pcVar5); - return; -} - - - -void SaveDepotBox(ulong CreatureID,int Nr,Object *Con) - -{ - bool bVar1; - TCreature *pTVar2; - int iVar3; - TCreature *cr; - char *Text; - int Count; - Object Obj; - Object local_2c [7]; - - // try { // try from 080748cb to 08074a1a has its CatchHandler @ 08074a40 - pTVar2 = GetCreature(CreatureID); - if (pTVar2 == (TCreature *)0x0) { - Text = "moveuse::SaveDepotBox: Kreatur nicht gefunden.\n"; - } - else { - bVar1 = Object::exists(Con); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { - if (pTVar2->Type == PLAYER) { - local_2c[0] = (Object)Con->ObjectID; - iVar3 = CountObjects(local_2c); - Log("game",&DAT_080f8120,Nr,pTVar2->Name,iVar3 + -1); - print(); - local_2c[0] = (Object)Con->ObjectID; - SaveDepot((TPlayerData *)pTVar2[1].super_TSkillBase.TimerList[10],Nr,local_2c); - Count = NONE.ObjectID; - pTVar2[1].super_TSkillBase.TimerList[6] = (TSkill *)NONE.ObjectID; - while( true ) { - local_2c[0] = (Object)Con->ObjectID; - GetFirstContainerObject((Object *)&Count); - if (Count == NONE.ObjectID) break; - local_2c[0].ObjectID = Count; - Delete(local_2c,-1); - } - return; - } - Text = "moveuse::SaveDepotBox: Kreatur ist kein Spieler.\n"; - } - else { - Text = &DAT_080f81c0; - } - } - else { - Text = &DAT_080f80a0; - } - } - error(Text); - return; -} - - - -void SendMail(Object *Obj) - -{ - uint *Text_00; - TPlayer *pTVar1; - ulong uVar2; - bool bVar3; - RESULT r_1; - ulong uVar4; - char *pcVar5; - int iVar6; - TDelayedMail *pTVar7; - uchar *__dest; - char *Text; - uint *puVar8; - uint *puVar9; - char cVar10; - uint uVar11; - uint uVar12; - int pos; - int iVar13; - int pos2; - int iVar14; - int *this; - bool PlayerOnline; - int DepotNumber; - TPlayer *local_280; - TPlayer *Player; - char Town [256]; - char Addressee [256]; - undefined1 local_6c [4]; - TDynamicWriteBuffer Buffer; - Object Label; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 08074a78 to 08074d69 has its CatchHandler @ 08075210 - bVar3 = Object::exists(Obj); - if (bVar3) { - bVar3 = false; - Object::getObjectType(local_2c); - GetSpecialObject((SPECIALMEANING)local_3c); - ObjectType::setTypeID((ObjectType *)local_4c,local_3c[0].ObjectID); - if (local_2c[0].ObjectID != local_4c[0].ObjectID) { - Object::getObjectType(local_4c); - GetSpecialObject((SPECIALMEANING)&Buffer.super_TWriteBuffer.Position); - ObjectType::setTypeID((ObjectType *)local_6c,Buffer.super_TWriteBuffer.Position); - if ((undefined1 [4])local_4c[0].ObjectID != local_6c) { - bVar3 = true; - } - } - if (!bVar3) { - print(); - Object::getObjectType((Object *)local_6c); - GetSpecialObject((SPECIALMEANING)&Buffer.super_TWriteBuffer.Position); - this = (int *)Obj; - if (local_6c != (undefined1 [4])Buffer.super_TWriteBuffer.Position) { - local_4c[0] = (Object)Obj->ObjectID; - GetFirstContainerObject((Object *)&Buffer.super_TWriteBuffer.Position); - while( true ) { - bVar3 = false; - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - if (Buffer.super_TWriteBuffer.Position != NONE.ObjectID) { - Object::getObjectType(local_3c); - GetSpecialObject((SPECIALMEANING)local_2c); - ObjectType::setTypeID((ObjectType *)(Addressee + 0xfc),local_2c[0].ObjectID) - ; - if (local_3c[0].ObjectID != Addressee._252_4_) { - bVar3 = true; - } - } - if (!bVar3) break; - Object::getNextObject(local_4c); - Addressee._252_4_ = local_4c[0].ObjectID; - Buffer.super_TWriteBuffer.Position = Addressee._252_4_; - } - Addressee._252_4_ = NONE.ObjectID; - if (Buffer.super_TWriteBuffer.Position == NONE.ObjectID) { - return; - } - this = &Buffer.super_TWriteBuffer.Position; - } - uVar4 = Object::getAttribute((Object *)this,TEXTSTRING); - pcVar5 = GetDynamicString(uVar4); - if (pcVar5 != (char *)0x0) { - cVar10 = *pcVar5; - iVar13 = 0; - if ((cVar10 != '\n') && (cVar10 != '\0')) { - while( true ) { - Town[iVar13 + 0xfc] = cVar10; - iVar13 = iVar13 + 1; - cVar10 = pcVar5[iVar13]; - if (cVar10 == '\n') break; - if ((cVar10 == '\0') || (0xff < iVar13)) break; - } - } - iVar14 = 0; - Town[iVar13 + 0xfc] = '\0'; - if ((pcVar5[iVar13 + 1] != '\n') && (iVar6 = iVar13, pcVar5[iVar13 + 1] != '\0')) { - do { - Town[iVar14 + -4] = pcVar5[iVar6 + 1]; - iVar14 = iVar14 + 1; - if ((pcVar5[iVar14 + iVar13 + 1] == '\n') || - (pcVar5[iVar14 + iVar13 + 1] == '\0')) break; - iVar6 = iVar14 + iVar13; - } while (iVar14 < 0x100); - } - Town[iVar14 + -4] = '\0'; - Text_00 = (uint *)(Town + 0xfc); - Trim((char *)Text_00); - Trim((char *)&Player); - puVar9 = Text_00; - if (Town[0xfc] != '\0') { - do { - puVar8 = puVar9; - uVar11 = *puVar8 + 0xfefefeff & ~*puVar8; - uVar12 = uVar11 & 0x80808080; - puVar9 = puVar8 + 1; - } while (uVar12 == 0); - bVar3 = (uVar11 & 0x8080) == 0; - if (bVar3) { - uVar12 = uVar12 >> 0x10; - } - if (bVar3) { - puVar9 = (uint *)((int)puVar8 + 6); - } - if (((char *)((int)puVar9 + - ((-3 - (uint)CARRY1((byte)uVar12,(byte)uVar12)) - (int)Text_00)) < - (char *)0x1e) && ((char)Player != '\0')) { - Log("game","Post an %s in %s.\n",Text_00,&Player); - iVar13 = GetDepotNumber((char *)&Player); - if (iVar13 != -1) { - iVar14 = IdentifyPlayer((char *)Text_00,true,true,&local_280); - bVar3 = iVar14 == 0; - if (bVar3) { - uVar4 = (local_280->super_TCreature).ID; - } - else { - // try { // try from 08075019 to 08075139 has its CatchHandler @ 08075210 - uVar4 = GetCharacterID((char *)Text_00); - if (uVar4 == 0) { - return; - } - } - uVar2 = Addressee._252_4_; - if ((bVar3) && (local_280->DepotNr == iVar13)) { - local_6c = (undefined1 [4])NONE.ObjectID; - Addressee[0xfc] = (undefined1)NONE.ObjectID; - Addressee[0xfd] = NONE.ObjectID._1_1_; - Addressee[0xfe] = NONE.ObjectID._2_1_; - Addressee[0xff] = NONE.ObjectID._3_1_; - uVar2 = (ulong)local_6c; - if ((local_280->Depot).ObjectID != NONE.ObjectID) { - print(); - local_6c = (undefined1 [4])NONE.ObjectID; - Buffer.super_TWriteBuffer.Position = (local_280->Depot).ObjectID - ; - local_4c[0] = (Object)Obj->ObjectID; - // try { // try from 08074ef3 to 08075003 has its CatchHandler @ 08075152 - Move(0,local_4c,(Object *)&Buffer.super_TWriteBuffer.Position,-1 - ,true,(Object *)local_6c); - Object::getObjectType((Object *)local_6c); - GetSpecialObject((SPECIALMEANING) - &Buffer.super_TWriteBuffer.Position); - GetSpecialObject((SPECIALMEANING) - &Buffer.super_TWriteBuffer.Position); - local_4c[0] = (Object)Obj->ObjectID; - Change(local_4c,(ObjectType *) - &Buffer.super_TWriteBuffer.Position,0); - Log("game","Post an %s in %s versandt.\n",Text_00,&Player); - pTVar1 = local_280; - local_6c = (undefined1 [4])Obj->ObjectID; - iVar13 = CountObjects((Object *)local_6c); - pTVar1->DepotSpace = pTVar1->DepotSpace - iVar13; - iVar13 = local_280->DepotSpace; - print(); - SendMessage((local_280->super_TCreature).Connection,0x16, - "New mail has arrived.",iVar13); - print(); - return; - } - } - Addressee._252_4_ = uVar2; - print(); - Object::getObjectType((Object *)local_6c); - GetSpecialObject((SPECIALMEANING)&Buffer.super_TWriteBuffer.Position); - GetSpecialObject((SPECIALMEANING)&Buffer.super_TWriteBuffer.Position); - local_4c[0] = (Object)Obj->ObjectID; - Change(local_4c,(ObjectType *)&Buffer.super_TWriteBuffer.Position,0); - // try { // try from 08074d78 to 08074d7c has its CatchHandler @ 08075205 - TDynamicWriteBuffer::TDynamicWriteBuffer - ((TDynamicWriteBuffer *)local_6c,0x400); - Buffer.super_TWriteBuffer.Position = Obj->ObjectID; - // try { // try from 08074d97 to 08074de3 has its CatchHandler @ 080751b6 - SaveObjects((Object *)&Buffer.super_TWriteBuffer.Position, - (TWriteStream *)local_6c,true); - Buffer.super_TWriteBuffer.Position = Obj->ObjectID; - Delete((Object *)&Buffer.super_TWriteBuffer.Position,-1); - pTVar7 = vector<>::operator()(&DelayedMail,DelayedMails); - pTVar7->CharacterID = uVar4; - pTVar7->DepotNumber = iVar13; - pTVar7->PacketSize = Buffer.super_TWriteBuffer.Size; - __dest = (uchar *)operator_new__(Buffer.super_TWriteBuffer.Size); - pTVar7->Packet = __dest; - memcpy(__dest,Buffer.super_TWriteBuffer.super_TWriteStream. - _vptr_TWriteStream,pTVar7->PacketSize); - // try { // try from 08074e03 to 08074e07 has its CatchHandler @ 08075205 - TDynamicWriteBuffer::~TDynamicWriteBuffer - ((TDynamicWriteBuffer *)local_6c, - (int)Buffer.super_TWriteBuffer.super_TWriteStream. - _vptr_TWriteStream); - DelayedMails = DelayedMails + 1; - // try { // try from 08074e2b to 08074eaa has its CatchHandler @ 08075210 - Log("game",&DAT_080f82c0,Text_00,&Player); - print(); - if (bVar3) { - SendMails(local_280->PlayerData); - } - else { - LoadCharacterOrder(uVar4); - } - } - } - } - } - } - } - else { - error(&DAT_080f8240); - } - return; -} - - - -void SendMails(TPlayerData *PlayerData) - -{ - __pid_t _Var1; - TDelayedMail *pTVar2; - uint uVar3; - uchar *__dest; - TDelayedMail *pTVar4; - int iVar5; - TDelayedMail *D; - int i; - int i_00; - bool bVar6; - char *Text; - uchar *NewDepot; - int NewDepotSize; - ushort local_3c; - bool DepotEmpty; - undefined1 local_2c [4]; - TWriteBuffer Buffer; - - if (PlayerData == (TPlayerData *)0x0) { - Text = "SendMails: PlayerData ist NULL.\n"; - } - else if (PlayerData->CharacterID == 0) { - Text = "SendMails: Slot ist nicht belegt.\n"; - } - else { - _Var1 = getpid(); - if (PlayerData->Locked == _Var1) { - if (DelayedMails < 1) { - return; - } - i_00 = 0; - do { - pTVar2 = vector<>::operator()(&DelayedMail,i_00); - if (pTVar2->CharacterID == PlayerData->CharacterID) { - iVar5 = pTVar2->DepotNumber; - bVar6 = false; - if ((-1 < iVar5) && (iVar5 < 9)) { - bVar6 = true; - } - if (!bVar6) { - error(&DAT_080f84e0,iVar5); - iVar5 = 0; - pTVar2->DepotNumber = 0; - } - bVar6 = PlayerData->Depot[iVar5] != (uchar *)0x0; - if (bVar6) { - uVar3 = pTVar2->PacketSize + PlayerData->DepotSize[iVar5]; - } - else { - uVar3 = pTVar2->PacketSize + 5; - } - __dest = (uchar *)operator_new__(uVar3); - memcpy(__dest,pTVar2->Packet,pTVar2->PacketSize); - if (pTVar2->Packet != (uchar *)0x0) { - operator_delete__(pTVar2->Packet); - } - if (bVar6) { - memcpy(__dest + pTVar2->PacketSize,PlayerData->Depot[pTVar2->DepotNumber], - PlayerData->DepotSize[pTVar2->DepotNumber]); - iVar5 = pTVar2->DepotNumber; - if (PlayerData->Depot[iVar5] != (uchar *)0x0) { - operator_delete__(PlayerData->Depot[iVar5]); - goto LAB_0807537c; - } - } - else { - TWriteBuffer::TWriteBuffer - ((TWriteBuffer *)local_2c,__dest + pTVar2->PacketSize,5); - GetSpecialObject((SPECIALMEANING)&local_3c); - TWriteBuffer::writeWord((TWriteBuffer *)local_2c,local_3c); - TWriteBuffer::writeByte((TWriteBuffer *)local_2c,0xff); - TWriteBuffer::writeWord((TWriteBuffer *)local_2c,0xffff); -LAB_0807537c: - iVar5 = pTVar2->DepotNumber; - } - PlayerData->Depot[iVar5] = __dest; - iVar5 = pTVar2->DepotNumber; - PlayerData->Dirty = true; - PlayerData->DepotSize[iVar5] = uVar3; - Log("game","Post an %s zugestellt.\n",PlayerData->Name); - if (i_00 != DelayedMails + -1) { - pTVar2 = vector<>::operator()(&DelayedMail,i_00); - pTVar4 = vector<>::operator()(&DelayedMail,DelayedMails + -1); - pTVar2->CharacterID = pTVar4->CharacterID; - pTVar2->DepotNumber = pTVar4->DepotNumber; - pTVar2->Packet = pTVar4->Packet; - pTVar2->PacketSize = pTVar4->PacketSize; - } - DelayedMails = DelayedMails + -1; - i_00 = i_00 + -1; - } - i_00 = i_00 + 1; - if (DelayedMails <= i_00) { - return; - } - } while( true ); - } - Text = "SendMails: Slot ist nicht vom GameThread gesperrt.\n"; - } - error(Text); - return; -} - - - -void TextEffect(char *Text,int x,int y,int z,int Radius) - -{ - TConnection *this; - ulong ID; - ulong CharacterID; - TPlayer *pTVar1; - TConnection *Connection; - int local_58; - int destX; - int destY; - int destZ; - TFindCreatures Search; - - if (Text == (char *)0x0) { - error("TextEffect: Text existiert nicht.\n"); - } - else { - TFindCreatures::TFindCreatures((TFindCreatures *)&destZ,Radius,Radius,x,y,1); - while( true ) { - CharacterID = TFindCreatures::getNext((TFindCreatures *)&destZ); - if (CharacterID == 0) break; - pTVar1 = GetPlayer(CharacterID); - if ((pTVar1 != (TPlayer *)0x0) && - (this = (pTVar1->super_TCreature).Connection, this != (TConnection *)0x0)) { - TConnection::GetPosition(this,&local_58,&destX,&destY); - if (((7 < Radius) || (z == destY)) && - (((0x1e < Radius || (z == destY)) || ((z < 8 && (destY < 8)))))) { - SendTalk(this,0,"",0x10,x,y,z,Text); - } - } - } - } - return; -} - - - -void ExecuteAction(EventType Event,TMoveUseAction *Action,Object *User,Object *Obj1,Object *Obj2, - Object *Temp) - -{ - bool bVar1; - ulong uVar2; - TPlayer *pTVar3; - undefined4 *puVar4; - char *__s; - size_t sVar5; - TCreature *pTVar6; - ulong uVar7; - int iVar8; - uint *puVar9; - uint *puVar10; - RESULT r; - uint uVar11; - uint uVar12; - TCreature *cr; - bool bVar13; - char *pcVar14; - ActionType AVar15; - Object *pOVar16; - INSTANCEATTRIBUTE Attribute; - ulong *puVar17; - Object *pOVar18; - Object *pOVar19; - Object *pOVar20; - int local_1c4; - int pos; - char *Text2; - TCreature *cr2; - int dx; - int dy; - int dz; - int x; - int y; - int z; - Object local_18c [4]; - Object local_17c [4]; - Object local_16c [4]; - Object local_15c [4]; - ulong local_14c [4]; - uint local_13c; - char Text [256]; - Object Con; - Object local_2c; - Object Obj; - - Text[0xfc] = '\0'; - Text[0xfd] = '\0'; - Text[0xfe] = '\0'; - Text[0xff] = '\0'; - local_2c.ObjectID = 0; - switch(Action->Action) { - case ACTION_CREATEONMAP: - // try { // try from 08075619 to 08077e1c has its CatchHandler @ 08077e32 - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_16c,Action->Parameters[1]); - GetMapContainer((int)local_17c,dz,x); - CreateObject(local_15c,(ObjectType *)local_17c,(ulong)local_16c); - Temp->ObjectID = (ulong)local_15c[0]; - break; - case ACTION_CREATE: - local_15c[0] = (Object)Temp->ObjectID; - local_14c[0] = Obj2->ObjectID; - local_18c[0] = (Object)Obj1->ObjectID; - z = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_16c[0].ObjectID; - local_17c[0].ObjectID = local_16c[0].ObjectID; - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - Object::getContainer(local_16c); - CreateObject(local_18c,(ObjectType *)local_16c,(ulong)local_17c); - Temp->ObjectID = (ulong)local_18c[0]; - break; - case ACTION_MONSTERONMAP: - UnpackAbsoluteCoordinate(); - iVar8 = Action->Parameters[1]; - goto LAB_080757f5; - case ACTION_MONSTER: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - iVar8 = Action->Parameters[1]; -LAB_080757f5: - CreateMonster(iVar8,dz,x,y,0,0,true); - break; - case ACTION_EFFECTONMAP: - UnpackAbsoluteCoordinate(); - GetMapContainer((int)&z,dz,x); - goto LAB_08075945; - case ACTION_EFFECT: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetMapContainer((Object *)&z); -LAB_08075945: - GraphicalEffect((Object *)&z,Action->Parameters[1]); - break; - case ACTION_TEXTONMAP: - UnpackAbsoluteCoordinate(); - pcVar14 = GetDynamicString(Action->Parameters[1]); - goto LAB_08075a34; - case ACTION_TEXT: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - pcVar14 = GetDynamicString(Action->Parameters[1]); -LAB_08075a34: - TextEffect(pcVar14,dz,x,y,Action->Parameters[2]); - break; - case ACTION_CHANGEONMAP: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - GetFirstSpecObject(); - Temp->ObjectID = (ulong)local_18c[0]; - z = NONE.ObjectID; - if (Temp->ObjectID == NONE.ObjectID) { - iVar8 = Action->Parameters[1]; - pcVar14 = "ExecuteAction (CHANGEONMAP): Kein Objekt %d auf [%d,%d,%d].\n"; -LAB_08075be0: - NONE.ObjectID = z; - error(pcVar14,iVar8,dz,x,y); - return; - } - ObjectType::setTypeID((ObjectType *)&z,Action->Parameters[2]); - local_18c[0] = (Object)Temp->ObjectID; - uVar7 = Action->Parameters[3]; - goto LAB_08075c18; - case ACTION_CHANGE: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - ObjectType::setTypeID((ObjectType *)&z,Action->Parameters[1]); - local_18c[0].ObjectID = local_2c.ObjectID; - uVar7 = Action->Parameters[2]; - goto LAB_08075c18; - case ACTION_CHANGEREL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - UnpackRelativeCoordinate(); - dz = (int)(cr2->super_TSkillBase).Skills + dz + -4; - x = x + dx; - y = y + dy; - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[2]); - GetFirstSpecObject(); - Temp->ObjectID = (ulong)local_18c[0]; - z = NONE.ObjectID; - if (Temp->ObjectID == NONE.ObjectID) { - iVar8 = Action->Parameters[2]; - pcVar14 = "ExecuteAction (CHANGEREL): Kein Objekt %d auf [%d,%d,%d].\n"; - goto LAB_08075be0; - } - ObjectType::setTypeID((ObjectType *)&z,Action->Parameters[3]); - local_18c[0] = (Object)Temp->ObjectID; - uVar7 = Action->Parameters[4]; -LAB_08075c18: - ChangeObject(local_18c,(ObjectType *)&z,uVar7); - break; - case ACTION_SETATTRIBUTE: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - uVar7 = Action->Parameters[2]; - Attribute = Action->Parameters[1]; - goto LAB_08075f26; - case ACTION_CHANGEATTRIBUTE: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - uVar7 = Object::getAttribute(&local_2c,Action->Parameters[1]); - uVar7 = uVar7 + Action->Parameters[2]; - if ((int)uVar7 < 1) { - dz = uVar7; - uVar7 = Object::getAttribute(&local_2c,Action->Parameters[1]); - uVar7 = (ulong)(uVar7 != 0); - } - Attribute = Action->Parameters[1]; - dz = uVar7; - goto LAB_08075f26; - case ACTION_SETQUESTVALUE: - pOVar18 = local_15c; - local_17c[0] = (Object)Temp->ObjectID; - pOVar19 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pOVar20 = local_17c; - GetEventObject(); - pOVar16 = &local_2c; - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getObjectType((Object *)&z); - if (z == 99) { - z = local_2c.ObjectID; - pTVar3 = (TPlayer *)GetCreature((Object *)&z); - if ((pTVar3 != (TPlayer *)0x0) && ((pTVar3->super_TCreature).Type == PLAYER)) { - TPlayer::SetQuestValue(pTVar3,Action->Parameters[1],Action->Parameters[2]); - return; - } - pcVar14 = - "ExecuteAction (SETQUESTVALUE): Kreatur existiert nicht oder ist kein Spieler.\n"; -LAB_08076102: - error(pcVar14,pOVar16,puVar17,pOVar18,pOVar19,pOVar20); - return; - } - Object::getObjectType((Object *)&z); - pcVar14 = "ExecuteAction (SETQUESTVALUE): Objekt ist keine Kreatur, sondern Typ %ld.\n"; - AVar15 = z; - goto switchD_080755eb_default; - case ACTION_DAMAGE: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - Text2 = (char *)0x0; - local_2c.ObjectID = local_18c[0].ObjectID; - bVar13 = local_18c[0].ObjectID != NONE.ObjectID; - z = NONE.ObjectID; - local_18c[0].ObjectID = NONE.ObjectID; - if (bVar13) { - Object::getObjectType(local_18c); - if (local_18c[0].ObjectID == 99) { - local_18c[0].ObjectID = local_2c.ObjectID; - Text2 = (char *)GetCreature(local_18c); - } - Object::getObjectType(local_18c); - bVar13 = ObjectType::getFlag((ObjectType *)local_18c,MAGICFIELD); - if ((bVar13) && (uVar7 = Object::getAttribute(&local_2c,RESPONSIBLE), uVar7 != 0)) { - local_18c[0].ObjectID = local_2c.ObjectID; - uVar7 = CronInfo(local_18c,false); - Object::getObjectType(local_17c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_17c,TOTALEXPIRETIME); - if (uVar2 < uVar7 + 5) { - uVar7 = Object::getAttribute(&local_2c,RESPONSIBLE); - Text2 = (char *)GetCreature(uVar7); - } - } - } - pOVar20 = local_17c; - pOVar19 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pOVar18 = local_15c; - GetEventObject(); - pOVar16 = &local_2c; - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getObjectType((Object *)&z); - if (z == 99) { - z = local_2c.ObjectID; - pTVar6 = GetCreature((Object *)&z); - if (pTVar6 != (TCreature *)0x0) { - TCreature::Damage(pTVar6,(TCreature *)Text2,Action->Parameters[3], - Action->Parameters[2]); - return; - } - pcVar14 = "ExecuteAction (DAMAGE): Kreatur existiert nicht.\n"; - goto LAB_08076102; - } - Object::getObjectType((Object *)&z); - pcVar14 = "ExecuteAction (DAMAGE): Objekt ist keine Kreatur, sondern Typ %d.\n"; - AVar15 = z; - goto switchD_080755eb_default; - case ACTION_SETSTART: - pOVar20 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - puVar17 = local_14c; - local_16c[0] = (Object)Obj2->ObjectID; - pOVar16 = local_15c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pOVar19 = local_17c; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = (char *)&local_2c; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z == 99) { - z = local_2c.ObjectID; - pTVar3 = (TPlayer *)GetCreature((Object *)&z); - uVar7 = Text._252_4_; - if ((pTVar3 != (TPlayer *)0x0) && ((pTVar3->super_TCreature).Type == PLAYER)) { - Log("game",&DAT_080f8780,(pTVar3->super_TCreature).Name,pOVar16,pOVar20,pOVar19); - UnpackAbsoluteCoordinate(); - TPlayer::SaveData(pTVar3); - return; - } - } - goto LAB_08076474; - case ACTION_WRITENAME: - local_17c[0] = (Object)Temp->ObjectID; - pOVar20 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - pOVar16 = local_15c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - puVar17 = local_14c; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = (char *)&local_2c; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z != 99) goto LAB_08076474; - z = local_2c.ObjectID; - pTVar6 = GetCreature((Object *)&z); - uVar7 = Text._252_4_; - if (pTVar6 == (TCreature *)0x0) goto LAB_08076474; - puVar10 = &local_13c; - for (iVar8 = 0x40; iVar8 != 0; iVar8 = iVar8 + -1) { - *puVar10 = 0; - puVar10 = puVar10 + 1; - } - __s = GetDynamicString(Action->Parameters[1]); - for (local_1c4 = 0; sVar5 = strlen(__s), local_1c4 < (int)sVar5; local_1c4 = local_1c4 + 1) - { - if ((__s[local_1c4] == '%') && (__s[local_1c4 + 1] == 'N')) { - pcVar14 = pTVar6->Name; - local_1c4 = local_1c4 + 1; - strcat((char *)&local_13c,pcVar14); - } - else { - puVar10 = &local_13c; - do { - puVar9 = puVar10; - uVar11 = *puVar9 + 0xfefefeff & ~*puVar9; - uVar12 = uVar11 & 0x80808080; - puVar10 = puVar9 + 1; - } while (uVar12 == 0); - bVar13 = (uVar11 & 0x8080) == 0; - if (bVar13) { - uVar12 = uVar12 >> 0x10; - } - if (bVar13) { - puVar10 = (uint *)((int)puVar9 + 6); - } - *(char *)((int)puVar10 + (-3 - (uint)CARRY1((byte)uVar12,(byte)uVar12))) = - __s[local_1c4]; - } - uVar7 = Text._252_4_; - if (Text[0xc4] != '\0') goto LAB_08076474; - } - pOVar20 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - puVar17 = local_14c; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pOVar16 = local_15c; - pcVar14 = (char *)Action->Parameters[2]; - GetEventObject(); - bVar13 = false; - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - if (local_18c[0].ObjectID == NONE.ObjectID) { -LAB_08076725: - bVar13 = true; - } - else { - Object::getObjectType(local_18c); - pcVar14 = (char *)0x18; - bVar1 = ObjectType::getFlag((ObjectType *)local_18c,TEXT); - if (!bVar1) goto LAB_08076725; - } - uVar7 = Text._252_4_; - if (bVar13) goto LAB_08076474; - uVar7 = Object::getAttribute(&local_2c,TEXTSTRING); - DeleteDynamicString(uVar7); - z = local_2c.ObjectID; - uVar7 = AddDynamicString((char *)&local_13c); - Change((Object *)&z,TEXTSTRING,uVar7); - uVar7 = 0; - Attribute = EDITOR; - goto LAB_08075f26; - case ACTION_WRITETEXT: - pOVar20 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - pOVar16 = local_15c; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pcVar14 = (char *)Action->Parameters[1]; - GetEventObject(); - bVar13 = false; - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - if (local_18c[0].ObjectID == NONE.ObjectID) { -LAB_08076857: - bVar13 = true; - } - else { - Object::getObjectType(local_18c); - pcVar14 = (char *)0x18; - bVar1 = ObjectType::getFlag((ObjectType *)local_18c,TEXT); - if (!bVar1) goto LAB_08076857; - } - uVar7 = Text._252_4_; - if (bVar13) goto LAB_08076474; - uVar7 = Object::getAttribute(&local_2c,TEXTSTRING); - DeleteDynamicString(uVar7); - z = local_2c.ObjectID; - pcVar14 = GetDynamicString(Action->Parameters[0]); - uVar7 = AddDynamicString(pcVar14); - Change((Object *)&z,TEXTSTRING,uVar7); - uVar7 = 0; - Attribute = EDITOR; -LAB_08075f26: - z = local_2c.ObjectID; - Change((Object *)&z,Attribute,uVar7); - break; - case ACTION_LOGOUT: - pOVar20 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - puVar17 = local_14c; - local_16c[0] = (Object)Obj2->ObjectID; - pOVar16 = local_15c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = (char *)&local_2c; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z == 99) { - z = local_2c.ObjectID; - pTVar6 = GetCreature((Object *)&z); - uVar7 = Text._252_4_; - if (pTVar6 != (TCreature *)0x0) { - TCreature::StartLogout(pTVar6,true,true); - return; - } - } - goto LAB_08076474; - case ACTION_MOVEALLONMAP: - UnpackAbsoluteCoordinate(); - GetFirstObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - UnpackAbsoluteCoordinate(); - GetMapContainer((int)local_18c,dz,x); - bVar13 = false; - z = NONE.ObjectID; - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - local_17c[0].ObjectID = local_2c.ObjectID; - goto LAB_08076acf; - case ACTION_MOVEALL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getContainer(local_17c); - GetFirstContainerObject(local_18c); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - UnpackAbsoluteCoordinate(); - goto LAB_08076bd6; - case ACTION_MOVEALLREL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getContainer(local_17c); - GetFirstContainerObject(local_18c); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - UnpackRelativeCoordinate(); - x = dx + x; - dz = (int)(cr2->super_TSkillBase).Skills + dz + -4; -LAB_08076bd6: - GetMapContainer((int)local_18c,dz,x); - bVar13 = false; - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - z = local_2c.ObjectID; - local_17c[0].ObjectID = local_2c.ObjectID; - goto LAB_08076acf; - case ACTION_MOVETOPONMAP: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - GetFirstSpecObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - if (local_18c[0].ObjectID == NONE.ObjectID) { - iVar8 = Action->Parameters[1]; - pcVar14 = "ExecuteAction (MOVETOPONMAP): Kein Objekt %d auf [%d,%d,%d].\n"; - goto LAB_08075be0; - } - UnpackAbsoluteCoordinate(); - GetMapContainer((int)local_18c,dz,x); - z = NONE.ObjectID; - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - Object::getNextObject(local_17c); - bVar13 = true; - goto LAB_08076acf; - case ACTION_MOVETOP: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - UnpackAbsoluteCoordinate(); - goto LAB_08076f87; - case ACTION_MOVETOPREL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - UnpackRelativeCoordinate(); - x = dx + x; - dz = (int)(cr2->super_TSkillBase).Skills + dz + -4; -LAB_08076f87: - GetMapContainer((int)local_18c,dz,x); - z = NONE.ObjectID; - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - Object::getNextObject(local_17c); - bVar13 = true; -LAB_08076acf: - MoveAllObjects(local_17c,local_18c,(Object *)&z,bVar13); - break; - case ACTION_MOVE: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - UnpackAbsoluteCoordinate(); - GetMapContainer((int)local_18c,dz,x); - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - goto LAB_080771eb; - case ACTION_MOVEREL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - local_18c[0] = (Object)Temp->ObjectID; - local_17c[0] = (Object)Obj2->ObjectID; - local_16c[0] = (Object)Obj1->ObjectID; - local_15c[0] = (Object)User->ObjectID; - GetEventObject(); - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - UnpackRelativeCoordinate(); - GetMapContainer((int)local_18c,(int)(cr2->super_TSkillBase).Skills + dz + -4,dx + x); - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - goto LAB_080771eb; - case ACTION_RETRIEVE: - local_18c[0] = (Object)Temp->ObjectID; - local_17c[0] = (Object)Obj2->ObjectID; - local_16c[0] = (Object)Obj1->ObjectID; - local_15c[0] = (Object)User->ObjectID; - GetEventObject(); - GetObjectCoordinates((Object *)&z,&dz,&x,&y); - UnpackRelativeCoordinate(); - GetTopObject((int)local_18c,(int)(cr2->super_TSkillBase).Skills + dz + -4,dx + x, - (bool)((char)dy + (char)y)); - bVar13 = false; - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - if (local_18c[0].ObjectID == NONE.ObjectID) { -LAB_080774d6: - bVar13 = true; - } - else { - Object::getObjectType(local_18c); - bVar1 = ObjectType::getFlag((ObjectType *)local_18c,UNMOVE); - if (bVar1) goto LAB_080774d6; - } - if (bVar13) { - return; - } - UnpackRelativeCoordinate(); - GetMapContainer((int)local_18c,(int)(cr2->super_TSkillBase).Skills + dz + -4,dx + x); - Text._252_4_ = local_18c[0].ObjectID; -LAB_080771eb: - z = Text._252_4_; - local_18c[0].ObjectID = local_2c.ObjectID; - MoveOneObject(local_18c,(Object *)&z); - break; - case ACTION_DELETEALLONMAP: - UnpackAbsoluteCoordinate(); - GetFirstObject(); - bVar13 = false; - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - goto LAB_0807762f; - case ACTION_DELETETOPONMAP: - UnpackAbsoluteCoordinate(); - pOVar20 = local_17c; - ObjectType::setTypeID((ObjectType *)pOVar20,Action->Parameters[1]); - GetFirstSpecObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - pcVar14 = (char *)dz; - puVar17 = (ulong *)x; - pOVar16 = (Object *)y; - uVar7 = Text._252_4_; - if (local_18c[0].ObjectID == NONE.ObjectID) goto LAB_08076474; - z = local_18c[0].ObjectID; - Object::getNextObject(local_18c); - bVar13 = true; -LAB_0807762f: - DeleteAllObjects(local_18c,(Object *)&z,bVar13); - break; - case ACTION_DELETEONMAP: - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - GetFirstSpecObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - if (local_18c[0].ObjectID == NONE.ObjectID) { - iVar8 = Action->Parameters[1]; - pcVar14 = "ExecuteAction (DELETEONMAP): Kein Objekt %d auf [%d,%d,%d].\n"; - goto LAB_08075be0; - } - goto LAB_080777c6; - case ACTION_DELETE: - pOVar16 = local_15c; - local_17c[0] = (Object)Temp->ObjectID; - pOVar20 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - pcVar14 = (char *)Action->Parameters[0]; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = NONE.ObjectID; - uVar7 = Text._252_4_; - if (local_18c[0].ObjectID == NONE.ObjectID) goto LAB_08076474; -LAB_080777c6: - Delete((Object *)&z,(-(uint)(Event < EVENT_MOVEMENT) & 2) - 1); - break; - case ACTION_DELETEININVENTORY: - pOVar20 = local_16c; - local_17c[0] = (Object)Temp->ObjectID; - puVar17 = local_14c; - local_16c[0] = (Object)Obj2->ObjectID; - pOVar16 = local_15c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = (char *)&local_2c; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z != 99) goto LAB_08076474; - ObjectType::setTypeID((ObjectType *)&z,Action->Parameters[1]); - uVar7 = Object::getCreatureID(&local_2c); - DeleteAtCreature(uVar7,(ObjectType *)&z,1,Action->Parameters[2]); - break; - case ACTION_DESCRIPTION: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getObjectType((Object *)&z); - if (z == 99) { - z = local_2c.ObjectID; - pTVar6 = GetCreature((Object *)&z); - if ((pTVar6 != (TCreature *)0x0) && (pTVar6->Type == PLAYER)) { - local_17c[0] = (Object)Temp->ObjectID; - pOVar16 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - pOVar20 = local_17c; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = GetInfo((Object *)&z); - SendMessage(pTVar6->Connection,0x16,"%s.",pcVar14,pOVar16,pOVar20); - } - } - break; - case ACTION_LOADDEPOT: - pOVar16 = local_15c; - local_17c[0] = (Object)Temp->ObjectID; - pOVar20 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - pcVar14 = (char *)&local_2c; - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z == 99) { - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - pOVar20 = local_17c; - GetFirstSpecObject(); - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - z = NONE.ObjectID; - pcVar14 = (char *)dz; - puVar17 = (ulong *)x; - pOVar16 = (Object *)y; - uVar7 = Text._252_4_; - if (local_18c[0].ObjectID != NONE.ObjectID) { - z = local_18c[0].ObjectID; - uVar7 = Object::getCreatureID(&local_2c); - LoadDepotBox(uVar7,Action->Parameters[3],(Object *)&z); - return; - } - } - goto LAB_08076474; - case ACTION_SAVEDEPOT: - pOVar16 = local_15c; - local_17c[0] = (Object)Temp->ObjectID; - pOVar20 = local_16c; - local_16c[0] = (Object)Obj2->ObjectID; - puVar17 = local_14c; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - pcVar14 = (char *)&local_2c; - Object::getObjectType((Object *)&z); - uVar7 = Text._252_4_; - if (z == 99) { - UnpackAbsoluteCoordinate(); - ObjectType::setTypeID((ObjectType *)local_17c,Action->Parameters[1]); - pOVar20 = local_17c; - GetFirstSpecObject(); - z = NONE.ObjectID; - Text[0xfc] = (undefined1)local_18c[0].ObjectID; - Text[0xfd] = local_18c[0].ObjectID._1_1_; - Text[0xfe] = local_18c[0].ObjectID._2_1_; - Text[0xff] = local_18c[0].ObjectID._3_1_; - pcVar14 = (char *)dz; - puVar17 = (ulong *)x; - pOVar16 = (Object *)y; - uVar7 = local_18c[0].ObjectID; - if (local_18c[0].ObjectID != NONE.ObjectID) { - z = local_18c[0].ObjectID; - uVar7 = Object::getCreatureID(&local_2c); - SaveDepotBox(uVar7,Action->Parameters[3],(Object *)&z); - return; - } - } -LAB_08076474: - Text._252_4_ = uVar7; - puVar4 = (undefined4 *)__cxa_allocate_exception(4,pcVar14,puVar17,pOVar16,pOVar20); - *puVar4 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); - case ACTION_SENDMAIL: - local_17c[0] = (Object)Temp->ObjectID; - local_16c[0] = (Object)Obj2->ObjectID; - local_15c[0] = (Object)Obj1->ObjectID; - local_14c[0] = User->ObjectID; - GetEventObject(); - local_2c.ObjectID = local_18c[0].ObjectID; - z = local_18c[0].ObjectID; - SendMail((Object *)&z); - break; - case ACTION_NOP: - break; - default: - pcVar14 = "ExecuteAction: Unbekannte Aktion %d.\n"; - AVar15 = Action->Action; -switchD_080755eb_default: - error(pcVar14,AVar15); - } - return; -} - - - -bool HandleEvent(EventType Event,Object *User,Object *Obj1,Object *Obj2) - -{ - bool bVar1; - bool bVar2; - TMoveUseCondition *Condition; - TMoveUseRule *pTVar3; - TMoveUseCondition *Condition_00; - TMoveUseAction *Action; - int condition; - int iVar4; - int iVar5; - TMoveUseRule *Rule; - TMoveUseDatabase *DB; - int iStack_60; - bool fulfilled; - int rule; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object Temp; - - if (HandleEvent::RecursionDepth < 0xb) { - iStack_60 = 1; - HandleEvent::RecursionDepth = HandleEvent::RecursionDepth + 1; - if (0 < MoveUseDatabases[Event].NumberOfRules) { - do { - pTVar3 = vector<>::operator()(&MoveUseDatabases[Event].Rules,iStack_60); - bVar1 = true; - local_2c.ObjectID = NONE.ObjectID; - iVar4 = pTVar3->FirstCondition; - if (iVar4 <= pTVar3->LastCondition) { - do { - Condition_00 = vector<>::operator()(&MoveUseConditions,iVar4); - local_3c[0] = (Object)Obj2->ObjectID; - local_4c[0] = (Object)Obj1->ObjectID; - rule = User->ObjectID; - bVar2 = CheckCondition(Event,Condition_00,(Object *)&rule,local_4c,local_3c, - &local_2c); - if (!bVar2) { - bVar1 = false; - } - iVar4 = iVar4 + 1; - if (!bVar1) goto LAB_08077f6d; - } while (iVar4 <= pTVar3->LastCondition); - } - if (bVar1) { - iVar4 = pTVar3->FirstAction; - if (pTVar3->FirstAction <= pTVar3->LastAction) { - do { - iVar5 = iVar4 + 1; - Action = vector<>::operator()(&MoveUseActions,iVar4); - rule = Obj2->ObjectID; - local_4c[0] = (Object)Obj1->ObjectID; - local_3c[0] = (Object)User->ObjectID; - ExecuteAction(Event,Action,local_3c,local_4c,(Object *)&rule,&local_2c); - iVar4 = iVar5; - } while (iVar5 <= pTVar3->LastAction); - } - HandleEvent::RecursionDepth = HandleEvent::RecursionDepth + -1; - return true; - } -LAB_08077f6d: - iStack_60 = iStack_60 + 1; - } while (iStack_60 <= MoveUseDatabases[Event].NumberOfRules); - } - HandleEvent::RecursionDepth = HandleEvent::RecursionDepth + -1; - } - else { - error("HandleEvent: Endlosschleife im Move/Use-System vermutet.\n"); - } - return false; -} - - - -void UseContainer(ulong CreatureID,Object *Con,uchar Window) - -{ - bool bVar1; - TPlayer *this; - undefined4 *puVar2; - int Window_00; - char *pcVar3; - Object *pOVar4; - TPlayer *pl; - Object OStack_4c; - uchar Window_local; - _func_int_varargs **local_3c; - _func_int_varargs **local_2c; - - // try { // try from 0807802f to 080781a2 has its CatchHandler @ 080781b0 - bVar1 = Object::exists(Con); - if (bVar1) { - Object::getObjectType((Object *)&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,CONTAINER); - if (!bVar1) { - pcVar3 = &DAT_080f8980; - goto LAB_0807819e; - } - if (Window < 0x10) { - pOVar4 = Con; - Object::getObjectType((Object *)&local_2c); - if (local_2c == (_func_int_varargs **)0x63) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4,pOVar4); - *puVar2 = 0x1d; - goto LAB_0807815a; - } - this = GetPlayer(CreatureID); - if (this != (TPlayer *)0x0) { - Window_00 = 0; - do { - TPlayer::GetOpenContainer((TPlayer *)&local_2c,(int)this); - local_3c = (_func_int_varargs **)Con->ObjectID; - if (local_2c == local_3c) { - OStack_4c.ObjectID = NONE.ObjectID; - TPlayer::SetOpenContainer(this,Window_00,&stack0xffffffb4); - SendCloseContainer((this->super_TCreature).Connection,Window_00); - return; - } - Window_00 = Window_00 + 1; - } while (Window_00 < 0x10); - OStack_4c.ObjectID = (ulong)local_3c; - TPlayer::SetOpenContainer(this,(uint)Window,&stack0xffffffb4); - SendContainer((this->super_TCreature).Connection,(uint)Window); - return; - } - pcVar3 = "UseContainer: Spieler %d existiert nicht.\n"; - } - else { - CreatureID = (ulong)Window; - pcVar3 = &DAT_080f8940; - } - error(pcVar3,CreatureID); - } - else { - pcVar3 = &DAT_080f89c0; -LAB_0807819e: - error(pcVar3); - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_0807815a: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -void UseChest(ulong CreatureID,Object *Chest) - -{ - bool bVar1; - bool bVar2; - ulong uVar3; - int iVar4; - TPlayer *this; - char *pcVar5; - int iVar6; - int iVar7; - char *pcVar8; - undefined4 *puVar9; - int Weight; - ulong uVar10; - undefined4 uVar11; - undefined8 local_bc; - int iStack_b8; - bool invert; - bool first; - int pos; - TPlayer *pl; - int Number; - int x; - int y; - int z; - Object local_7c [4]; - Object local_6c; - Object Obj; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object Treasure; - - // try { // try from 080781e8 to 08078562 has its CatchHandler @ 08078948 - bVar2 = Object::exists(Chest); - if (bVar2) { - Object::getObjectType(&local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,CHEST); - if (bVar2) { - local_2c = (Object)Chest->ObjectID; - GetObjectCoordinates(&local_2c,&Number,&x,&y); - uVar3 = Object::getAttribute(Chest,CHESTQUESTNUMBER); - bVar2 = false; - if ((0 < (int)uVar3) && ((int)uVar3 < 500)) { - bVar2 = true; - } - if (!bVar2) { - error(&DAT_080f8b40,uVar3,Number,x,y); - goto LAB_0807875e; - } - local_2c = (Object)Chest->ObjectID; - iVar4 = CountObjectsInContainer(&local_2c); - if (iVar4 != 1) { - error(&DAT_080f8ae0,Number,x,y); - goto LAB_0807875e; - } - local_3c[0] = (Object)Chest->ObjectID; - GetFirstContainerObject(&local_2c); - Object::getObjectType(local_3c); - bVar2 = ObjectType::getFlag((ObjectType *)local_3c,UNMOVE); - if (!bVar2) { - Object::getObjectType(local_3c); - bVar2 = ObjectType::getFlag((ObjectType *)local_3c,TAKE); - if (bVar2) { - this = GetPlayer(CreatureID); - if (this == (TPlayer *)0x0) { - // try { // try from 08078759 to 080787f5 has its CatchHandler @ 08078948 - error("UseChest: Spieler %d existiert nicht.\n",CreatureID); - goto LAB_0807875e; - } - iVar4 = TPlayer::GetQuestValue(this,uVar3); - if (iVar4 != 0) { - print(); - Object::getObjectType(local_3c); - pcVar5 = ObjectType::getName((ObjectType *)local_3c); - SendMessage((this->super_TCreature).Connection,0x16,"The %s is empty.", - pcVar5); - return; - } - bVar2 = CheckRight(CreatureID,UNLIMITED_CAPACITY); - if (bVar2) { -LAB_080784f2: - Object::getContainer(&local_6c); - Copy(local_4c,&local_6c); - local_2c.ObjectID = local_4c[0].ObjectID; - local_3c[0].ObjectID = local_4c[0].ObjectID; - Object::getObjectType(&local_6c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_6c,MOVEMENTEVENT); - uVar11 = 1; - uVar10 = CreatureID; - // try { // try from 08078586 to 08078614 has its CatchHandler @ 0807880d - GetBodyObject((ulong)&local_6c,CreatureID); - if ((bVar2) || (local_6c.ObjectID != NONE.ObjectID)) { - bVar1 = false; - if (bVar2) { - local_7c[0] = (Object)NONE.ObjectID; - local_4c[0].ObjectID = NONE.ObjectID; - if (local_6c.ObjectID != NONE.ObjectID) { - Object::getObjectType(local_4c); - uVar10 = 4; - bVar2 = ObjectType::getFlag((ObjectType *)local_4c,CONTAINER); - if (bVar2) { - bVar1 = true; - } - } - } - if (!bVar1) { - puVar9 = (undefined4 *)__cxa_allocate_exception(4,uVar10,uVar11); - *puVar9 = 4; - // WARNING: Subroutine does not return - // try { // try from 08078698 to 0807873f has its CatchHandler @ 0807880d - __cxa_throw(puVar9,&RESULT::typeinfo,0); - } - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = local_6c.ObjectID; - z = local_2c.ObjectID; - Move(CreatureID,(Object *)&z,local_3c,-1,true,local_4c); - } - else { - local_4c[0].ObjectID = NONE.ObjectID; - GetBodyContainer((ulong)local_3c,CreatureID); - local_7c[0].ObjectID = local_2c.ObjectID; - Move(CreatureID,local_7c,local_3c,-1,true,local_4c); - } - z = local_2c.ObjectID; - // try { // try from 08078621 to 0807866d has its CatchHandler @ 08078948 - pcVar5 = GetName((Object *)&z); - SendMessage((this->super_TCreature).Connection,0x16,"You have found %s.\n", - pcVar5); - TPlayer::SetQuestValue(this,uVar3,1); - return; - } - local_3c[0].ObjectID = local_2c.ObjectID; - iVar4 = GetCompleteWeight(local_3c); - iVar6 = GetInventoryWeight(CreatureID); - iVar7 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[5]); - if ((iVar4 + iVar6 <= iVar7 * 100) && - (bVar2 = CheckRight(CreatureID,ZERO_CAPACITY), !bVar2)) goto LAB_080784f2; - Object::getObjectType(local_3c); - bVar2 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE); - if (bVar2) { - uVar3 = Object::getAttribute(&local_2c,AMOUNT); - pcVar5 = "they are"; - if (1 < uVar3) goto LAB_0807844b; - } - pcVar5 = "it is"; -LAB_0807844b: - local_3c[0].ObjectID = local_2c.ObjectID; - pcVar8 = GetName(local_3c); - iVar6 = (iStack_b8 >> 5) - (iVar4 >> 0x1f); - SendMessage((this->super_TCreature).Connection,0x16, - "You have found %s. Weighing %d.%02d oz %s too heavy.",pcVar8,iVar6, - iVar4 + iVar6 * -100,pcVar5); - return; - } - } - pcVar5 = "UseChest: Schatz auf Position [%d,%d,%d] ist nicht nehmbar.\n"; - } - else { - pcVar5 = &DAT_080f8ba0; - } - } - else { - pcVar5 = &DAT_080f8be0; - } - error(pcVar5); -LAB_0807875e: - puVar9 = (undefined4 *)__cxa_allocate_exception(4); - *puVar9 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar9,&RESULT::typeinfo,0); -} - - - -void UseLiquidContainer(ulong CreatureID,Object *Obj,Object *Dest) - -{ - TSkill *pTVar1; - bool bVar2; - bool bVar3; - ulong uVar4; - undefined4 *puVar5; - TPlayer *this; - int iVar6; - char *pcVar7; - int iVar8; - undefined4 uVar9; - int LiquidType; - int local_58; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c; - Object Help; - - // try { // try from 0807897b to 08078f23 has its CatchHandler @ 08078f43 - bVar2 = Object::exists(Obj); - if (bVar2) { - bVar2 = Object::exists(Dest); - if (bVar2) { - Object::getObjectType(&local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,LIQUIDCONTAINER); - if (!bVar2) { - pcVar7 = &DAT_080f8ce0; - goto LAB_08078f0b; - } - Object::getObjectType(&local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,LIQUIDSOURCE); - if ((bVar2) && (uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE), uVar4 == 0)) { - Object::getObjectType(&local_2c); - uVar4 = ObjectType::getAttribute((ObjectType *)&local_2c,SOURCELIQUIDTYPE); - local_2c = (Object)Obj->ObjectID; -LAB_08078ec5: - Change(&local_2c,CONTAINERLIQUIDTYPE,uVar4); - return; - } - Object::getObjectType(&local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,LIQUIDCONTAINER); - if ((bVar2) && - ((uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE), uVar4 != 0 && - (uVar4 = Object::getAttribute(Dest,CONTAINERLIQUIDTYPE), uVar4 == 0)))) { - local_2c = (Object)Dest->ObjectID; - uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE); - Change(&local_2c,CONTAINERLIQUIDTYPE,uVar4); - local_2c = (Object)Obj->ObjectID; - uVar4 = 0; - goto LAB_08078ec5; - } - Object::getObjectType(&local_2c); - if (local_2c.ObjectID != 99) { - Object::getContainer(local_3c); - GetFirstContainerObject(&local_2c); - z = NONE.ObjectID; - local_3c[0].ObjectID = z; - if (local_2c.ObjectID != NONE.ObjectID) { - do { - z = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getObjectType((Object *)&z); - if ((z == 99) && - (uVar4 = Object::getCreatureID(&local_2c), uVar4 == CreatureID)) { - local_3c[0].ObjectID = local_2c.ObjectID; - Dest->ObjectID = (ulong)local_2c; - z = local_2c.ObjectID; - break; - } - Object::getNextObject(local_3c); - local_2c.ObjectID = local_3c[0].ObjectID; - bVar2 = local_3c[0].ObjectID != NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - z = NONE.ObjectID; - } while (bVar2); - } - } - Object::getObjectType((Object *)&z); - if ((z != 99) || (uVar4 = Object::getCreatureID(Dest), uVar4 != CreatureID)) { - uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE); - if (uVar4 == 0) { - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0x1d; - } - else { - z = Dest->ObjectID; - GetObjectCoordinates((Object *)&z,&local_58,&x,&y); - bVar2 = false; - uVar9 = 0; - iVar6 = x; - iVar8 = y; - bVar3 = CoordinateFlag(); - if (bVar3) { - uVar9 = 0x23; - bVar2 = CoordinateFlag(); - bVar2 = !bVar2; - iVar6 = x; - iVar8 = y; - } - if (bVar2) { - Object::getAttribute(Obj,CONTAINERLIQUIDTYPE); - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - local_3c[0] = (Object)Dest->ObjectID; - GetMapContainer((Object *)&z); - GetSpecialObject((SPECIALMEANING)&local_2c); - CreatePool(); - return; - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4,iVar6,iVar8,uVar9); - *puVar5 = 4; - } - goto LAB_08078b95; - } - this = GetPlayer(CreatureID); - if (this != (TPlayer *)0x0) { - uVar4 = Object::getAttribute(Obj,CONTAINERLIQUIDTYPE); - switch(uVar4) { - case 0: - return; - default: - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - pcVar7 = "Gulp."; - break; - case 2: - case 3: - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0x14]; - pcVar7 = "Aah..."; - iVar6 = (*pTVar1->_vptr_TSkill[0xd])(pTVar1); - if (iVar6 < 5) { - pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0x14]; - (*pTVar1->_vptr_TSkill[0xd])(pTVar1); - TSkillBase::SetTimer(&(this->super_TCreature).super_TSkillBase); - } - break; - case 6: - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - pcVar7 = "Urgh!"; - TCreature::Damage(&this->super_TCreature,(TCreature *)0x0,200,0x20); - break; - case 8: - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - pcVar7 = "Urgh!"; - break; - case 10: - case 0xb: - z = Obj->ObjectID; - DrinkPotion(CreatureID,(Object *)&z); - pcVar7 = "Aaaah..."; - break; - case 0xc: - z = Obj->ObjectID; - Change((Object *)&z,CONTAINERLIQUIDTYPE,0); - pcVar7 = "Mmmh."; - } - Talk(CreatureID,1,(char *)0x0,pcVar7,false); - return; - } - pcVar7 = "UseLiquidContainer: Spieler %d existiert nicht.\n"; - } - else { - Object::getObjectType(&local_2c); - pcVar7 = &DAT_080f8d40; - CreatureID = local_2c.ObjectID; - } - error(pcVar7,CreatureID); - } - else { - pcVar7 = &DAT_080f8da0; -LAB_08078f0b: - error(pcVar7); - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0xffffffff; -LAB_08078b95: - // WARNING: Subroutine does not return - __cxa_throw(puVar5,&RESULT::typeinfo,0); -} - - - -void UseFood(ulong CreatureID,Object *Obj) - -{ - TSkill *pTVar1; - int iVar2; - bool bVar3; - TPlayer *pTVar4; - int iVar5; - ulong uVar6; - undefined4 *puVar7; - char *Text; - TPlayer *pl; - - // try { // try from 08078f78 to 080790e9 has its CatchHandler @ 080790f5 - bVar3 = Object::exists(Obj); - if (bVar3) { - Object::getObjectType((Object *)&pl); - bVar3 = ObjectType::getFlag((ObjectType *)&pl,FOOD); - if (!bVar3) { - Text = &DAT_080f8e20; - goto LAB_080790e5; - } - pTVar4 = GetPlayer(CreatureID); - if (pTVar4 != (TPlayer *)0x0) { - pTVar1 = (pTVar4->super_TCreature).super_TSkillBase.Skills[0xe]; - iVar5 = (*pTVar1->_vptr_TSkill[0xd])(pTVar1); - iVar2 = pTVar1->Max; - Object::getObjectType((Object *)&pl); - uVar6 = ObjectType::getAttribute((ObjectType *)&pl,NUTRITION); - if (iVar5 <= (int)(iVar2 + uVar6 * -0xc)) { - (*pTVar1->_vptr_TSkill[0xd])(pTVar1); - Object::getObjectType((Object *)&pl); - ObjectType::getAttribute((ObjectType *)&pl,NUTRITION); - TSkillBase::SetTimer(&(pTVar4->super_TCreature).super_TSkillBase); - pl = (TPlayer *)Obj->ObjectID; - Delete((Object *)&pl,1); - return; - } - puVar7 = (undefined4 *)__cxa_allocate_exception(4); - *puVar7 = 0x1e; - goto LAB_080790a2; - } - error("UseFood: Kreatur %d existiert nicht.\n",CreatureID); - } - else { - Text = &DAT_080f8e60; -LAB_080790e5: - error(Text); - } - puVar7 = (undefined4 *)__cxa_allocate_exception(4); - *puVar7 = 0xffffffff; -LAB_080790a2: - // WARNING: Subroutine does not return - __cxa_throw(puVar7,&RESULT::typeinfo,0); -} - - - -void UseTextObject(ulong CreatureID,Object *Obj) - -{ - bool bVar1; - TPlayer *pTVar2; - undefined4 *puVar3; - TPlayer *pl; - char *Text; - Object local_2c [7]; - - // try { // try from 08079128 to 080791d2 has its CatchHandler @ 080791e0 - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,TEXT); - if (bVar1) { - pTVar2 = GetPlayer(CreatureID); - if (pTVar2 != (TPlayer *)0x0) { - local_2c[0] = (Object)Obj->ObjectID; - SendEditText((pTVar2->super_TCreature).Connection,local_2c); - return; - } - error("UseTextObject: Kreatur %d existiert nicht.\n",CreatureID); - goto LAB_0807919d; - } - Text = &DAT_080f8ee0; - } - else { - Text = &DAT_080f8f20; - } - error(Text); -LAB_0807919d: - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -void UseAnnouncer(ulong CreatureID,Object *Obj) - -{ - bool bVar1; - TPlayer *this; - ulong uVar2; - int iVar3; - undefined4 *puVar4; - char cVar5; - char *Text; - TPlayer *pl; - int Hour; - int Minute; - int Year; - int Cycle; - int Day; - char Help [200]; - Object local_2c [7]; - - // try { // try from 0807921b to 080795fa has its CatchHandler @ 08079606 - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,INFORMATION); - if (bVar1) { - this = GetPlayer(CreatureID); - if (this != (TPlayer *)0x0) { - Object::getObjectType(local_2c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_2c,INFORMATIONTYPE); - if (uVar2 == 2) { - GetTime((int *)&pl,&Hour); - SendMessage((this->super_TCreature).Connection,0x16,"The time is %d:%.2d.",pl, - Hour); - return; - } - if (uVar2 < 3) { - if (uVar2 == 1) { - GetDate(&Minute,&Year,&Cycle); - GetTime((int *)&pl,&Hour); - SendMessage((this->super_TCreature).Connection,0x16, - "It is the %dth day of the %dth cycle in the year %d. The time is %d:%.2d." - ,Cycle,Year,Minute,pl,Hour); - return; - } - } - else { - if (uVar2 == 3) { - Day = 0x65636552; - builtin_strncpy(Help,"ived blessings:",0x10); - iVar3 = TPlayer::GetQuestValue(this,0x65); - cVar5 = iVar3 != 0; - if ((bool)cVar5) { - strcat((char *)&Day,"\nWisdom of Solitude"); - } - iVar3 = TPlayer::GetQuestValue(this,0x66); - if (iVar3 != 0) { - cVar5 = cVar5 + '\x01'; - strcat((char *)&Day,"\nSpark of the Phoenix"); - } - iVar3 = TPlayer::GetQuestValue(this,0x67); - if (iVar3 != 0) { - cVar5 = cVar5 + '\x01'; - strcat((char *)&Day,"\nFire of the Suns"); - } - iVar3 = TPlayer::GetQuestValue(this,0x68); - if (iVar3 != 0) { - cVar5 = cVar5 + '\x01'; - strcat((char *)&Day,"\nSpiritual Shielding"); - } - iVar3 = TPlayer::GetQuestValue(this,0x69); - if (iVar3 != 0) { - cVar5 = cVar5 + '\x01'; - strcat((char *)&Day,"\nEmbrace of Tibia"); - } - if (cVar5 == '\0') { - builtin_strncpy(Help,"lessings received.",0x13); - Day = 0x62206f4e; - } - SendMessage((this->super_TCreature).Connection,0x16,"%s",&Day); - return; - } - if (uVar2 == 4) { - local_2c[0] = (Object)Obj->ObjectID; - SendEditText((this->super_TCreature).Connection,local_2c); - return; - } - } - Object::getObjectType(local_2c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_2c,INFORMATIONTYPE); - error(&DAT_080f8f60,uVar2); - return; - } - error("UseAnnouncer: Kreatur %d existiert nicht.\n",CreatureID); - goto LAB_080795c5; - } - Text = &DAT_080f9040; - } - else { - Text = &DAT_080f9080; - } - error(Text); -LAB_080795c5: - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void UseKeyDoor(ulong param_1,Object *Key,Object *Door) - -{ - bool bVar1; - ulong uVar2; - ulong uVar3; - undefined4 *puVar4; - char *Text; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - ObjectType Target; - - // try { // try from 08079638 to 08079834 has its CatchHandler @ 08079850 - bVar1 = Object::exists(Key); - if (bVar1) { - bVar1 = Object::exists(Door); - if (!bVar1) { - Text = &DAT_080f9140; - goto LAB_08079830; - } - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,KEY); - if (!bVar1) { - Text = &DAT_080f9100; - goto LAB_08079830; - } - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,KEYDOOR); - if (!bVar1) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x1d; - goto LAB_080797e9; - } - uVar2 = Object::getAttribute(Door,KEYHOLENUMBER); - if ((uVar2 == 0) || (uVar2 = Object::getAttribute(Key,KEYNUMBER), uVar2 == 0)) { -LAB_08079801: - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x16; - goto LAB_080797e9; - } - uVar2 = Object::getAttribute(Door,KEYHOLENUMBER); - uVar3 = Object::getAttribute(Key,KEYNUMBER); - if (uVar2 != uVar3) goto LAB_08079801; - Object::getObjectType(local_3c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_3c,KEYDOORTARGET); - ObjectType::setTypeID((ObjectType *)&local_2c,uVar2); - ObjectType::setTypeID((ObjectType *)local_3c,0); - if (local_2c.ObjectID != local_3c[0].ObjectID) { - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,UNPASS); - if (bVar1) { - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0] = (Object)Door->ObjectID; - ClearField(local_3c,local_4c); - } - ObjectType::setTypeID((ObjectType *)local_4c,local_2c.ObjectID); - local_3c[0] = (Object)Door->ObjectID; - Change(local_3c,(ObjectType *)local_4c,0); - return; - } - Object::getObjectType(local_4c); - error(&DAT_080f90c0,local_4c[0].ObjectID); - } - else { - Text = &DAT_080f9180; -LAB_08079830: - error(Text); - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_080797e9: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void UseNameDoor(ulong CreatureID,Object *Door) - -{ - bool bVar1; - ushort HouseID; - TPlayer *pl_00; - ulong _TypeID; - undefined4 *puVar2; - TPlayer *pl; - char *Text; - int local_58; - int x; - int y; - int z; - Object local_3c [4]; - Object local_2c; - ObjectType Target; - - // try { // try from 08079885 to 08079ace has its CatchHandler @ 08079af0 - bVar1 = Object::exists(Door); - if (bVar1) { - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,NAMEDOOR); - if (!bVar1) { - Text = &DAT_080f92c0; - goto LAB_08079aca; - } - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,TEXT); - if (!bVar1) { - Text = &DAT_080f9280; - goto LAB_08079aca; - } - pl_00 = GetPlayer(CreatureID); - if (pl_00 == (TPlayer *)0x0) { - Text = "UseNameDoor: Spieler existiert nicht.\n"; - goto LAB_08079aca; - } - local_2c = (Object)Door->ObjectID; - GetObjectCoordinates(&local_2c,&local_58,&x,&y); - HouseID = GetHouseID(local_58,x,y); - if (HouseID == 0) { - error(&DAT_080f9200,local_58,x,y); - } - else { - bVar1 = IsOwner(HouseID,pl_00); - if ((!bVar1) && (bVar1 = CheckRight((pl_00->super_TCreature).ID,OPEN_NAMEDOORS), !bVar1) - ) { - local_2c = (Object)Door->ObjectID; - bVar1 = MayOpenDoor(&local_2c,pl_00); - if (!bVar1) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 1; - goto LAB_08079a3a; - } - } - Object::getObjectType(local_3c); - _TypeID = ObjectType::getAttribute((ObjectType *)local_3c,NAMEDOORTARGET); - ObjectType::setTypeID((ObjectType *)&local_2c,_TypeID); - ObjectType::setTypeID((ObjectType *)local_3c,0); - if (local_2c.ObjectID != local_3c[0].ObjectID) { - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,UNPASS); - if (bVar1) { - z = NONE.ObjectID; - local_3c[0] = (Object)Door->ObjectID; - ClearField(local_3c,(Object *)&z); - } - ObjectType::setTypeID((ObjectType *)&z,local_2c.ObjectID); - local_3c[0] = (Object)Door->ObjectID; - Change(local_3c,(ObjectType *)&z,0); - return; - } - Object::getObjectType((Object *)&z); - error(&DAT_080f91c0,z); - } - } - else { - Text = &DAT_080f9320; -LAB_08079aca: - error(Text); - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_08079a3a: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -void UseLevelDoor(ulong CreatureID,Object *Door) - -{ - bool bVar1; - bool bVar2; - TPlayer *pTVar3; - int iVar4; - ulong uVar5; - char *pcVar6; - undefined4 *puVar7; - TPlayer *pl; - Object local_4c [4]; - Object local_3c; - ObjectType Target; - Object local_2c [7]; - - // try { // try from 08079b28 to 08079d8b has its CatchHandler @ 08079d97 - bVar1 = Object::exists(Door); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,LEVELDOOR); - if (!bVar1) goto LAB_08079d8e; - Object::getContainer(local_2c); - Object::getObjectType(&local_3c); - if (local_3c.ObjectID != 0) goto LAB_08079d8e; - pTVar3 = GetPlayer(CreatureID); - if (pTVar3 == (TPlayer *)0x0) { - pcVar6 = "UseLevelDoor: Spieler existiert nicht.\n"; - goto LAB_08079d87; - } - Object::getObjectType(&local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,UNPASS); - if (!bVar1) { - puVar7 = (undefined4 *)__cxa_allocate_exception(4); - *puVar7 = 0x1d; - goto LAB_08079d37; - } - iVar4 = TSkill::Get((pTVar3->super_TCreature).super_TSkillBase.Skills[0]); - uVar5 = Object::getAttribute(Door,DOORLEVEL); - if (iVar4 < (int)uVar5) { - local_3c = (Object)Door->ObjectID; - pcVar6 = GetInfo(&local_3c); - SendMessage((pTVar3->super_TCreature).Connection,0x16,"%s.",pcVar6); - return; - } - Object::getObjectType(local_2c); - uVar5 = ObjectType::getAttribute((ObjectType *)local_2c,LEVELDOORTARGET); - ObjectType::setTypeID((ObjectType *)&local_3c,uVar5); - bVar1 = false; - ObjectType::setTypeID((ObjectType *)local_2c,0); - if ((local_3c.ObjectID == local_2c[0].ObjectID) || - (bVar2 = ObjectType::getFlag((ObjectType *)&local_3c,UNPASS), bVar2)) { - bVar1 = true; - } - if (!bVar1) { - ObjectType::setTypeID((ObjectType *)local_4c,local_3c.ObjectID); - local_2c[0] = (Object)Door->ObjectID; - Change(local_2c,(ObjectType *)local_4c,0); - local_4c[0].ObjectID = NONE.ObjectID; - Object::getContainer(local_2c); - pl = (TPlayer *)(pTVar3->super_TCreature).CrObject.ObjectID; - Move(0,(Object *)&pl,local_2c,-1,false,local_4c); - return; - } - Object::getObjectType(local_4c); - error(&DAT_080f9360,local_4c[0].ObjectID); - } - else { -LAB_08079d8e: - pcVar6 = &DAT_080f9400; -LAB_08079d87: - error(pcVar6); - } - puVar7 = (undefined4 *)__cxa_allocate_exception(4); - *puVar7 = 0xffffffff; -LAB_08079d37: - // WARNING: Subroutine does not return - __cxa_throw(puVar7,&RESULT::typeinfo,0); -} - - - -void UseQuestDoor(ulong CreatureID,Object *Door) - -{ - bool bVar1; - bool bVar2; - TPlayer *this; - ulong uVar3; - ulong uVar4; - char *pcVar5; - undefined4 *puVar6; - TPlayer *pl; - Object local_4c [4]; - Object local_3c; - ObjectType Target; - Object local_2c [7]; - - // try { // try from 08079dc8 to 0807a03c has its CatchHandler @ 0807a048 - bVar1 = Object::exists(Door); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,QUESTDOOR); - if (!bVar1) goto LAB_0807a03f; - Object::getContainer(local_2c); - Object::getObjectType(&local_3c); - if (local_3c.ObjectID != 0) goto LAB_0807a03f; - this = GetPlayer(CreatureID); - if (this == (TPlayer *)0x0) { - pcVar5 = "UseQuestDoor: Spieler existiert nicht.\n"; - goto LAB_0807a038; - } - Object::getObjectType(&local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,UNPASS); - if (!bVar1) { - puVar6 = (undefined4 *)__cxa_allocate_exception(4); - *puVar6 = 0x1d; - goto LAB_08079fe8; - } - uVar3 = Object::getAttribute(Door,DOORQUESTNUMBER); - uVar3 = TPlayer::GetQuestValue(this,uVar3); - uVar4 = Object::getAttribute(Door,DOORQUESTVALUE); - if (uVar3 != uVar4) { - local_3c = (Object)Door->ObjectID; - pcVar5 = GetInfo(&local_3c); - SendMessage((this->super_TCreature).Connection,0x16,"%s.",pcVar5); - return; - } - Object::getObjectType(local_2c); - uVar3 = ObjectType::getAttribute((ObjectType *)local_2c,QUESTDOORTARGET); - ObjectType::setTypeID((ObjectType *)&local_3c,uVar3); - bVar1 = false; - ObjectType::setTypeID((ObjectType *)local_2c,0); - if ((local_3c.ObjectID == local_2c[0].ObjectID) || - (bVar2 = ObjectType::getFlag((ObjectType *)&local_3c,UNPASS), bVar2)) { - bVar1 = true; - } - if (!bVar1) { - ObjectType::setTypeID((ObjectType *)local_4c,local_3c.ObjectID); - local_2c[0] = (Object)Door->ObjectID; - Change(local_2c,(ObjectType *)local_4c,0); - local_4c[0].ObjectID = NONE.ObjectID; - Object::getContainer(local_2c); - pl = (TPlayer *)(this->super_TCreature).CrObject.ObjectID; - Move(0,(Object *)&pl,local_2c,-1,false,local_4c); - return; - } - Object::getObjectType(local_4c); - error(&DAT_080f9440,local_4c[0].ObjectID); - } - else { -LAB_0807a03f: - pcVar5 = &DAT_080f94e0; -LAB_0807a038: - error(pcVar5); - } - puVar6 = (undefined4 *)__cxa_allocate_exception(4); - *puVar6 = 0xffffffff; -LAB_08079fe8: - // WARNING: Subroutine does not return - __cxa_throw(puVar6,&RESULT::typeinfo,0); -} - - - -void UseWeapon(ulong CreatureID,Object *Weapon,Object *Target) - -{ - bool bVar1; - TPlayer *pl; - ulong uVar2; - TPlayer *pTVar3; - long lVar4; - undefined4 *puVar5; - char *Text; - Object *pOVar6; - Object local_4c [4]; - Object local_3c; - ObjectType Dest; - Object local_2c [7]; - - // try { // try from 0807a078 to 0807a2c9 has its CatchHandler @ 0807a2d5 - bVar1 = Object::exists(Weapon); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,WEAPON); - if (!bVar1) goto LAB_0807a2cc; - Object::getObjectType(local_2c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_2c,WEAPONTYPE); - bVar1 = false; - if ((0 < (int)uVar2) && ((int)uVar2 < 4)) { - bVar1 = true; - } - if (!bVar1) goto LAB_0807a2cc; - bVar1 = Object::exists(Target); - if (!bVar1) { -LAB_0807a2be: - Text = &DAT_080f9560; - goto LAB_0807a2c5; - } - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,DESTROY); - if (!bVar1) goto LAB_0807a2be; - pTVar3 = GetPlayer(CreatureID); - if (pTVar3 != (TPlayer *)0x0) { - Object::getContainer(local_2c); - pOVar6 = local_2c; - Object::getObjectType(&local_3c); - if (local_3c.ObjectID == 0) { - local_3c = (Object)Target->ObjectID; - GraphicalEffect(&local_3c,3); - lVar4 = random(); - if (lVar4 == 1) { - Object::getObjectType(local_2c); - uVar2 = ObjectType::getAttribute((ObjectType *)local_2c,DESTROYTARGET); - ObjectType::setTypeID((ObjectType *)&local_3c,uVar2); - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (bVar1) { - ObjectType::setTypeID((ObjectType *)local_2c,0); - if ((local_3c.ObjectID == local_2c[0].ObjectID) || - (bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER), !bVar1)) - { - uVar2 = 0; - } - else { - uVar2 = ObjectType::getAttribute((ObjectType *)&local_3c,CAPACITY); - } - local_4c[0] = (Object)Target->ObjectID; - Empty(local_4c,uVar2); - } - ObjectType::setTypeID((ObjectType *)local_4c,local_3c.ObjectID); - local_2c[0] = (Object)Target->ObjectID; - Change(local_2c,(ObjectType *)local_4c,0); - } - return; - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4,pOVar6); - *puVar5 = 1; - goto LAB_0807a27f; - } - error("UseWeapon: Spieler %d existiert nicht.\n",CreatureID); - } - else { -LAB_0807a2cc: - Text = &DAT_080f95c0; -LAB_0807a2c5: - error(Text); - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0xffffffff; -LAB_0807a27f: - // WARNING: Subroutine does not return - __cxa_throw(puVar5,&RESULT::typeinfo,0); -} - - - -void UseChangeObject(ulong CreatureID,Object *Obj) - -{ - bool bVar1; - bool bVar2; - TPlayer *pl; - TPlayer *pTVar3; - ulong _TypeID; - undefined4 *puVar4; - Object *this; - Object *Exclude; - int local_88; - int x; - int y; - int z; - Object local_6c [4]; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - ObjectType NewType; - - // try { // try from 0807a30b to 0807a849 has its CatchHandler @ 0807a850 - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,CHANGEUSE); - if (bVar1) { - pTVar3 = GetPlayer(CreatureID); - if (pTVar3 != (TPlayer *)0x0) { - Object::getObjectType(local_3c); - _TypeID = ObjectType::getAttribute((ObjectType *)local_3c,CHANGETARGET); - ObjectType::setTypeID((ObjectType *)&local_2c,_TypeID); - bVar1 = false; - Object::getObjectType(local_3c); - bVar2 = ObjectType::getFlag((ObjectType *)local_3c,UNPASS); - if (!bVar2) { - ObjectType::setTypeID((ObjectType *)local_3c,0); - ObjectType::setTypeID((ObjectType *)local_4c,local_3c[0].ObjectID); - if ((local_2c.ObjectID != local_4c[0].ObjectID) && - (bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,UNPASS), bVar2)) { - bVar1 = true; - } - } - if (bVar1) { - local_5c[0] = (Object)Obj->ObjectID; - local_4c[0].ObjectID = local_5c[0].ObjectID; - ClearField(local_5c,local_4c); - } - else { - bVar1 = false; - Object::getObjectType(local_5c); - bVar2 = ObjectType::getFlag((ObjectType *)local_5c,UNLAY); - if (!bVar2) { - ObjectType::setTypeID((ObjectType *)local_5c,0); - ObjectType::setTypeID((ObjectType *)local_4c,local_5c[0].ObjectID); - if ((local_2c.ObjectID != local_4c[0].ObjectID) && - (bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,UNLAY), bVar2)) { - bVar1 = true; - } - } - if (bVar1) { - local_4c[0] = (Object)Obj->ObjectID; - GetObjectCoordinates(local_4c,&local_88,&x,&y); - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { - local_4c[0].ObjectID = NONE.ObjectID; - GetMapContainer((int)local_6c,local_88 + 1,x); - this = (Object *)&z; - Object::getNextObject(this); - Exclude = local_4c; - } - else { - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { - x = x + 1; - z = NONE.ObjectID; - } - else { - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (bVar1) { - z = NONE.ObjectID; - local_88 = local_88 + -1; - } - else { - bVar1 = false; - bVar2 = CoordinateFlag(); - if (bVar2) { - bVar1 = CoordinateFlag(); - bVar1 = !bVar1; - } - if (!bVar1) goto LAB_0807a3d4; - x = x + -1; - z = NONE.ObjectID; - } - } - Exclude = (Object *)&z; - NONE.ObjectID = z; - GetMapContainer((int)local_6c,local_88,x); - Object::getNextObject(local_4c); - this = local_4c; - } - MoveAllObjects(this,local_6c,Exclude,true); - } - } -LAB_0807a3d4: - ObjectType::setTypeID((ObjectType *)&z,local_2c.ObjectID); - local_6c[0] = (Object)Obj->ObjectID; - Change(local_6c,(ObjectType *)&z,0); - return; - } - error("UseChangeObject: Spieler %d existiert nicht.\n",CreatureID); - goto LAB_0807a814; - } - } - error("UseChangeObject: Objekt existiert nicht oder ist kein CHANGEUSE-Objekt.\n"); -LAB_0807a814: - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void UseObject(ulong CreatureID,Object *Obj) - -{ - bool bVar1; - TCreature *cr; - TCreature *pTVar2; - undefined4 *puVar3; - char *Text; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object User; - - // try { // try from 0807a888 to 0807a967 has its CatchHandler @ 0807a985 - bVar1 = Object::exists(Obj); - if (bVar1) { - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,USEEVENT); - if (bVar1) { - if (CreatureID == 0) { - pTVar2 = (TCreature *)0x0; - } - else { - pTVar2 = GetCreature(CreatureID); - } - if (pTVar2 == (TCreature *)0x0) { - local_2c.ObjectID = NONE.ObjectID; - } - else { - local_2c.ObjectID = (pTVar2->CrObject).ObjectID; - } - local_3c[0] = (Object)NONE.ObjectID; - local_4c[0] = (Object)Obj->ObjectID; - local_5c[0].ObjectID = local_2c.ObjectID; - bVar1 = HandleEvent(EVENT_USE,local_5c,local_4c,local_3c); - if (bVar1) { - return; - } - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x1d; - goto LAB_0807a92d; - } - Text = &DAT_080f96c0; - } - else { - Text = &DAT_080f9700; - } - error(Text); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_0807a92d: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -void UseObjects(ulong CreatureID,Object *Obj1,Object *Obj2) - -{ - bool bVar1; - TCreature *cr; - TCreature *pTVar2; - undefined4 *puVar3; - char *Text; - Object local_5c [4]; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object User; - - // try { // try from 0807a9b8 to 0807aaa7 has its CatchHandler @ 0807aad0 - bVar1 = Object::exists(Obj1); - if (bVar1) { - bVar1 = Object::exists(Obj2); - if (bVar1) { - Object::getObjectType(&local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)&local_2c,USEEVENT); - if (bVar1) { - if (CreatureID == 0) { - pTVar2 = (TCreature *)0x0; - } - else { - pTVar2 = GetCreature(CreatureID); - } - local_5c[0].ObjectID = NONE.ObjectID; - if (pTVar2 != (TCreature *)0x0) { - local_5c[0].ObjectID = (pTVar2->CrObject).ObjectID; - } - local_3c[0] = (Object)Obj2->ObjectID; - local_4c[0] = (Object)Obj1->ObjectID; - local_2c.ObjectID = local_5c[0].ObjectID; - bVar1 = HandleEvent(EVENT_MULTIUSE,local_5c,local_4c,local_3c); - if (bVar1) { - return; - } - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x1d; - goto LAB_0807aa6d; - } - Text = &DAT_080f9740; - } - else { - Text = &DAT_080f9780; - } - } - else { - Text = &DAT_080f97c0; - } - error(Text); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_0807aa6d: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -void MovementEvent(Object *Obj,Object *Start,Object *Dest) - -{ - bool bVar1; - undefined4 *puVar2; - char *Text; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 0807ab0b to 0807aca1 has its CatchHandler @ 0807acc0 - bVar1 = Object::exists(Obj); - if (bVar1) { - bVar1 = Object::exists(Start); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (!bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST); - if (!bVar1) goto LAB_0807acaa; - } - bVar1 = Object::exists(Dest); - if (bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER); - if (!bVar1) { - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CHEST); - if (!bVar1) goto LAB_0807ac5d; - } - Object::getObjectType(local_2c); - bVar1 = ObjectType::getFlag((ObjectType *)local_2c,MOVEMENTEVENT); - if (!bVar1) { - return; - } - local_2c[0].ObjectID = NONE.ObjectID; - local_3c[0] = (Object)Obj->ObjectID; - local_4c[0].ObjectID = NONE.ObjectID; - HandleEvent(EVENT_MOVEMENT,local_4c,local_3c,local_2c); - bVar1 = Object::exists(Obj); - if (bVar1) { - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x1f; - goto LAB_0807ac18; - } -LAB_0807ac5d: - Text = "MovementEvent: \"Dest\" ist kein Container.\n"; - } - else { -LAB_0807acaa: - Text = "MovementEvent: \"Start\" ist kein Container.\n"; - } - } - else { - Text = &DAT_080f9880; - } - error(Text); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_0807ac18: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -void SeparationEvent(Object *Obj,Object *Start) - -{ - Object OVar1; - bool bVar2; - bool bVar3; - undefined4 *puVar4; - ulong uVar5; - char *Text; - Object local_6c; - Object Obj2; - Object local_5c; - Object Help; - Object local_4c; - ObjectType Target; - Object local_3c [4]; - Object local_2c; - Object Obj2_1; - - // try { // try from 0807acfb to 0807b14b has its CatchHandler @ 0807b160 - bVar2 = Object::exists(Obj); - if (bVar2) { - bVar2 = Object::exists(Start); - if (bVar2) { - Object::getObjectType(&local_2c); - if (local_2c.ObjectID != 0) { - return; - } - Object::getObjectType(&local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_2c,SEPARATIONEVENT); - if (bVar2) { - local_3c[0] = (Object)Start->ObjectID; - GetFirstContainerObject(&local_2c); - OVar1.ObjectID = local_5c.ObjectID; - do { - do { - local_5c.ObjectID = OVar1.ObjectID; - bVar2 = false; - local_3c[0].ObjectID = NONE.ObjectID; - local_4c.ObjectID = NONE.ObjectID; - if ((local_2c.ObjectID != NONE.ObjectID) && - (bVar3 = Object::exists(&local_2c), bVar3)) { - bVar2 = true; - } - if (!bVar2) goto LAB_0807ad65; - local_4c.ObjectID = local_2c.ObjectID; - Object::getNextObject(&local_5c); - local_2c.ObjectID = local_5c.ObjectID; - local_3c[0].ObjectID = local_5c.ObjectID; - uVar5 = Obj->ObjectID; - OVar1.ObjectID = local_4c.ObjectID; - } while (uVar5 == local_4c.ObjectID); - if (uVar5 == local_5c.ObjectID) { - Object::getNextObject(&local_6c); - local_2c.ObjectID = local_6c.ObjectID; - uVar5 = Obj->ObjectID; - } - local_6c.ObjectID = local_4c.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - local_5c.ObjectID = uVar5; - HandleEvent(EVENT_SEPARATION,local_3c,&local_5c,&local_6c); - bVar2 = Object::exists(Obj); - OVar1.ObjectID = local_5c.ObjectID; - } while (bVar2); - } - else { -LAB_0807ad65: - local_5c = (Object)Start->ObjectID; - GetFirstContainerObject(&local_6c); - do { - do { - bVar2 = false; - local_5c.ObjectID = NONE.ObjectID; - local_4c.ObjectID = NONE.ObjectID; - if ((local_6c.ObjectID != NONE.ObjectID) && - (bVar3 = Object::exists(&local_6c), bVar3)) { - bVar2 = true; - } - if (!bVar2) { - return; - } - local_5c.ObjectID = local_6c.ObjectID; - Object::getNextObject(local_3c); - local_6c.ObjectID = local_3c[0].ObjectID; - local_4c = (Object)Obj->ObjectID; - } while (local_5c.ObjectID == local_4c.ObjectID); - if (local_3c[0].ObjectID == local_4c.ObjectID) { - Object::getNextObject(&local_2c); - local_3c[0].ObjectID = local_2c.ObjectID; - } - local_6c.ObjectID = local_3c[0].ObjectID; - Object::getObjectType(&local_4c); - if (local_4c.ObjectID == 99) { - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,LEVELDOOR); - if (!bVar2) { - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,QUESTDOOR); - if (!bVar2) goto LAB_0807ae44; - } - Object::getObjectType(local_3c); - bVar2 = ObjectType::getFlag((ObjectType *)local_3c,LEVELDOOR); - Object::getObjectType(local_3c); - uVar5 = ObjectType::getAttribute - ((ObjectType *)local_3c,!bVar2 + LEVELDOORTARGET); - ObjectType::setTypeID((ObjectType *)&local_4c,uVar5); - bVar2 = false; - ObjectType::setTypeID((ObjectType *)local_3c,0); - if ((local_4c.ObjectID == local_3c[0].ObjectID) || - (bVar3 = ObjectType::getFlag((ObjectType *)&local_4c,UNPASS), !bVar3)) { - bVar2 = true; - } - if (!bVar2) { - local_3c[0] = (Object)Obj->ObjectID; - local_2c.ObjectID = local_5c.ObjectID; - ClearField(&local_2c,local_3c); - ObjectType::setTypeID((ObjectType *)local_3c,local_4c.ObjectID); - local_2c.ObjectID = local_5c.ObjectID; - Change(&local_2c,(ObjectType *)local_3c,0); - return; - } - Object::getObjectType(&local_2c); - error(&DAT_080f98c0,local_2c.ObjectID); - goto LAB_0807afdc; - } -LAB_0807ae44: - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,SEPARATIONEVENT); - if (bVar2) { - local_4c = (Object)Obj->ObjectID; - local_3c[0].ObjectID = local_5c.ObjectID; - local_2c.ObjectID = NONE.ObjectID; - HandleEvent(EVENT_SEPARATION,&local_2c,local_3c,&local_4c); - } - bVar2 = Object::exists(Obj); - } while (bVar2); - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x1f; - goto LAB_0807ae92; - } - Text = &DAT_080f9920; - } - else { - Text = &DAT_080f9960; - } - error(Text); -LAB_0807afdc: - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_0807ae92: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void CollisionEvent(Object *Obj,Object *Dest) - -{ - Object OVar1; - bool bVar2; - bool bVar3; - undefined4 *puVar4; - ulong uVar5; - char *Text; - Object *pOVar6; - int local_9c; - int dx_1; - int dy_1; - int dz_1; - int x_1; - int y_1; - int z_1; - int dx; - int dy; - int dz; - int x; - int y; - int z; - Object Obj2; - Object local_5c; - Object Help; - Object local_4c; - Object Obj2_1; - Object local_3c; - Object Help_1; - Object local_2c [7]; - - // try { // try from 0807b19b to 0807b86b has its CatchHandler @ 0807b890 - bVar2 = Object::exists(Obj); - if (bVar2) { - bVar2 = Object::exists(Dest); - if (bVar2) { - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID != 0) { - return; - } - Object::getObjectType(local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)local_2c,TELEPORTABSOLUTE); - if (bVar2) { -LAB_0807b228: - Object::getObjectType(local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)local_2c,TELEPORTABSOLUTE); - if (bVar2) { - Object::getAttribute(Obj,ABSTELEPORTDESTINATION); - UnpackAbsoluteCoordinate(); - } - else { - local_2c[0] = (Object)Obj->ObjectID; - GetObjectCoordinates(local_2c,&dz,&x,&y); - Object::getObjectType(local_2c); - ObjectType::getAttribute((ObjectType *)local_2c,RELTELEPORTDISPLACEMENT); - UnpackRelativeCoordinate(); - dz = dz + z_1; - x = x + dx; - y = y + dy; - } - local_2c[0].ObjectID = NONE.ObjectID; - GetMapContainer((int)&local_3c,dz,x); - Object::getNextObject(&local_4c); - MoveAllObjects(&local_4c,&local_3c,local_2c,true); - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,TELEPORTABSOLUTE); - Object::getObjectType(&local_4c); - ObjectType::getAttribute - ((ObjectType *)&local_4c,(uint)!bVar2 * 2 + ABSTELEPORTEFFECT); - pOVar6 = (Object *)x; - GraphicalEffect(); - bVar2 = Object::exists(Obj); - if (bVar2) { - return; - } - } - else { - Object::getObjectType(local_2c); - bVar2 = ObjectType::getFlag((ObjectType *)local_2c,TELEPORTRELATIVE); - if (bVar2) goto LAB_0807b228; - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,COLLISIONEVENT); - if (bVar2) { - local_3c = (Object)Dest->ObjectID; - GetFirstContainerObject(&local_4c); - OVar1.ObjectID = local_5c.ObjectID; - do { - do { - local_5c.ObjectID = OVar1.ObjectID; - bVar2 = false; - local_3c.ObjectID = NONE.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - if ((local_4c.ObjectID != NONE.ObjectID) && - (bVar3 = Object::exists(&local_4c), bVar3)) { - bVar2 = true; - } - if (!bVar2) goto LAB_0807b41e; - local_3c.ObjectID = local_4c.ObjectID; - Object::getNextObject(&local_5c); - local_4c.ObjectID = local_5c.ObjectID; - local_2c[0].ObjectID = local_5c.ObjectID; - uVar5 = Obj->ObjectID; - OVar1.ObjectID = local_3c.ObjectID; - } while (uVar5 == local_3c.ObjectID); - if (uVar5 == local_5c.ObjectID) { - Object::getNextObject((Object *)&z); - local_4c.ObjectID = z; - uVar5 = Obj->ObjectID; - } - z = local_3c.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - pOVar6 = local_2c; - local_5c.ObjectID = uVar5; - HandleEvent(EVENT_COLLISION,local_2c,&local_5c,(Object *)&z); - bVar2 = Object::exists(Obj); - OVar1.ObjectID = local_5c.ObjectID; - } while (bVar2); - } - else { -LAB_0807b41e: - local_5c = (Object)Dest->ObjectID; - GetFirstContainerObject((Object *)&z); - do { - do { - bVar2 = false; - local_5c.ObjectID = NONE.ObjectID; - local_4c.ObjectID = NONE.ObjectID; - if ((z != NONE.ObjectID) && - (bVar3 = Object::exists((Object *)&z), bVar3)) { - bVar2 = true; - } - if (!bVar2) { - return; - } - local_5c.ObjectID = z; - Object::getNextObject(&local_3c); - z = local_3c.ObjectID; - local_4c = (Object)Obj->ObjectID; - } while (local_5c.ObjectID == local_4c.ObjectID); - if (local_3c.ObjectID == local_4c.ObjectID) { - Object::getNextObject(local_2c); - local_3c.ObjectID = local_2c[0].ObjectID; - } - z = local_3c.ObjectID; - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,TELEPORTABSOLUTE); - if (bVar2) { -LAB_0807b4e5: - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,TELEPORTABSOLUTE); - if (bVar2) { - Object::getAttribute(&local_5c,ABSTELEPORTDESTINATION); - UnpackAbsoluteCoordinate(); - } - else { - local_4c.ObjectID = local_5c.ObjectID; - GetObjectCoordinates(&local_4c,&dz_1,&x_1,&y_1); - Object::getObjectType(&local_4c); - ObjectType::getAttribute - ((ObjectType *)&local_4c,RELTELEPORTDISPLACEMENT); - UnpackRelativeCoordinate(); - dz_1 = dz_1 + local_9c; - x_1 = x_1 + dx_1; - y_1 = y_1 + dy_1; - } - local_4c = (Object)Obj->ObjectID; - GetMapContainer((int)&local_3c,dz_1,x_1); - MoveOneObject(&local_4c,&local_3c); - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,TELEPORTABSOLUTE); - Object::getObjectType(&local_4c); - ObjectType::getAttribute - ((ObjectType *)&local_4c,(uint)!bVar2 * 2 + ABSTELEPORTEFFECT) - ; - pOVar6 = (Object *)x_1; - GraphicalEffect(); - } - else { - Object::getObjectType(&local_4c); - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,TELEPORTRELATIVE); - if (bVar2) goto LAB_0807b4e5; - Object::getObjectType(&local_4c); - pOVar6 = (Object *)0xd; - bVar2 = ObjectType::getFlag((ObjectType *)&local_4c,COLLISIONEVENT); - if (bVar2) { - local_4c = (Object)Obj->ObjectID; - local_3c.ObjectID = local_5c.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - pOVar6 = local_2c; - HandleEvent(EVENT_COLLISION,local_2c,&local_3c,&local_4c); - } - } - bVar2 = Object::exists(Obj); - } while (bVar2); - } - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4,pOVar6); - *puVar4 = 0x1f; - goto LAB_0807b364; - } - Text = &DAT_080f99a0; - } - else { - Text = &DAT_080f99e0; - } - error(Text); - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_0807b364: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -// WARNING: Variable defined which should be unmapped: z - -void LoadParameters(TReadScriptFile *Script,int *Parameters,int NumberOfParameters,...) - -{ - bool bVar1; - char cVar2; - int iVar3; - ulong uVar4; - char *pcVar5; - char *pcVar6; - char *pcVar7; - undefined1 uVar8; - char *Ident; - int local_24; - int i; - va_list va; - int x; - int y; - int z; - - if (5 < NumberOfParameters) { - error("LoadParameters: Zu viele Parameter (%d).\n",NumberOfParameters); - TReadScriptFile::error(Script,"too many parameters"); - } - if (NumberOfParameters != 0) { - if ((Script->Token != SPECIAL) || - (cVar2 = TReadScriptFile::getSpecial(Script), cVar2 != '(')) { - // try { // try from 0807b8eb to 0807bcc7 has its CatchHandler @ 0807bcd0 - TReadScriptFile::error(Script,"\'(\' expected"); - } - local_24 = 0; - i = (int)&stack0x00000010; - if (0 < NumberOfParameters) { - do { - if (0 < local_24) { - TReadScriptFile::readSymbol(Script,','); - } - uVar8 = *(int *)i == 0xb; - switch(*(int *)i) { - case 0: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = 5; - pcVar6 = pcVar5; - pcVar7 = "null"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar6 == *pcVar7; - pcVar6 = pcVar6 + 1; - pcVar7 = pcVar7 + 1; - } while ((bool)uVar8); - if ((bool)uVar8) { -LAB_0807ba55: - Parameters[local_24] = 0; - } - else { - iVar3 = 5; - pcVar6 = pcVar5; - pcVar7 = "obj1"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar6 == *pcVar7; - pcVar6 = pcVar6 + 1; - pcVar7 = pcVar7 + 1; - } while ((bool)uVar8); - if ((bool)uVar8) { - Parameters[local_24] = 1; - } - else { - iVar3 = 5; - pcVar6 = pcVar5; - pcVar7 = "obj2"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar6 == *pcVar7; - pcVar6 = pcVar6 + 1; - pcVar7 = pcVar7 + 1; - } while ((bool)uVar8); - if ((bool)uVar8) { - Parameters[local_24] = 2; - } - else { - iVar3 = 5; - pcVar6 = pcVar5; - pcVar7 = "user"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar6 == *pcVar7; - pcVar6 = pcVar6 + 1; - pcVar7 = pcVar7 + 1; - } while ((bool)uVar8); - if ((bool)uVar8) { - Parameters[local_24] = 3; - } - else { - iVar3 = 5; - pcVar6 = "temp"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar5 == *pcVar6; - pcVar5 = pcVar5 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar8); - if (!(bool)uVar8) { - pcVar5 = "Object expected"; - goto LAB_0807ba48; - } - Parameters[local_24] = 4; - } - } - } - } - break; - case 1: - iVar3 = TReadScriptFile::readNumber(Script); - Parameters[local_24] = iVar3; - bVar1 = ObjectTypeExists(iVar3); - if (!bVar1) { - pcVar5 = "Unknown object type"; -LAB_0807ba48: - TReadScriptFile::error(Script,pcVar5); - } - break; - case 2: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = GetFlagByName(pcVar5); - Parameters[local_24] = iVar3; - if (iVar3 == -1) { - pcVar5 = "Unknown flag"; - goto LAB_0807ba48; - } - break; - case 3: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = GetTypeAttributeByName(pcVar5); - Parameters[local_24] = iVar3; - if (iVar3 == -1) { - pcVar5 = "Unknown type attribute"; - goto LAB_0807ba48; - } - break; - case 4: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = GetInstanceAttributeByName(pcVar5); - Parameters[local_24] = iVar3; - if (iVar3 == -1) { - pcVar5 = "Unknown instance attribute"; - goto LAB_0807ba48; - } - break; - case 5: - TReadScriptFile::readCoordinate(Script); - uVar4 = PackAbsoluteCoordinate((int)va,x,y); - goto LAB_0807bb56; - case 6: - TReadScriptFile::readCoordinate(Script); - uVar4 = PackRelativeCoordinate((int)va,x,y); - goto LAB_0807bb9a; - case 7: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = 0x10; - pcVar6 = pcVar5; - pcVar7 = "premium_account"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar6 == *pcVar7; - pcVar6 = pcVar6 + 1; - pcVar7 = pcVar7 + 1; - } while ((bool)uVar8); - if ((bool)uVar8) goto LAB_0807ba55; - iVar3 = 0x10; - pcVar6 = "special_moveuse"; - do { - if (iVar3 == 0) break; - iVar3 = iVar3 + -1; - uVar8 = *pcVar5 == *pcVar6; - pcVar5 = pcVar5 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar8); - if (!(bool)uVar8) { - pcVar5 = "Unknown right"; - goto LAB_0807ba48; - } - Parameters[local_24] = 0x37; - break; - case 8: - pcVar5 = TReadScriptFile::readIdentifier(Script); - iVar3 = GetSkillByName(pcVar5); - Parameters[local_24] = iVar3; - if (iVar3 == -1) { - pcVar5 = "Unknown skill"; - goto LAB_0807ba48; - } - break; - case 9: - uVar4 = TReadScriptFile::readNumber(Script); -LAB_0807bb9a: - Parameters[local_24] = uVar4; - break; - case 10: - pcVar5 = TReadScriptFile::readString(Script); - uVar4 = AddDynamicString(pcVar5); -LAB_0807bb56: - Parameters[local_24] = uVar4; - break; - case 0xb: - cVar2 = TReadScriptFile::readSpecial(Script); - Parameters[local_24] = (int)cVar2; - pcVar5 = strchr("N",(int)cVar2); - if (pcVar5 == (char *)0x0) { - pcVar5 = "Unknown comparison operator"; - goto LAB_0807ba48; - } - } - local_24 = local_24 + 1; - i = i + 4; - } while (local_24 < NumberOfParameters); - } - TReadScriptFile::readSymbol(Script,')'); - TReadScriptFile::nextToken(Script); - } - return; -} - - - -void LoadCondition(TReadScriptFile *Script,TMoveUseCondition *Condition) - -{ - char *pcVar1; - int iVar2; - char *pcVar3; - undefined1 uVar4; - char local_3c [4]; - char Ident [30]; - - uVar4 = &stack0x00000000 == (undefined1 *)0x5c; - // try { // try from 0807bd05 to 0807c4e2 has its CatchHandler @ 0807c4e8 - pcVar1 = TReadScriptFile::getIdentifier(Script); - strcpy(local_3c,pcVar1); - TReadScriptFile::nextToken(Script); - iVar2 = 0xb; - pcVar1 = local_3c; - pcVar3 = "isposition"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISPOSITION; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "istype"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISTYPE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 0xb; - pcVar1 = local_3c; - pcVar3 = "iscreature"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISCREATURE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "isplayer"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISPLAYER; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "hasflag"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASFLAG; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 0x11; - pcVar1 = local_3c; - pcVar3 = "hastypeattribute"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASTYPEATTRIBUTE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,4); - } - iVar2 = 0x15; - pcVar1 = local_3c; - pcVar3 = "hasinstanceattribute"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASINSTANCEATTRIBUTE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,4); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "hastext"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASTEXT; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 0xb; - pcVar1 = local_3c; - pcVar3 = "ispeaceful"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISPEACEFUL; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "maylogout"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_MAYLOGOUT; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 0xe; - pcVar1 = local_3c; - pcVar3 = "hasprofession"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASPROFESSION; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "haslevel"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASLEVEL; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,3); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "hasright"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASRIGHT; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 0xe; - pcVar1 = local_3c; - pcVar3 = "hasquestvalue"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_HASQUESTVALUE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,4); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "testskill"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_TESTSKILL; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,4); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "countobjects"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_COUNTOBJECTS; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,3); - } - iVar2 = 0x12; - pcVar1 = local_3c; - pcVar3 = "countobjectsonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_COUNTOBJECTSONMAP; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,3); - } - iVar2 = 0xe; - pcVar1 = local_3c; - pcVar3 = "isobjectthere"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISOBJECTTHERE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 0x10; - pcVar1 = local_3c; - pcVar3 = "iscreaturethere"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISCREATURETHERE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 0xe; - pcVar1 = local_3c; - pcVar3 = "isplayerthere"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISPLAYERTHERE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 0x14; - pcVar1 = local_3c; - pcVar3 = "isobjectininventory"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISOBJECTININVENTORY; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,3); - } - iVar2 = 0x11; - pcVar1 = local_3c; - pcVar3 = "isprotectionzone"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISPROTECTIONZONE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "ishouse"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISHOUSE; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "ishouseowner"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISHOUSEOWNER; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,2); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "isdressed"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_ISDRESSED; - uVar4 = Condition->Parameters == (int *)0x0; - LoadParameters(Script,Condition->Parameters,1); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "random"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Condition->Condition = CONDITION_RANDOM; - LoadParameters(Script,Condition->Parameters,1); - } - return; -} - - - -void LoadAction(TReadScriptFile *Script,TMoveUseAction *Action) - -{ - char *pcVar1; - int iVar2; - char *pcVar3; - undefined1 uVar4; - char local_3c [4]; - char Ident [30]; - - uVar4 = &stack0x00000000 == (undefined1 *)0x5c; - // try { // try from 0807c515 to 0807d0d8 has its CatchHandler @ 0807d0e0 - pcVar1 = TReadScriptFile::getIdentifier(Script); - strcpy(local_3c,pcVar1); - TReadScriptFile::nextToken(Script); - iVar2 = 0xc; - pcVar1 = local_3c; - pcVar3 = "createonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CREATEONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "create"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CREATE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "monsteronmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MONSTERONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "monster"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MONSTER; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 0xc; - pcVar1 = local_3c; - pcVar3 = "effectonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_EFFECTONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "effect"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_EFFECT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "textonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_TEXTONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 5; - pcVar1 = local_3c; - pcVar3 = "text"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_TEXT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0xc; - pcVar1 = local_3c; - pcVar3 = "changeonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CHANGEONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,4); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "change"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CHANGE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "changerel"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CHANGEREL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,5); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "setattribute"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_SETATTRIBUTE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0x10; - pcVar1 = local_3c; - pcVar3 = "changeattribute"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_CHANGEATTRIBUTE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0xe; - pcVar1 = local_3c; - pcVar3 = "setquestvalue"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_SETQUESTVALUE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "damage"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DAMAGE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,4); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "setstart"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_SETSTART; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "writename"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_WRITENAME; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "writetext"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_WRITETEXT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "logout"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_LOGOUT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,1); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "moveallonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVEALLONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "moveall"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVEALL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 0xb; - pcVar1 = local_3c; - pcVar3 = "moveallrel"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVEALLREL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 0xd; - pcVar1 = local_3c; - pcVar3 = "movetoponmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVETOPONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "movetop"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVETOP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 0xb; - pcVar1 = local_3c; - pcVar3 = "movetoprel"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVETOPREL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 5; - pcVar1 = local_3c; - pcVar3 = "move"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 8; - pcVar1 = local_3c; - pcVar3 = "moverel"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_MOVEREL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "retrieve"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_RETRIEVE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0xf; - pcVar1 = local_3c; - pcVar3 = "deleteallonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DELETEALLONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,1); - } - iVar2 = 0xf; - pcVar1 = local_3c; - pcVar3 = "deletetoponmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DELETETOPONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 0xc; - pcVar1 = local_3c; - pcVar3 = "deleteonmap"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DELETEONMAP; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 7; - pcVar1 = local_3c; - pcVar3 = "delete"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DELETE; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,1); - } - iVar2 = 0x12; - pcVar1 = local_3c; - pcVar3 = "deleteininventory"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DELETEININVENTORY; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,3); - } - iVar2 = 0xc; - pcVar1 = local_3c; - pcVar3 = "description"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_DESCRIPTION; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,2); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "loaddepot"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_LOADDEPOT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,4); - } - iVar2 = 10; - pcVar1 = local_3c; - pcVar3 = "savedepot"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_SAVEDEPOT; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,4); - } - iVar2 = 9; - pcVar1 = local_3c; - pcVar3 = "sendmail"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_SENDMAIL; - uVar4 = Action->Parameters == (int *)0x0; - LoadParameters(Script,Action->Parameters,1); - } - iVar2 = 4; - pcVar1 = local_3c; - pcVar3 = "nop"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar4 = *pcVar1 == *pcVar3; - pcVar1 = pcVar1 + 1; - pcVar3 = pcVar3 + 1; - } while ((bool)uVar4); - if ((bool)uVar4) { - Action->Action = ACTION_NOP; - LoadParameters(Script,Action->Parameters,0); - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void LoadDataBase(void) - -{ - TReadScriptFile *Script_00; - char cVar1; - int i; - int iVar2; - TMoveUseAction *Action; - TMoveUseRule *pTVar3; - TMoveUseCondition *Condition_00; - int *piVar4; - int EventType; - int iVar5; - TMoveUseCondition *Condition; - char *pcVar6; - undefined1 uVar7; - char *pcVar8; - char local_501c [4]; - char Ident [30]; - TReadScriptFile Script; - undefined1 local_101c [4]; - char FileName [4096]; - - // try { // try from 0807d121 to 0807d151 has its CatchHandler @ 0807d510 - print(); - pcVar8 = DATAPATH; - Action = (TMoveUseAction *)local_101c; - sprintf((char *)Action,"%s/moveuse.dat"); - TReadScriptFile::TReadScriptFile((TReadScriptFile *)(Ident + 0x1c)); - // try { // try from 0807d15f to 0807d4d5 has its CatchHandler @ 0807d4f1 - TReadScriptFile::open((TReadScriptFile *)(Ident + 0x1c),(char *)Action,(int)pcVar8); - piVar4 = &MoveUseDatabases[0].NumberOfRules; - iVar2 = 4; - do { - *piVar4 = 0; - piVar4 = piVar4 + 0xc; - iVar2 = iVar2 + -1; - } while (-1 < iVar2); -LAB_0807d183: - TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)); - do { - uVar7 = stack0xffffb004 == 0; - if ((bool)uVar7) { - TReadScriptFile::close((TReadScriptFile *)(Ident + 0x1c),(int)Action); - pcVar8 = "Move/Use-Datenbank mit %d/%d/%d/%d/%d Regeln gelesen.\n"; - print(); - // try { // try from 0807d4df to 0807d4e3 has its CatchHandler @ 0807d510 - TReadScriptFile::~TReadScriptFile((TReadScriptFile *)(Ident + 0x1c),(int)pcVar8); - return; - } - Action = (TMoveUseAction *)TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c)) - ; - strcpy(local_501c,(char *)Action); - iVar2 = 6; - pcVar8 = local_501c; - pcVar6 = "begin"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - if ((bool)uVar7) { - TReadScriptFile::readString((TReadScriptFile *)(Ident + 0x1c)); - goto LAB_0807d183; - } - iVar2 = 4; - pcVar8 = local_501c; - pcVar6 = "end"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - if ((bool)uVar7) goto LAB_0807d183; - iVar2 = 4; - pcVar8 = local_501c; - pcVar6 = "use"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - iVar5 = -1; - iVar2 = 9; - if ((bool)uVar7) { - iVar5 = 0; - } - pcVar8 = local_501c; - pcVar6 = "multiuse"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - iVar2 = 9; - if ((bool)uVar7) { - iVar5 = 1; - } - pcVar8 = local_501c; - pcVar6 = "movement"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - iVar2 = 10; - if ((bool)uVar7) { - iVar5 = 2; - } - pcVar8 = local_501c; - pcVar6 = "collision"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - iVar2 = 0xb; - if ((bool)uVar7) { - iVar5 = 3; - } - pcVar8 = local_501c; - pcVar6 = "separation"; - do { - if (iVar2 == 0) break; - iVar2 = iVar2 + -1; - uVar7 = *pcVar8 == *pcVar6; - pcVar8 = pcVar8 + 1; - pcVar6 = pcVar6 + 1; - } while ((bool)uVar7); - if ((bool)uVar7) { - iVar5 = 4; - } - if (iVar5 == -1) { - TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"Unknown event type"); - } - iVar2 = MoveUseDatabases[iVar5].NumberOfRules + 1; - MoveUseDatabases[iVar5].NumberOfRules = iVar2; - pTVar3 = vector<>::operator()(&MoveUseDatabases[iVar5].Rules,iVar2); - pTVar3->FirstCondition = NumberOfMoveUseConditions + 1; - TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),','); - do { - TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)); - NumberOfMoveUseConditions = NumberOfMoveUseConditions + 1; - Condition_00 = vector<>::operator()(&MoveUseConditions,NumberOfMoveUseConditions); - Condition_00->Modifier = MODIFIER_NORMAL; - if (stack0xffffb004 == 6) { - cVar1 = TReadScriptFile::getSpecial((TReadScriptFile *)(Ident + 0x1c)); - if (cVar1 == '!') { - Condition_00->Modifier = MODIFIER_INVERT; - } - else { - if ((stack0xffffb004 != 6) || - (cVar1 = TReadScriptFile::getSpecial((TReadScriptFile *)(Ident + 0x1c)), - cVar1 != '~')) goto LAB_0807d301; - Condition_00->Modifier = MODIFIER_TRUE; - } - TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)); - } -LAB_0807d301: - LoadCondition((TReadScriptFile *)(Ident + 0x1c),Condition_00); - if (stack0xffffb004 != 6) goto LAB_0807d33a; - cVar1 = TReadScriptFile::getSpecial((TReadScriptFile *)(Ident + 0x1c)); - } while (cVar1 == ','); - if ((stack0xffffb004 != 6) || - (cVar1 = TReadScriptFile::getSpecial((TReadScriptFile *)(Ident + 0x1c)), cVar1 != 'I')) { -LAB_0807d33a: - TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"\'->\' expected"); - } - pTVar3->LastCondition = NumberOfMoveUseConditions; - TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)); - pTVar3->FirstAction = NumberOfMoveUseActions + 1; - while( true ) { - NumberOfMoveUseActions = NumberOfMoveUseActions + 1; - Action = vector<>::operator()(&MoveUseActions,NumberOfMoveUseActions); - Script_00 = (TReadScriptFile *)(Ident + 0x1c); - LoadAction(Script_00,Action); - if ((stack0xffffb004 != 6) || - (cVar1 = TReadScriptFile::getSpecial(Script_00), cVar1 != ',')) break; - TReadScriptFile::nextToken(Script_00); - } - if (stack0xffffb004 == 3) { - TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c)); - } - pTVar3->LastAction = NumberOfMoveUseActions; - } while( true ); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitMoveUse(void) - -{ - NumberOfMoveUseConditions = 0; - NumberOfMoveUseActions = 0; - // try { // try from 0807d534 to 0807d538 has its CatchHandler @ 0807d545 - LoadDataBase(); - DelayedMails = 0; - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ExitMoveUse(void) - -{ - TDelayedMail *pTVar1; - int i; - int i_00; - int iVar2; - - if ((0 < DelayedMails) && (i_00 = 0, 0 < DelayedMails)) { - do { - iVar2 = i_00 + 1; - pTVar1 = vector<>::operator()(&DelayedMail,i_00); - error("ExitMoveUse: Paket an %ld wurde nicht zugestellt.\n",pTVar1->CharacterID); - i_00 = iVar2; - } while (iVar2 < DelayedMails); - } - return; -} - - - void __tcf_0(void *param_1) { diff --git a/reference/types.hh b/reference/types.hh index ae021ad..513fb78 100644 --- a/reference/types.hh +++ b/reference/types.hh @@ -55,37 +55,12 @@ struct THouse { int Help; }; -struct TDelayedMail { - ulong CharacterID; - int DepotNumber; - uchar *Packet; - int PacketSize; -}; - struct THelpDepot { ulong CharacterID; struct Object Box; int DepotNr; }; -struct TMoveUseAction { - enum ActionType Action; - int Parameters[5]; -}; - -struct TMoveUseRule { - int FirstCondition; - int LastCondition; - int FirstAction; - int LastAction; -}; - -struct TMoveUseCondition { - enum ModifierType Modifier; - enum ConditionType Condition; - int Parameters[5]; -}; - struct THouseArea { ushort ID; int SQMPrice; @@ -177,11 +152,6 @@ struct TKillStatisticsOrderData { int *KilledCreatures; }; -struct TMoveUseDatabase { - struct vector Rules; - int NumberOfRules; -}; - struct TReaderThreadOrder { enum TReaderThreadOrderType OrderType; int SectorX; diff --git a/src/crcombat.cc b/src/crcombat.cc index df8b312..43c3f76 100644 --- a/src/crcombat.cc +++ b/src/crcombat.cc @@ -271,7 +271,7 @@ int TCombat::GetDefendDamage(void){ if(RemainingUses > 1){ Change(Shield, REMAININGUSES, RemainingUses - 1); }else{ - ObjectType WearOutType = ShieldType.getAttribute(WEAROUTTARGET); + ObjectType WearOutType = (int)ShieldType.getAttribute(WEAROUTTARGET); Change(Shield, WearOutType, 0); // TODO(fusion): Probably just check anyways, to be sure. if(!Shield.exists() || !WearOutType.getFlag(SHIELD)){ @@ -684,7 +684,7 @@ void TCombat::CloseAttack(TCreature *Target){ if(RemainingUses > 1){ Change(Close, REMAININGUSES, RemainingUses - 1); }else{ - ObjectType WearOutType = CloseType.getAttribute(WEAROUTTARGET); + ObjectType WearOutType = (int)CloseType.getAttribute(WEAROUTTARGET); Change(Close, WearOutType, 0); this->CheckCombatValues(); } diff --git a/src/crmain.cc b/src/crmain.cc index b786676..c70acb2 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -517,7 +517,7 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){ if(RemainingUses > 1){ Change(Obj, REMAININGUSES, RemainingUses - 1); }else{ - ObjectType WearOutType = ObjType.getAttribute(WEAROUTTARGET); + ObjectType WearOutType = (int)ObjType.getAttribute(WEAROUTTARGET); Change(Obj, WearOutType, 0); } }catch(RESULT r){ @@ -736,11 +736,11 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){ if(Attacker != NULL){ SendMessage(this->Connection, TALK_STATUS_MESSAGE, "You lose %d hitpoint%s due to an attack by %s.", - Damage, (Damage == 1 ? "" : "s"), Attacker->Name); + Damage, (Damage != 1 ? "s" : ""), Attacker->Name); }else{ SendMessage(this->Connection, TALK_STATUS_MESSAGE, "You lose %d hitpoint%s.", - Damage, (Damage == 1 ? "" : "s")); + Damage, (Damage != 1 ? "s" : "")); } SendPlayerData(this->Connection); } @@ -1052,12 +1052,12 @@ void ProcessCreatures(void){ continue; } - // TODO(fusion): It is weird that we do check the connection all the time - // and most of the time it is redundant because functions will check if - // it's NULL before attempting anything. - - int FoodInterval = Creature->Skills[SKILL_FED]->Get(); - if(FoodInterval > 0 && (RoundNr % FoodInterval) == 0 && !Creature->IsDead + // TODO(fusion): I'm almost sure this is processing ITEM regen rather + // FOOD regen. It wouldn't make a lot of sense to have this plus what + // happens in `TSkillFed::Event` if we didn't consider things like the + // life ring, etc... + int RegenInterval = Creature->Skills[SKILL_FED]->Get(); + if(RegenInterval > 0 && (RoundNr % RegenInterval) == 0 && !Creature->IsDead && !IsProtectionZone(Creature->posx, Creature->posy, Creature->posz)){ Creature->Skills[SKILL_HITPOINTS]->Change(1); Creature->Skills[SKILL_MANA]->Change(4); @@ -1701,13 +1701,19 @@ void LoadRaces(void){ throw "Cannot load races"; } - char FilePath[4096]; + char FileName[4096]; while(dirent *DirEntry = readdir(MonsterDir)){ + if(DirEntry->d_type != DT_REG){ + continue; + } + const char *FileExt = findLast(DirEntry->d_name, '.'); - if(FileExt != NULL && strcmp(FileExt, ".mon") == 0){ - snprintf(FilePath, sizeof(FilePath), "%s/%s", MONSTERPATH, DirEntry->d_name); - LoadRace(FilePath); + if(FileExt == NULL || strcmp(FileExt, ".mon") != 0){ + continue; } + + snprintf(FileName, sizeof(FileName), "%s/%s", MONSTERPATH, DirEntry->d_name); + LoadRace(FileName); } closedir(MonsterDir); @@ -1929,44 +1935,49 @@ void LoadMonsterRaids(void){ char FileName[4096]; while(dirent *DirEntry = readdir(MonsterDir)){ + if(DirEntry->d_type != DT_REG){ + continue; + } + const char *FileExt = findLast(DirEntry->d_name, '.'); - if(FileExt != NULL && strcmp(FileExt, ".evt") == 0){ - snprintf(FileName, sizeof(FileName), "%s/%s", MONSTERPATH, DirEntry->d_name); - - bool BigRaid; - int Date, Interval, Duration; - LoadMonsterRaid(FileName, -1, &BigRaid, &Date, &Interval, &Duration); - print(1, "Raid %s: Date %d, Interval %d, Duration %d\n", - FileName, Date, Interval, Duration); - - if(Date > 0){ - if(Now <= Date && Date <= (Now + SecondsToReboot)){ - int Start = RoundNr + (Date - Now); - LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); - if(BigRaid){ - BigRaidName[0] = 0; - BigRaidDuration = 0; - BigRaidTieBreaker = 100; - } + if(FileExt == NULL || strcmp(FileExt, ".evt") != 0){ + continue; + } + + bool BigRaid; + int Date, Interval, Duration; + snprintf(FileName, sizeof(FileName), "%s/%s", MONSTERPATH, DirEntry->d_name); + LoadMonsterRaid(FileName, -1, &BigRaid, &Date, &Interval, &Duration); + print(1, "Raid %s: Date %d, Interval %d, Duration %d\n", + FileName, Date, Interval, Duration); + + if(Date > 0){ + if(Now <= Date && Date <= (Now + SecondsToReboot)){ + int Start = RoundNr + (Date - Now); + LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); + if(BigRaid){ + BigRaidName[0] = 0; + BigRaidDuration = 0; + BigRaidTieBreaker = 100; } - }else if(Duration <= SecondsToReboot){ - // NOTE(fusion): `Interval` specifies an average raid interval - // in seconds. With this function being called at startup, usually - // after a reboot, we can expect `SecondsToReboot` to be close to - // a day very regularly. Meaning we can approximate the condition - // below to `random(1, AverageIntervalDays) == 1` which hopefully - // makes more sense. - if(random(0, Interval - 1) < SecondsToReboot){ - if(!BigRaid){ - int Start = RoundNr + random(0, SecondsToReboot - Duration); - LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); - }else{ - int TieBreaker = random(0, 99); - if(TieBreaker > BigRaidTieBreaker){ - strcpy(BigRaidName, FileName); - BigRaidDuration = Duration; - BigRaidTieBreaker = TieBreaker; - } + } + }else if(Duration <= SecondsToReboot){ + // NOTE(fusion): `Interval` specifies an average raid interval + // in seconds. With this function being called at startup, usually + // after a reboot, we can expect `SecondsToReboot` to be close to + // a day very regularly. Meaning we can approximate the condition + // below to `random(1, AverageIntervalDays) == 1` which hopefully + // makes more sense. + if(random(0, Interval - 1) < SecondsToReboot){ + if(!BigRaid){ + int Start = RoundNr + random(0, SecondsToReboot - Duration); + LoadMonsterRaid(FileName, Start, NULL, NULL, NULL, NULL); + }else{ + int TieBreaker = random(0, 99); + if(TieBreaker > BigRaidTieBreaker){ + strcpy(BigRaidName, FileName); + BigRaidDuration = Duration; + BigRaidTieBreaker = TieBreaker; } } } diff --git a/src/crnonpl.cc b/src/crnonpl.cc index 3d43012..b05a5e5 100644 --- a/src/crnonpl.cc +++ b/src/crnonpl.cc @@ -1747,7 +1747,7 @@ void TNPC::IdleStimulus(void){ return; } - bool FoundDest = false; + bool DestFound = false; int DestX, DestY, DestZ; for(int i = 0; i < 10; i += 1){ DestX = this->posx; @@ -1761,12 +1761,12 @@ void TNPC::IdleStimulus(void){ } if(this->MovePossible(DestX, DestY, DestZ, true, false)){ - FoundDest = true; + DestFound = true; break; } } - if(FoundDest){ + if(DestFound){ try{ this->ToDoGo(DestX, DestY, DestZ, true, INT_MAX); this->ToDoWait(2000); diff --git a/src/crplayer.cc b/src/crplayer.cc index 2660c04..9978527 100644 --- a/src/crplayer.cc +++ b/src/crplayer.cc @@ -1,6 +1,7 @@ #include "cr.hh" #include "config.hh" #include "info.hh" +#include "moveuse.hh" #include "operate.hh" #include "query.hh" #include "threads.hh" diff --git a/src/enums.hh b/src/enums.hh index 6d6baf0..9dad622 100644 --- a/src/enums.hh +++ b/src/enums.hh @@ -126,37 +126,6 @@ enum Color: int { COLOR_WHITE = 215, }; -// TODO(fusion): These are used with `TMoveUseCondition`. Probably add a -// `MOVEUSE` prefix not to mix with `TBehaviourCondition`? -enum ConditionType: int { - CONDITION_ISPOSITION = 0, - CONDITION_ISTYPE = 1, - CONDITION_ISCREATURE = 2, - CONDITION_ISPLAYER = 3, - CONDITION_HASFLAG = 4, - CONDITION_HASTYPEATTRIBUTE = 5, - CONDITION_HASINSTANCEATTRIBUTE = 6, - CONDITION_HASTEXT = 7, - CONDITION_ISPEACEFUL = 8, - CONDITION_MAYLOGOUT = 9, - CONDITION_HASPROFESSION = 10, - CONDITION_HASLEVEL = 11, - CONDITION_HASRIGHT = 12, - CONDITION_HASQUESTVALUE = 13, - CONDITION_TESTSKILL = 14, - CONDITION_COUNTOBJECTS = 15, - CONDITION_COUNTOBJECTSONMAP = 16, - CONDITION_ISOBJECTTHERE = 17, - CONDITION_ISCREATURETHERE = 18, - CONDITION_ISPLAYERTHERE = 19, - CONDITION_ISOBJECTININVENTORY = 20, - CONDITION_ISPROTECTIONZONE = 21, - CONDITION_ISHOUSE = 22, - CONDITION_ISHOUSEOWNER = 23, - CONDITION_ISDRESSED = 24, - CONDITION_RANDOM = 25, -}; - enum CONNECTIONSTATE: int { CONNECTION_FREE = 0, CONNECTION_ASSIGNED = 1, diff --git a/src/info.cc b/src/info.cc index 8f520cf..13e777f 100644 --- a/src/info.cc +++ b/src/info.cc @@ -179,6 +179,9 @@ uint32 GetObjectCreatureID(Object Obj){ return CreatureID; } +// TODO(fusion): I'm not sure about this one. Objects inside containers would +// also return the body position of the container even if it isn't activelly +// equipped. int GetObjectBodyPosition(Object Obj){ if(!Obj.exists()){ error("GetObjectBodyPosition: Übergebenes Objekt existiert nicht.\n"); diff --git a/src/magic.cc b/src/magic.cc index 19a9dc8..e268a7d 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -2561,7 +2561,7 @@ void ChangeData(TCreature *Actor, const char *Param){ } if(Attribute != -1){ - Change(Obj, Attribute, Value); + Change(Obj, (INSTANCEATTRIBUTE)Attribute, Value); GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, EFFECT_MAGIC_GREEN); }else{ SendMessage(Actor->Connection, TALK_FAILURE_MESSAGE, diff --git a/src/main.cc b/src/main.cc index f4df04d..4b52ab2 100644 --- a/src/main.cc +++ b/src/main.cc @@ -4,6 +4,7 @@ #include "info.hh" #include "map.hh" #include "magic.hh" +#include "moveuse.hh" #include "objects.hh" #include "operate.hh" #include "query.hh" @@ -227,7 +228,7 @@ static void InitAll(void){ InitObjects(); InitMap(); InitInfo(); - //InitMoveUse(); + InitMoveUse(); InitMagic(); InitCr(); //InitHouses(); @@ -246,7 +247,7 @@ static void ExitAll(void){ ExitTime(); ExitCr(); ExitMagic(); - //ExitMoveUse(); + ExitMoveUse(); ExitInfo(); //ExitHouses(); ExitMap(SaveMapOn); diff --git a/src/map.cc b/src/map.cc index 9eb29cd..64886bf 100644 --- a/src/map.cc +++ b/src/map.cc @@ -760,19 +760,23 @@ void DeleteSwappedSectors(void){ return; } - char FilePath[4096]; + char FileName[4096]; while(dirent *DirEntry = readdir(SwapDir)){ - if(DirEntry->d_type == DT_REG){ - // NOTE(fusion): `DirEntry->d_name` will only contain the filename - // so we need to assemble the actual file path (relative in this - // case) to properly unlink it. Windows has the same behavior with - // its `FindFirstFile`/`FindNextFile` API. - const char *FileExt = findLast(DirEntry->d_name, '.'); - if(FileExt != NULL && strcmp(FileExt, ".swp") == 0){ - snprintf(FilePath, sizeof(FilePath), "%s/%s", SAVEPATH, DirEntry->d_name); - unlink(FilePath); - } + if(DirEntry->d_type != DT_REG){ + continue; } + + // NOTE(fusion): `DirEntry->d_name` will only contain the filename + // so we need to assemble the actual file path (relative in this + // case) to properly unlink it. Windows has the same behavior with + // its `FindFirstFile`/`FindNextFile` API. + const char *FileExt = findLast(DirEntry->d_name, '.'); + if(FileExt == NULL || strcmp(FileExt, ".swp") != 0){ + continue; + } + + snprintf(FileName, sizeof(FileName), "%s/%s", SAVEPATH, DirEntry->d_name); + unlink(FileName); } closedir(SwapDir); @@ -1020,19 +1024,23 @@ void LoadMap(void){ ObjectCounter = 0; int SectorCounter = 0; - char FilePath[4096]; + char FileName[4096]; while(dirent *DirEntry = readdir(MapDir)){ - if(DirEntry->d_type == DT_REG){ - // NOTE(fusion): See note in `DeleteSwappedSectors`. - const char *FileExt = findLast(DirEntry->d_name, '.'); - if(FileExt != NULL && strcmp(FileExt, ".sec") == 0){ - int SectorX, SectorY, SectorZ; - if(sscanf(DirEntry->d_name, "%d-%d-%d.sec", &SectorX, &SectorY, &SectorZ) == 3){ - snprintf(FilePath, sizeof(FilePath), "%s/%s", SAVEPATH, DirEntry->d_name); - LoadSector(FilePath, SectorX, SectorY, SectorZ); - SectorCounter += 1; - } - } + if(DirEntry->d_type != DT_REG){ + continue; + } + + // NOTE(fusion): See note in `DeleteSwappedSectors`. + const char *FileExt = findLast(DirEntry->d_name, '.'); + if(FileExt == NULL || strcmp(FileExt, ".sec") != 0){ + continue; + } + + int SectorX, SectorY, SectorZ; + if(sscanf(DirEntry->d_name, "%d-%d-%d.sec", &SectorX, &SectorY, &SectorZ) == 3){ + snprintf(FileName, sizeof(FileName), "%s/%s", SAVEPATH, DirEntry->d_name); + LoadSector(FileName, SectorX, SectorY, SectorZ); + SectorCounter += 1; } } diff --git a/src/moveuse.cc b/src/moveuse.cc index f11fffa..9cdcd95 100644 --- a/src/moveuse.cc +++ b/src/moveuse.cc @@ -1,27 +1,424 @@ +#include "moveuse.hh" +#include "config.hh" +#include "info.hh" #include "operate.hh" -// NOTE(fusion): Oh no. +#include "stubs.hh" + +static vector MoveUseConditions(1, 1000, 1000); +static int NumberOfMoveUseConditions; + +static vector MoveUseActions(1, 1000, 1000); +static int NumberOfMoveUseActions; + +static TMoveUseDatabase MoveUseDatabases[5]; + +static vector DelayedMail(0, 10, 10); +static int DelayedMails; + +// Coordinate Packing +// ============================================================================= +int PackAbsoluteCoordinate(int x, int y, int z){ + // DOMAIN: [24576, 40959] x [24576, 40959] x [0, 15] + int Packed = (((x - 24576) & 0x00003FFF) << 18) + | (((y - 24576) & 0x00003FFF) << 4) + | (z & 0x0000000F); + return Packed; +} + +void UnpackAbsoluteCoordinate(int Packed, int *x, int *y, int *z){ + *x = ((Packed >> 18) & 0x00003FFF) + 24576; + *y = ((Packed >> 4) & 0x00003FFF) + 24576; + *z = ((Packed >> 0) & 0x0000000F); +} + +int PackRelativeCoordinate(int x, int y, int z){ + // DOMAIN: [-8192, 8191] x [-8192, 8191] x [-8, 7] + int Packed = (((x + 8192) & 0x00003FFF) << 18) + | (((y + 8192) & 0x00003FFF) << 4) + | ((z + 8) & 0x0000000F); + return Packed; +} + +void UnpackRelativeCoordinate(int Packed, int *x, int *y, int *z){ + *x = ((Packed >> 18) & 0x00003FFF) - 8192; + *y = ((Packed >> 4) & 0x00003FFF) - 8192; + *z = ((Packed >> 0) & 0x0000000F) - 8; +} + +// Event Execution +// ============================================================================= +Object GetEventObject(int Nr, Object User, Object Obj1, Object Obj2, Object Temp){ + Object Obj = NONE; + switch(Nr){ + case 0: Obj = NONE; break; + case 1: Obj = Obj1; break; + case 2: Obj = Obj2; break; + case 3: Obj = User; break; + case 4: Obj = Temp; break; + default:{ + error("GetEventObject: Unbekannte Nummer %d.\n", Nr); + break; + } + } + return Obj; +} + +bool Compare(int Value1, int Operator, int Value2){ + bool Result = false; + switch(Operator){ + case '<': Result = (Value1 < Value2); break; + case '>': Result = (Value1 > Value2); break; + case '=': Result = (Value1 == Value2); break; + case 'N': Result = (Value1 != Value2); break; + case 'L': Result = (Value1 <= Value2); break; + case 'G': Result = (Value1 >= Value2); break; + default:{ + error("Compare: Ungültiger Operator %d.\n", Operator); + break; + } + } + return Result; +} + +bool CheckCondition(MoveUseEventType EventType, TMoveUseCondition *Condition, + Object User, Object Obj1, Object Obj2, Object *Temp){ + bool Result = false; + switch(Condition->Condition){ + case MOVEUSE_CONDITION_ISPOSITION:{ + int ObjX, ObjY, ObjZ, CoordX, CoordY, CoordZ; + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackAbsoluteCoordinate(Condition->Parameters[1], &CoordX, &CoordY, &CoordZ); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Result = (ObjX == CoordX && ObjY == CoordY && ObjZ == CoordZ); + break; + } + + case MOVEUSE_CONDITION_ISTYPE:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + Result = (Obj.getObjectType().TypeID == Condition->Parameters[1]); + break; + } + + case MOVEUSE_CONDITION_ISCREATURE:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + Result = Obj.getObjectType().isCreatureContainer(); + break; + } + + case MOVEUSE_CONDITION_ISPLAYER:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + Result = (Creature && Creature->Type == PLAYER); + } + break; + } + + case MOVEUSE_CONDITION_HASFLAG:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + Result = Obj.getObjectType().getFlag((FLAG)Condition->Parameters[1]); + break; + } + + case MOVEUSE_CONDITION_HASTYPEATTRIBUTE:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int Attribute = (int)Obj.getObjectType().getAttribute((TYPEATTRIBUTE)Condition->Parameters[1]); + int Operator = Condition->Parameters[2]; + int Value = Condition->Parameters[3]; + Result = Compare(Attribute, Operator, Value); + break; + } + + case MOVEUSE_CONDITION_HASINSTANCEATTRIBUTE:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int Attribute = (int)Obj.getAttribute((INSTANCEATTRIBUTE)Condition->Parameters[1]); + int Operator = Condition->Parameters[2]; + int Value = Condition->Parameters[3]; + Result = Compare(Attribute, Operator, Value); + break; + } + + case MOVEUSE_CONDITION_HASTEXT:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + const char *Attribute = GetDynamicString(Obj.getAttribute(TEXTSTRING)); + const char *Text = GetDynamicString(Condition->Parameters[1]); + Result = (strcmp(Attribute, Text) == 0); + break; + } + + case MOVEUSE_CONDITION_ISPEACEFUL:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + Result = (Creature && Creature->IsPeaceful()); + } + break; + } + + case MOVEUSE_CONDITION_MAYLOGOUT:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + Result = (Creature != NULL && Creature->Type == PLAYER + && Creature->LogoutPossible() == 0); + } + break; + } + + case MOVEUSE_CONDITION_HASPROFESSION:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int Profession = Condition->Parameters[1]; + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + Result = (Creature != NULL && Creature->Type == PLAYER + && ((TPlayer*)Creature)->GetEffectiveProfession() == Profession); + } + break; + } + + case MOVEUSE_CONDITION_HASLEVEL:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int Operator = Condition->Parameters[1]; + int Value = Condition->Parameters[2]; + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + if(Creature != NULL){ + int Level = Creature->Skills[SKILL_LEVEL]->Get(); + Result = Compare(Level, Operator, Value); + } + } + break; + } + + case MOVEUSE_CONDITION_HASRIGHT:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + RIGHT Right = (RIGHT)Condition->Parameters[1]; + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + Result = (Creature != NULL && Creature->Type == PLAYER + && CheckRight(Creature->ID, Right)); + } + break; + } + + case MOVEUSE_CONDITION_HASQUESTVALUE:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int QuestNr = Condition->Parameters[1]; + int Operator = Condition->Parameters[2]; + int Value = Condition->Parameters[3]; + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + if(Creature != NULL && Creature->Type == PLAYER){ + int QuestValue = ((TPlayer*)Creature)->GetQuestValue(QuestNr); + Result = Compare(QuestValue, Operator, Value); + } + } + break; + } + + case MOVEUSE_CONDITION_TESTSKILL:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int SkillNr = Condition->Parameters[1]; + int Difficulty = Condition->Parameters[2]; + int Probability = Condition->Parameters[3]; + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + if(Creature != NULL){ + if(SkillNr >= 0 && SkillNr < NARRAY(Creature->Skills)){ + Result = Creature->Skills[SkillNr]->Probe(Difficulty, Probability, true); + }else{ + error("CheckCondition (TestSkill): Ungültige Skillnummer %d.\n", SkillNr); + } + } + } + break; + } + + // TODO(fusion): This also counts objects at the object's map location? + case MOVEUSE_CONDITION_COUNTOBJECTS:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + int Operator = Condition->Parameters[1]; + int Value = Condition->Parameters[2]; + Object MapCon = GetMapContainer(Obj); + int ObjCount = CountObjectsInContainer(MapCon); + Result = Compare(ObjCount, Operator, Value); + break; + } + + case MOVEUSE_CONDITION_COUNTOBJECTSONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Condition->Parameters[0], &CoordX, &CoordY, &CoordZ); + int Operator = Condition->Parameters[1]; + int Value = Condition->Parameters[2]; + Object MapCon = GetMapContainer(CoordX, CoordY, CoordZ); + int ObjCount = CountObjectsInContainer(MapCon); + Result = Compare(ObjCount, Operator, Value); + break; + } + + case MOVEUSE_CONDITION_ISOBJECTTHERE:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Condition->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Condition->Parameters[1]; + *Temp = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + Result = (*Temp != NONE); + break; + } + + case MOVEUSE_CONDITION_ISCREATURETHERE:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Condition->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = TYPEID_CREATURE_CONTAINER; + *Temp = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + Result = (*Temp != NONE); + break; + } + + // TODO(fusion): I feel this one should iterate the field because there + // could be more than one creature. + case MOVEUSE_CONDITION_ISPLAYERTHERE:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Condition->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = TYPEID_CREATURE_CONTAINER; + *Temp = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + if(*Temp != NONE){ + TCreature *Creature = GetCreature(*Temp); + Result = Creature && Creature->Type == PLAYER; + } + break; + } + + case MOVEUSE_CONDITION_ISOBJECTININVENTORY:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + ObjectType Type = Condition->Parameters[1]; + int Count = Condition->Parameters[2]; + if(Obj.getObjectType().isCreatureContainer()){ + *Temp = GetInventoryObject(Obj.getCreatureID(), Type, Count); + Result = (*Temp != NONE); + } + break; + } + + case MOVEUSE_CONDITION_ISPROTECTIONZONE:{ + int ObjX, ObjY, ObjZ; + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Result = IsProtectionZone(ObjX, ObjY, ObjZ); + break; + } + + case MOVEUSE_CONDITION_ISHOUSE:{ + int ObjX, ObjY, ObjZ; + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Result = IsHouse(ObjX, ObjY, ObjZ); + break; + } + + case MOVEUSE_CONDITION_ISHOUSEOWNER:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + Object Cr = GetEventObject(Condition->Parameters[1], User, Obj1, Obj2, *Temp); + if(Cr.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Cr); + if(Creature != NULL && Creature->Type == PLAYER){ + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + uint16 HouseID = GetHouseID(ObjX, ObjY, ObjZ); + Result = IsOwner(HouseID, (TPlayer*)Creature); + } + } + break; + } + + case MOVEUSE_CONDITION_ISDRESSED:{ + Object Obj = GetEventObject(Condition->Parameters[0], User, Obj1, Obj2, *Temp); + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(CLOTHES)){ + int CurPosition = GetObjectBodyPosition(Obj); + int ObjPosition = (int)ObjType.getAttribute(BODYPOSITION); + Result = (CurPosition == ObjPosition); + }else{ + error("CheckCondition (IsDressed): Objekt ist kein Kleidungsstück.\n"); + } + break; + } + + case MOVEUSE_CONDITION_RANDOM:{ + Result = (random(1, 100) <= Condition->Parameters[0]); + break; + } + + default:{ + error("CheckCondition: Unbekannte Bedingung %d.\n", Condition->Condition); + return false; + } + } + + if(Condition->Modifier == MOVEUSE_MODIFIER_NORMAL){ + // no-op + }else if(Condition->Modifier == MOVEUSE_MODIFIER_INVERT){ + Result = !Result; + }else if(Condition->Modifier == MOVEUSE_MODIFIER_TRUE){ + Result = true; + }else{ + // TODO(fusion): Error? + Result = false; + } + + return Result; +} + +Object CreateObject(Object Con, ObjectType Type, uint32 Value){ + for(int Attempt = 0; true; Attempt += 1){ + try{ + Object Obj = NONE; + ObjectType ConType = Con.getObjectType(); + if(ConType.isBodyContainer()){ + uint32 CreatureID = GetObjectCreatureID(Con); + Obj = CreateAtCreature(CreatureID, Type, Value); + }else{ + Obj = Create(Con, Type, Value); + } + return Obj; + }catch(RESULT r){ + if(Attempt == 0 && (r == NOTTAKABLE || r == TOOHEAVY || r == CONTAINERFULL)){ + // NOTE(fusion): Try to create object on the map, ONCE. + Con = GetMapContainer(Con); + }else{ + int ConX, ConY, ConZ; + GetObjectCoordinates(Con, &ConX, &ConY, &ConZ); + error("moveuse::CreateObject: Exception %d, Objekt %d, Position [%d,%d,%d].\n", + r, Type.TypeID, ConX, ConY, ConZ); + return NONE; + } + } + } +} + void ChangeObject(Object Obj, ObjectType NewType, uint32 Value){ if(!Obj.exists()){ error("ChangeObject: Übergebenes Objekt existiert nicht (1, NewType=%d).\n", NewType.TypeID); return; } - Object Con = Obj.getContainer(); - while(true){ + // NOTE(fusion): `Change` requires CUMULATIVE objects to have AMOUNT + // equal to ONE or it fails with `SPLITOBJECT`. This means might need + // to split the object and the split destination may change depending + // on how things go. + Object SplitDest = Obj.getContainer(); + for(int Attempt = 0; true; Attempt += 1){ if(!Obj.exists()){ error("ChangeObject: Übergebenes Objekt existiert nicht (2, NewType=%d).\n", NewType.TypeID); return; } try{ - // NOTE(fusion): `Change` requires CUMULATIVE objects to have AMOUNT - // equal to one or it fails with `SPLITOBJECT`. ObjectType ObjType = Obj.getObjectType(); if(ObjType.getFlag(CUMULATIVE)){ uint32 Amount = Obj.getAttribute(AMOUNT); if(Amount > 1){ - Move(0, Obj, Con, Amount - 1, true, NONE); + Move(0, Obj, SplitDest, Amount - 1, true, NONE); } } @@ -33,20 +430,25 @@ void ChangeObject(Object Obj, ObjectType NewType, uint32 Value){ return; } + // TODO(fusion): I feel a couple of attempts should be enough? + if(Attempt >= 2){ + throw; + } + if(r == CONTAINERFULL){ - Con = GetMapContainer(Obj); + // NOTE(fusion): Set `SplitDest` to map. + SplitDest = GetMapContainer(Obj); }else if(r == TOOHEAVY){ + // NOTE(fusion): Move object to map, keep `SplitDest`. Object MapCon = GetMapContainer(Obj); Move(0, Obj, MapCon, -1, true, NONE); - }else if(r == NOROOM){ - if(!Obj.getObjectType().getFlag(CUMULATIVE) - || Obj.getAttribute(AMOUNT) <= 1){ - throw; - } - - // TODO(fusion): Why do we use `Con` with `GetMapContainer` here? + }else if(r == NOROOM + && Obj.getObjectType().getFlag(CUMULATIVE) + && Obj.getAttribute(AMOUNT) > 1){ + // NOTE(fusion): Split to map directly. Similar to setting `SplitDest` + // to map, although failing here will throw us out of the function. uint32 Amount = Obj.getAttribute(AMOUNT); - Object MapCon = GetMapContainer(Con); + Object MapCon = GetMapContainer(SplitDest); Move(0, Obj, MapCon, Amount - 1, true, NONE); }else{ throw; @@ -54,3 +456,2610 @@ void ChangeObject(Object Obj, ObjectType NewType, uint32 Value){ } } } + +void MoveOneObject(Object Obj, Object Con){ + if(!Obj.exists()){ + error("MoveOneObject: Übergebenes Objekt existiert nicht.\n"); + return; + } + + if(!Con.exists()){ + error("MoveOneObject: Übergebener Container existiert nicht.\n"); + return; + } + + ObjectType ConType = Con.getObjectType(); + if(!ConType.getFlag(CONTAINER)){ + error("MoveOneObject: \"Con\" ist kein Container.\n"); + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer() && !ConType.isMapContainer()){ + error("MoveOneObject: \"Con\" ist kein MapContainer.\n"); + return; + } + + try{ + if(ObjType.getFlag(LIQUIDPOOL) || ObjType.getFlag(MAGICFIELD)){ + Delete(Obj, -1); + }else{ + Move(0, Obj, Con, -1, true, NONE); + } + }catch(RESULT r){ + if(r != DESTROYED){ + int ConX, ConY, ConZ; + GetObjectCoordinates(Con, &ConX, &ConY, &ConZ); + error("MoveOneObject: Exception %d; Koordinate [%d,%d,%d].\n", + r, ConX, ConY, ConZ); + } + + if(r == CONTAINERFULL){ + Delete(Obj, -1); + } + } +} + +void MoveAllObjects(Object Obj, Object Dest, Object Exclude, bool MoveUnmovable){ + if(Obj == NONE){ + return; + } + + if(!Dest.getObjectType().isMapContainer()){ + error("MoveAllObjects: \"Dest\" ist kein Mapcontainer.\n"); + return; + } + + // TODO(fusion): We probably use recursion to move objects in reverse order? + MoveAllObjects(Obj.getNextObject(), Dest, Exclude, MoveUnmovable); + + if(Obj != Exclude){ + ObjectType ObjType = Obj.getObjectType(); + try{ + if(ObjType.getFlag(LIQUIDPOOL) || ObjType.getFlag(MAGICFIELD)){ + Delete(Obj, -1); + }else if(MoveUnmovable || !ObjType.getFlag(UNMOVE)){ + Move(0, Obj, Dest, -1, true, NONE); + } + }catch(RESULT r){ + if(r != DESTROYED){ + int DestX, DestY, DestZ; + GetObjectCoordinates(Dest, &DestX, &DestY, &DestZ); + error("MoveAllObjects: Exception %d; Objekt %d, Zielkoordinate [%d,%d,%d].\n", + r, ObjType.TypeID, DestX, DestY, DestZ); + } + } + } +} + +void DeleteAllObjects(Object Obj, Object Exclude, bool DeleteUnmovable){ + if(Obj == NONE){ + return; + } + + // TODO(fusion): Same as `MoveAllObjects`. + DeleteAllObjects(Obj.getNextObject(), Exclude, DeleteUnmovable); + + if(Obj != Exclude){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer()){ + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + error("DeleteAllObjects: An Position [%d,%d,%d] soll eine Kreatur gelöscht werden.\n", + ObjX, ObjY, ObjZ); + return; + } + + if(!DeleteUnmovable && ObjType.getFlag(UNMOVE) + && !ObjType.getFlag(LIQUIDPOOL) + && !ObjType.getFlag(MAGICFIELD)){ + return; + } + + try{ + Delete(Obj, -1); + }catch(RESULT r){ + error("DeleteAllObjects: Exception %d.\n", r); + } + } +} + +void ClearField(Object Obj, Object Exclude){ + // IMPORTANT(fusion): This function seems to be used when items transform + // into `UNPASS` versions of themselves, like doors, which is why we skip + // the actual object when calling `MoveAllObjects` at the end. + // The order we scan available fields may also be important which is why + // I've kept the same ordering used by the original function. + + if(!Obj.exists()){ + error("ClearField: Objekt existiert nicht.\n"); + return; + } + + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + + bool DestFound = false; + int DestX, DestY, DestZ; + int OffsetX[4] = { 1, 0, -1, 0}; + int OffsetY[4] = { 0, 1, 0, -1}; + + // NOTE(fusion): First look for a field that's not blocked. + for(int i = 0; i < 4; i += 1){ + DestX = ObjX + OffsetX[i]; + DestY = ObjY + OffsetY[i]; + DestZ = ObjZ; + if(CoordinateFlag(DestX, DestY, DestZ, BANK) + && !CoordinateFlag(DestX, DestY, DestZ, UNPASS)){ + DestFound = true; + break; + } + } + + // NOTE(fusion): Then look for a field where jumping is possible. + if(!DestFound){ + for(int i = 0; i < 4; i += 1){ + DestX = ObjX + OffsetX[i]; + DestY = ObjY + OffsetY[i]; + DestZ = ObjZ; + if(JumpPossible(DestX, DestY, DestZ, false)){ + DestFound = true; + break; + } + } + } + + if(DestFound){ + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveAllObjects(Obj.getNextObject(), Dest, Exclude, true); + } +} + +void LoadDepotBox(uint32 CreatureID, int Nr, Object Con){ + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("moveuse::LoadDepotBox: Kreatur nicht gefunden.\n"); + return; + } + + if(!Con.exists()){ + error("moveuse::LoadDepotBox: Übergebener Container existiert nicht.\n"); + return; + } + + if(!Con.getObjectType().getFlag(CONTAINER)){ + error("moveuse::LoadDepotBox: Übergebenes Objekt ist kein Container.\n"); + return; + } + + // NOTE(fusion): Holy fuck. Objects are actually loaded into the depot box. + LoadDepot(Player->PlayerData, Nr, Con); + + int DepotObjects = CountObjects(Con) - 1; + int DepotCapacity = GetDepotSize(Nr, CheckRight(Player->ID, PREMIUM_ACCOUNT)); + int DepotSpace = DepotCapacity - DepotObjects; + Player->Depot = Con; + Player->DepotNr = Nr; + Player->DepotSpace = DepotSpace; + + print(3, "Depot von %s hat %d freie Plätze.\n", Player->Name, DepotSpace); + SendMessage(Player->Connection, TALK_STATUS_MESSAGE, + "Your depot contains %d item%s.", + DepotObjects, (DepotObjects != 1 ? "s" : "")); + + if(DepotSpace <= 0){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "Your depot is full. Remove surplus items before storing new ones."); + } +} + +void SaveDepotBox(uint32 CreatureID, int Nr, Object Con){ + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("moveuse::SaveDepotBox: Kreatur nicht gefunden.\n"); + return; + } + + if(!Con.exists()){ + error("moveuse::SaveDepotBox: Übergebener Container existiert nicht.\n"); + return; + } + + if(!Con.getObjectType().getFlag(CONTAINER)){ + error("moveuse::SaveDepotBox: Übergebenes Objekt ist kein Container.\n"); + return; + } + + int DepotObjects = CountObjects(Con) - 1; + Log("game", "Speichere Depot %d von %s ... Depotgröße: %d.\n", + Nr, Player->Name, DepotObjects); + print(3, "Depot von %s: berechnete freie Plätze %d, tatsächliche Objekte %d.\n", + Player->Name, Player->DepotSpace, DepotObjects); + + SaveDepot(Player->PlayerData, Nr, Con); + Player->Depot = NONE; + + Object Obj = GetFirstContainerObject(Con); + while(Obj != NONE){ + Object Next = Obj.getNextObject(); + Delete(Obj, -1); + Obj = Next; + } +} + +void SendMail(Object Obj){ + if(!Obj.exists()){ + error("SendMail: Übergebenes Objekt existiert nicht.\n"); + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType != GetSpecialObject(PARCEL_NEW) + && ObjType != GetSpecialObject(LETTER_NEW)){ + return; + } + + print(3,"Versende Post...\n"); + + uint32 TextAttr = 0; + if(ObjType == GetSpecialObject(LETTER_NEW)){ + TextAttr = Obj.getAttribute(TEXTSTRING); + }else{ + ObjectType LabelType = GetSpecialObject(PARCEL_LABEL); + Object Label = GetFirstContainerObject(Obj); + while(Label != NONE){ + if(Label.getObjectType() == LabelType){ + break; + } + Label = Label.getNextObject(); + } + + if(Label == NONE){ + return; + } + + TextAttr = Label.getAttribute(TEXTSTRING); + } + + const char *Text = GetDynamicString(TextAttr); + if(Text == NULL || Text[0] == 0){ + return; + } + + + // TODO(fusion): Have some helper functions to read lines? + char Addressee[256]; + char Town[256]; + { + int ReadPos = 0; + int WritePos = 0; + while(Text[ReadPos] != 0 && Text[ReadPos] != '\n'){ + if(WritePos < (int)(sizeof(Addressee) - 1)){ + Addressee[WritePos] = Text[ReadPos]; + WritePos += 1; + } + ReadPos += 1; + } + Addressee[WritePos] = 0; + + WritePos = 0; + while(Text[ReadPos] != 0 && Text[ReadPos] != '\n'){ + if(WritePos < (int)(sizeof(Town) - 1)){ + Town[WritePos] = Text[ReadPos]; + WritePos += 1; + } + ReadPos += 1; + } + Town[WritePos] = 0; + + Trim(Addressee); + Trim(Town); + } + + if(Addressee[0] == 0 || Town[0] == 0){ + return; + } + + // TODO(fusion): This constant for the size of creature names showing up again. + // Maybe `MAX_NAME_LENGTH`? + if(strlen(Addressee) >= 30){ + return; + } + + Log("game", "Post an %s in %s.\n", Addressee, Town); + int DepotNr = GetDepotNumber(Town); + if(DepotNr == -1){ + return; + } + + TPlayer *Player; + bool PlayerOnline; + uint32 CharacterID; + if(IdentifyPlayer(Addressee, true, true, &Player) == 0){ + PlayerOnline = true; + CharacterID = Player->ID; + }else{ + PlayerOnline = false; + CharacterID = GetCharacterID(Addressee); + if(CharacterID == 0){ + return; + } + } + + if(PlayerOnline && Player->Depot != NONE && Player->DepotNr == DepotNr){ + print(3, "Adressat ist eingeloggt und hat Depot offen.\n"); + try{ + Move(0, Obj, Player->Depot, -1, true, NONE); + if(ObjType == GetSpecialObject(LETTER_NEW)){ + Change(Obj, GetSpecialObject(LETTER_STAMPED), 0); + }else{ + Change(Obj, GetSpecialObject(PARCEL_STAMPED), 0); + } + Log("game", "Post an %s in %s versandt.\n", Addressee, Town); + Player->DepotSpace -= CountObjects(Obj); + print(3, "Depot von %s hat jetzt %d freie Plätze.\n", Player->Name, Player->DepotSpace); + SendMessage(Player->Connection, TALK_INFO_MESSAGE, "New mail has arrived."); + print(3, "Post erfolgreich versandt.\n"); + }catch(RESULT r){ + if(r != CONTAINERFULL){ + error("SendMail (Depot offen): Exception %d.\n", r); + } + + print(3, "Exception %d beim Postversand.\n", r); + } + }else{ + print(3, "Adressat ist nicht eingeloggt oder hat Depot geschlossen.\n"); + + // TODO(fusion): The scope of this try block was unclear but I suppose + // this is correct due to how `Change` is also inside the try block in + // the try block above, when the player is online. + try{ + if(ObjType == GetSpecialObject(LETTER_NEW)){ + Change(Obj, GetSpecialObject(LETTER_STAMPED), 0); + }else{ + Change(Obj, GetSpecialObject(PARCEL_STAMPED), 0); + } + + TDynamicWriteBuffer WriteBuffer(1024); + SaveObjects(Obj, &WriteBuffer, true); + Delete(Obj, -1); + + TDelayedMail *Mail = DelayedMail.at(DelayedMails); + Mail->CharacterID = CharacterID; + Mail->DepotNumber = DepotNr; + Mail->PacketSize = WriteBuffer.Position; + // TODO(fusion): Check if `WriteBuffer.Position` is not zero? + Mail->Packet = new uint8[WriteBuffer.Position]; + memcpy(Mail->Packet, WriteBuffer.Data, WriteBuffer.Position); + DelayedMails += 1; + + Log("game", "Post an %s in %s zurückgestellt.\n", Addressee, Town); + print(3, "Post zurückgestellt.\n"); + if(PlayerOnline){ + SendMails(Player->PlayerData); + }else{ + LoadCharacterOrder(CharacterID); + } + }catch(RESULT r){ + error("SendMail: Kann Paket nicht löschen (%d).\n", r); + }catch(const char *str){ + error("SendMail: Kann Paket nicht schreiben (%s).\n", str); + } + } +} + +void SendMails(TPlayerData *PlayerData){ + if(PlayerData == NULL){ + error("SendMails: PlayerData ist NULL.\n"); + return; + } + + if(PlayerData->CharacterID == 0){ + error("SendMails: Slot ist nicht belegt.\n"); + return; + } + + if(PlayerData->Locked != getpid()){ + error("SendMails: Slot ist nicht vom GameThread gesperrt.\n"); + return; + } + + for(int i = 0; i < DelayedMails; i += 1){ + TDelayedMail *Mail = DelayedMail.at(i); + if(Mail->CharacterID != PlayerData->CharacterID){ + continue; + } + + int DepotNr = Mail->DepotNumber; + if(DepotNr < 0 || DepotNr >= 9){ // MAX_DEPOT ? + error("SendMails: Ungültige Depotnummer %d.\n", DepotNr); + DepotNr = 0; + } + + int NewDepotSize = 0; + uint8 *NewDepot = NULL; + if(PlayerData->Depot[DepotNr] != NULL){ + NewDepotSize = PlayerData->DepotSize[DepotNr] + Mail->PacketSize; + NewDepot = new uint8[NewDepotSize]; + memcpy(&NewDepot[0], Mail->Packet, Mail->PacketSize); + memcpy(&NewDepot[Mail->PacketSize], + PlayerData->Depot[DepotNr], + PlayerData->DepotSize[DepotNr]); + delete[] PlayerData->Depot[DepotNr]; + }else{ + NewDepotSize = Mail->PacketSize + 5; + NewDepot = new uint8[NewDepotSize]; + memcpy(&NewDepot[0], Mail->Packet, Mail->PacketSize); + TWriteBuffer WriteBuffer(&NewDepot[Mail->PacketSize], 5); + WriteBuffer.writeWord((uint16)GetSpecialObject(DEPOT_CHEST).TypeID); + WriteBuffer.writeByte(0xFF); + WriteBuffer.writeWord(0xFFFF); + } + + PlayerData->Depot[DepotNr] = NewDepot; + PlayerData->DepotSize[DepotNr] = NewDepotSize; + PlayerData->Dirty = true; + + Log("game", "Post an %s zugestellt.\n", PlayerData->Name); + + if(Mail->Packet != NULL){ + delete[] Mail->Packet; + } + + // NOTE(fusion): A little swap and pop action. + DelayedMails -= 1; + *DelayedMail.at(i) = *DelayedMail.at(DelayedMails); + *DelayedMail.at(DelayedMails) = TDelayedMail{}; + + // NOTE(fusion): Check current index again after removal. + i -= 1; + } +} + +void TextEffect(const char *Text, int x, int y, int z, int Radius){ + if(Text == NULL){ + error("TextEffect: Text existiert nicht.\n"); + return; + } + + TFindCreatures Search(Radius, Radius, x, y, FIND_PLAYERS); + while(true){ + uint32 CharacterID = Search.getNext(); + if(CharacterID == 0){ + break; + } + + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL || Player->Connection == NULL){ + continue; + } + + int PlayerZ = Player->posz; + if(PlayerZ == z || Radius > 30 || (Radius > 7 && PlayerZ <= 7 && z <= 7)){ + SendTalk(Player->Connection, 0, "", TALK_ANIMAL_LOW, x, y, z, Text); + } + } +} + +void ExecuteAction(MoveUseEventType EventType, TMoveUseAction *Action, + Object User, Object Obj1, Object Obj2, Object *Temp){ + try{ + switch(Action->Action){ + case MOVEUSE_ACTION_CREATEONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Action->Parameters[1]; + int Value = Action->Parameters[2]; + Object MapCon = GetMapContainer(CoordX, CoordY, CoordZ); + *Temp = CreateObject(MapCon, Type, Value); + break; + } + + case MOVEUSE_ACTION_CREATE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + ObjectType Type = Action->Parameters[1]; + int Value = Action->Parameters[2]; + *Temp = CreateObject(Obj.getContainer(), Type, Value); + break; + } + + case MOVEUSE_ACTION_MONSTERONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + int Race = Action->Parameters[1]; + CreateMonster(Race, CoordX, CoordY, CoordZ, 0, 0, true); + break; + } + + case MOVEUSE_ACTION_MONSTER:{ + int ObjX, ObjY, ObjZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + int Race = Action->Parameters[1]; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + CreateMonster(Race, ObjX, ObjY, ObjZ, 0, 0, true); + break; + } + + case MOVEUSE_ACTION_EFFECTONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + int Effect = Action->Parameters[1]; + GraphicalEffect(CoordX, CoordY, CoordZ, Effect); + break; + } + + case MOVEUSE_ACTION_EFFECT:{ + int ObjX, ObjY, ObjZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + int Effect = Action->Parameters[1]; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + GraphicalEffect(ObjX, ObjY, ObjZ, Effect); + break; + } + + case MOVEUSE_ACTION_TEXTONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + const char *Text = GetDynamicString(Action->Parameters[1]); + int Radius = Action->Parameters[2]; + TextEffect(Text, CoordX, CoordY, CoordZ, Radius); + break; + } + + case MOVEUSE_ACTION_TEXT:{ + int ObjX, ObjY, ObjZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + const char *Text = GetDynamicString(Action->Parameters[1]); + int Radius = Action->Parameters[2]; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + TextEffect(Text, ObjX, ObjY, ObjZ, Radius); + break; + } + + case MOVEUSE_ACTION_CHANGEONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType OldType = Action->Parameters[1]; + ObjectType NewType = Action->Parameters[2]; + int NewValue = Action->Parameters[3]; + *Temp = GetFirstSpecObject(CoordX, CoordY, CoordZ, OldType); + if(*Temp != NONE){ + ChangeObject(*Temp, NewType, NewValue); + }else{ + error("ExecuteAction (CHANGEONMAP): Kein Objekt %d auf [%d,%d,%d].\n", + OldType.TypeID, CoordX, CoordY, CoordZ); + } + break; + } + + case MOVEUSE_ACTION_CHANGE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + ObjectType NewType = Action->Parameters[1]; + int NewValue = Action->Parameters[2]; + ChangeObject(Obj, NewType, NewValue); + break; + } + + case MOVEUSE_ACTION_CHANGEREL:{ + int ObjX, ObjY, ObjZ, RelX, RelY, RelZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackRelativeCoordinate(Action->Parameters[1], &RelX, &RelY, &RelZ); + ObjectType OldType = Action->Parameters[2]; + ObjectType NewType = Action->Parameters[3]; + int NewValue = Action->Parameters[4]; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + *Temp = GetFirstSpecObject((ObjX + RelX), (ObjY + RelY), (ObjZ + RelZ), OldType); + if(*Temp != NONE){ + ChangeObject(*Temp, NewType, NewValue); + }else{ + error("ExecuteAction (CHANGEREL): Kein Objekt %d auf [%d,%d,%d].\n", + OldType.TypeID, (ObjX + RelX), (ObjY + RelY), (ObjZ + RelZ)); + } + break; + } + + case MOVEUSE_ACTION_SETATTRIBUTE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + INSTANCEATTRIBUTE Attribute = (INSTANCEATTRIBUTE)Action->Parameters[1]; + int Value = Action->Parameters[2]; + Change(Obj, Attribute, Value); + break; + } + + case MOVEUSE_ACTION_CHANGEATTRIBUTE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + INSTANCEATTRIBUTE Attribute = (INSTANCEATTRIBUTE)Action->Parameters[1]; + int Amount = Action->Parameters[2]; + // TODO(fusion): This is weird. + int OldValue = (int)Obj.getAttribute(Attribute); + int NewValue = OldValue + Amount; + if(NewValue <= 0){ + if(OldValue == 0){ + NewValue = 0; + }else{ + NewValue = 1; + } + } + Change(Obj, Attribute, NewValue); + break; + } + + case MOVEUSE_ACTION_SETQUESTVALUE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + int QuestNr = Action->Parameters[1]; + int QuestValue = Action->Parameters[2]; + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer()){ + TCreature *Creature = GetCreature(Obj); + if(Creature != NULL && Creature->Type == PLAYER){ + ((TPlayer*)Creature)->SetQuestValue(QuestNr, QuestValue); + }else{ + error("ExecuteAction (SETQUESTVALUE): Kreatur existiert nicht oder ist kein Spieler.\n"); + } + }else{ + error("ExecuteAction (SETQUESTVALUE): Objekt ist keine Kreatur, sondern Typ %d.\n", ObjType.TypeID); + } + break; + } + + case MOVEUSE_ACTION_DAMAGE:{ + Object AttackerObj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + Object VictimObj = GetEventObject(Action->Parameters[1], User, Obj1, Obj2, *Temp); + int DamageType = Action->Parameters[2]; + int Damage = Action->Parameters[3]; + + TCreature *Attacker = NULL; + if(AttackerObj != NONE){ + ObjectType AttackerType = AttackerObj.getObjectType(); + if(AttackerType.isCreatureContainer()){ + Attacker = GetCreature(AttackerObj); + }else if(AttackerType.getFlag(MAGICFIELD) + && AttackerObj.getAttribute(RESPONSIBLE) != 0){ + int TotalExpireTime = (int)AttackerType.getAttribute(TOTALEXPIRETIME); + int CurExpireTime = (int)CronInfo(AttackerObj, false); + if((TotalExpireTime - CurExpireTime) < 5){ + Attacker = GetCreature(AttackerObj.getAttribute(RESPONSIBLE)); + } + } + } + + ObjectType VictimType = VictimObj.getObjectType(); + if(VictimType.isCreatureContainer()){ + TCreature *Victim = GetCreature(VictimObj); + if(Victim != NULL){ + Victim->Damage(Attacker, Damage, DamageType); + }else{ + error("ExecuteAction (DAMAGE): Kreatur existiert nicht.\n"); + } + }else{ + error("ExecuteAction (DAMAGE): Objekt ist keine Kreatur, sondern Typ %d.\n", VictimType.TypeID); + } + break; + } + + case MOVEUSE_ACTION_SETSTART:{ + int StartX, StartY, StartZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackAbsoluteCoordinate(Action->Parameters[1], &StartX, &StartY, &StartZ); + + if(!Obj.getObjectType().isCreatureContainer()){ + throw ERROR; + } + + TCreature *Creature = GetCreature(Obj); + if(Creature == NULL || Creature->Type != PLAYER){ + throw ERROR; + } + + Creature->startx = StartX; + Creature->starty = StartY; + Creature->startz = StartZ; + ((TPlayer*)Creature)->SaveData(); + break; + } + + case MOVEUSE_ACTION_WRITENAME:{ + Object WriterObj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + const char *Format = GetDynamicString(Action->Parameters[1]); + Object TargetObj = GetEventObject(Action->Parameters[2], User, Obj1, Obj2, *Temp); + + if(WriterObj == NONE || !WriterObj.getObjectType().isCreatureContainer() + || TargetObj == NONE || !TargetObj.getObjectType().getFlag(TEXT)){ + throw ERROR; + } + + TCreature *Writer = GetCreature(WriterObj); + if(Writer == NULL){ + throw ERROR; + } + + // TODO(fusion): Some helper function to format text? + char Text[256]; + { + int ReadPos = 0; + int WritePos = 0; + int TextSize = (int)sizeof(Text); + while(Format[ReadPos] != 0){ + if(Format[ReadPos] == '%' && Format[ReadPos + 1] == 'N'){ + // NOTE(fusion): Make sure we don't overflow the buffer. + int NameLen = (int)strlen(Writer->Name); + if(NameLen > 0){ + if((WritePos + NameLen) > TextSize){ + NameLen = TextSize - WritePos; + } + + if(NameLen > 0){ + memcpy(&Text[WritePos], Writer->Name, NameLen); + WritePos += NameLen; + } + } + + ReadPos += 2; + }else{ + // NOTE(fusion): Make sure we don't overflow the buffer. + if(WritePos < TextSize){ + Text[WritePos] = Format[ReadPos]; + WritePos += 1; + } + + ReadPos += 1; + } + } + + if(WritePos >= TextSize){ + throw ERROR; + } + } + + DeleteDynamicString(TargetObj.getAttribute(TEXTSTRING)); + DeleteDynamicString(TargetObj.getAttribute(EDITOR)); + Change(TargetObj, TEXTSTRING, AddDynamicString(Text)); + Change(TargetObj, EDITOR, 0); + break; + } + + case MOVEUSE_ACTION_WRITETEXT:{ + const char *Text = GetDynamicString(Action->Parameters[0]); + Object Obj = GetEventObject(Action->Parameters[1], User, Obj1, Obj2, *Temp); + + if(Obj == NONE || !Obj.getObjectType().getFlag(TEXT)){ + throw ERROR; + } + + DeleteDynamicString(Obj.getAttribute(TEXTSTRING)); + DeleteDynamicString(Obj.getAttribute(EDITOR)); + Change(Obj, TEXTSTRING, AddDynamicString(Text)); + Change(Obj, EDITOR, 0); + break; + } + + case MOVEUSE_ACTION_LOGOUT:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + + if(Obj == NONE || !Obj.getObjectType().isCreatureContainer()){ + throw ERROR; + } + + TCreature *Creature = GetCreature(Obj); + if(Creature == NULL){ + throw ERROR; + } + + Creature->StartLogout(true, true); + break; + } + + case MOVEUSE_ACTION_MOVEALLONMAP:{ + int OrigX, OrigY, OrigZ, DestX, DestY, DestZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &OrigX, &OrigY, &OrigZ); + UnpackAbsoluteCoordinate(Action->Parameters[1], &DestX, &DestY, &DestZ); + Object First = GetFirstObject(OrigX, OrigY, OrigZ); + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveAllObjects(First, Dest, NONE, false); + break; + } + + case MOVEUSE_ACTION_MOVEALL:{ + int DestX, DestY, DestZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackAbsoluteCoordinate(Action->Parameters[1], &DestX, &DestY, &DestZ); + Object First = GetFirstContainerObject(Obj.getContainer()); + Object Dest = GetMapContainer(DestX, DestY, DestZ); + // TODO(fusion): Why do we set the `Exclude` parameter to `First`? + // Maybe we just don't want to check if it is `NONE` can call + // `getNextObject()` like MOVETOPONMAP? + MoveAllObjects(First, Dest, First, false); + break; + } + + case MOVEUSE_ACTION_MOVEALLREL:{ + int ObjX, ObjY, ObjZ, RelX, RelY, RelZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackRelativeCoordinate(Action->Parameters[1], &RelX, &RelY, &RelZ); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Object First = GetFirstContainerObject(Obj.getContainer()); + Object Dest = GetMapContainer((ObjX + RelX), (ObjY + RelY), (ObjZ + RelZ)); + // TODO(fusion): Same as above? + MoveAllObjects(First, Dest, First, false); + break; + } + + case MOVEUSE_ACTION_MOVETOPONMAP:{ + int OrigX, OrigY, OrigZ, DestX, DestY, DestZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &OrigX, &OrigY, &OrigZ); + ObjectType Type = Action->Parameters[1]; + UnpackAbsoluteCoordinate(Action->Parameters[2], &DestX, &DestY, &DestZ); + Object Obj = GetFirstSpecObject(OrigX, OrigY, OrigZ, Type); + if(Obj != NONE){ + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveAllObjects(Obj.getNextObject(), Dest, NONE, true); + }else{ + error("ExecuteAction (MOVETOPONMAP): Kein Objekt %d auf [%d,%d,%d].\n", + Type.TypeID, OrigX, OrigY, OrigZ); + } + break; + } + + case MOVEUSE_ACTION_MOVETOP:{ + int DestX, DestY, DestZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackAbsoluteCoordinate(Action->Parameters[1], &DestX, &DestY, &DestZ); + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveAllObjects(Obj.getNextObject(), Dest, NONE, true); + break; + } + + case MOVEUSE_ACTION_MOVETOPREL:{ + int ObjX, ObjY, ObjZ, RelX, RelY, RelZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackRelativeCoordinate(Action->Parameters[1], &RelX, &RelY, &RelZ); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Object Dest = GetMapContainer((ObjX + RelX), (ObjY + RelY), (ObjZ + RelZ)); + MoveAllObjects(Obj.getNextObject(), Dest, NONE, true); + break; + } + + case MOVEUSE_ACTION_MOVE:{ + int DestX, DestY, DestZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackAbsoluteCoordinate(Action->Parameters[1], &DestX, &DestY, &DestZ); + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveOneObject(Obj, Dest); + break; + } + + case MOVEUSE_ACTION_MOVEREL:{ + int ObjX, ObjY, ObjZ, RelX, RelY, RelZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackRelativeCoordinate(Action->Parameters[1], &RelX, &RelY, &RelZ); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Object Dest = GetMapContainer((ObjX + RelX), (ObjY + RelY), (ObjZ + RelZ)); + MoveOneObject(Obj, Dest); + break; + } + + case MOVEUSE_ACTION_RETRIEVE:{ + int ObjX, ObjY, ObjZ, OrigRelX, OrigRelY, OrigRelZ, DestRelX, DestRelY, DestRelZ; + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + UnpackRelativeCoordinate(Action->Parameters[1], &OrigRelX, &OrigRelY, &OrigRelZ); + UnpackRelativeCoordinate(Action->Parameters[2], &DestRelX, &DestRelY, &DestRelZ); + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + Object Top = GetTopObject((ObjX + OrigRelX), (ObjY + OrigRelY), (ObjZ + OrigRelZ), false); + if(Top != NONE && !Top.getObjectType().getFlag(UNMOVE)){ + Object Dest = GetMapContainer((ObjX + DestRelX), (ObjY + DestRelY), (ObjZ + DestRelZ)); + MoveOneObject(Obj, Dest); + } + break; + } + + case MOVEUSE_ACTION_DELETEALLONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + Object First = GetFirstObject(CoordX, CoordY, CoordZ); + // TODO(fusion): Same as `MOVEALL`. + DeleteAllObjects(First, First, false); + break; + } + + case MOVEUSE_ACTION_DELETETOPONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Action->Parameters[1]; + Object First = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + // TODO(fusion): Sometimes we throw, sometimes we print an error, + // sometimes we ignore it, what a mess. + if(First == NONE){ + throw ERROR; + } + DeleteAllObjects(First, First, true); + break; + } + + case MOVEUSE_ACTION_DELETEONMAP:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Action->Parameters[1]; + Object Obj = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + if(Obj != NONE){ + bool IsUseEvent = (EventType == MOVEUSE_EVENT_USE + || EventType == MOVEUSE_EVENT_MULTIUSE); + Delete(Obj, (IsUseEvent ? 1 : -1)); + }else{ + error("ExecuteAction (DELETEONMAP): Kein Objekt %d auf [%d,%d,%d].\n", + Type.TypeID, CoordX, CoordY, CoordZ); + } + break; + } + + case MOVEUSE_ACTION_DELETE:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + if(Obj == NONE){ + throw ERROR; + } + bool IsUseEvent = (EventType == MOVEUSE_EVENT_USE + || EventType == MOVEUSE_EVENT_MULTIUSE); + Delete(Obj, (IsUseEvent ? 1 : -1)); + break; + } + + case MOVEUSE_ACTION_DELETEININVENTORY:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + ObjectType Type = Action->Parameters[1]; + int Value = Action->Parameters[2]; + if(Obj.getObjectType().isCreatureContainer()){ + DeleteAtCreature(Obj.getCreatureID(), Type, 1, Value); + }else{ + throw ERROR; + } + break; + } + + case MOVEUSE_ACTION_DESCRIPTION:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + Object Cr = GetEventObject(Action->Parameters[1], User, Obj1, Obj2, *Temp); + if(Cr.getObjectType().isCreatureContainer()){ + TCreature *Creature = GetCreature(Cr); + if(Creature != NULL && Creature->Type == PLAYER){ + SendMessage(Creature->Connection, TALK_INFO_MESSAGE, + "%s.", GetInfo(Obj)); + } + } + break; + } + + case MOVEUSE_ACTION_LOADDEPOT:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Action->Parameters[1]; + Object Cr = GetEventObject(Action->Parameters[2], User, Obj1, Obj2, *Temp); + int DepotNr = Action->Parameters[3]; + + if(!Cr.getObjectType().isCreatureContainer()){ + throw ERROR; + } + + Object Depot = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + if(Depot == NONE){ + throw ERROR; + } + + LoadDepotBox(Cr.getCreatureID(), DepotNr, Depot); + break; + } + + case MOVEUSE_ACTION_SAVEDEPOT:{ + int CoordX, CoordY, CoordZ; + UnpackAbsoluteCoordinate(Action->Parameters[0], &CoordX, &CoordY, &CoordZ); + ObjectType Type = Action->Parameters[1]; + Object Cr = GetEventObject(Action->Parameters[2], User, Obj1, Obj2, *Temp); + int DepotNr = Action->Parameters[3]; + + if(!Cr.getObjectType().isCreatureContainer()){ + throw ERROR; + } + + Object Depot = GetFirstSpecObject(CoordX, CoordY, CoordZ, Type); + if(Depot == NONE){ + throw ERROR; + } + + SaveDepotBox(Cr.getCreatureID(), DepotNr, Depot); + break; + } + + case MOVEUSE_ACTION_SENDMAIL:{ + Object Obj = GetEventObject(Action->Parameters[0], User, Obj1, Obj2, *Temp); + SendMail(Obj); + break; + } + + case MOVEUSE_ACTION_NOP:{ + // no-op + break; + } + + default:{ + error("ExecuteAction: Unbekannte Aktion %d.\n", Action->Action); + break; + } + } + }catch(RESULT r){ + error("ExecuteAction: Exception %d (Aktion %d).\n", r, Action->Action); + } +} + +bool HandleEvent(MoveUseEventType EventType, Object User, Object Obj1, Object Obj2){ + static int RecursionDepth = 0; + + if(RecursionDepth > 10){ + error("HandleEvent: Endlosschleife im Move/Use-System vermutet.\n"); + return false; + } + + bool Result = false; + RecursionDepth += 1; + TMoveUseDatabase *DB = &MoveUseDatabases[EventType]; + for(int RuleNr = 1; RuleNr <= DB->NumberOfRules; RuleNr += 1){ + bool Execute = true; + Object Temp = NONE; + TMoveUseRule *Rule = DB->Rules.at(RuleNr); + for(int ConditionNr = Rule->FirstCondition; + ConditionNr <= Rule->LastCondition; + ConditionNr += 1){ + TMoveUseCondition *Condition = MoveUseConditions.at(ConditionNr); + if(!CheckCondition(EventType, Condition, User, Obj1, Obj2, &Temp)){ + Execute = false; + break; + } + } + + if(Execute){ + for(int ActionNr = Rule->FirstAction; + ActionNr <= Rule->LastAction; + ActionNr += 1){ + TMoveUseAction *Action = MoveUseActions.at(ActionNr); + ExecuteAction(EventType, Action, User, Obj2, Obj2, &Temp); + } + Result = true; + } + } + RecursionDepth -= 1; + return Result; +} + +// Event Dispatching +// ============================================================================= +void UseContainer(uint32 CreatureID, Object Con, int NextContainerNr){ + if(!Con.exists()){ + error("UseContainer: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType ConType = Con.getObjectType(); + if(!ConType.getFlag(CONTAINER)){ + error("UseContainer: Übergebenes Objekt ist kein Container.\n"); + throw ERROR; + } + + if(NextContainerNr < 0 || NextContainerNr >= NARRAY(TPlayer::OpenContainer)){ + error("UseContainer: Ungültige Fensternummer %d.\n", NextContainerNr); + throw ERROR; + } + + if(ConType.isCreatureContainer()){ + throw NOTUSABLE; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseContainer: Spieler %d existiert nicht.\n", CreatureID); + throw ERROR; + } + + bool ContainerClosed = false; + for(int ContainerNr = 0; + ContainerNr < NARRAY(TPlayer::OpenContainer); + ContainerNr += 1){ + if(Player->GetOpenContainer(ContainerNr) == Con){ + Player->SetOpenContainer(ContainerNr, NONE); + SendCloseContainer(Player->Connection, ContainerNr); + ContainerClosed = true; + break; + } + } + + if(!ContainerClosed){ + Player->SetOpenContainer(NextContainerNr, Con); + SendContainer(Player->Connection, NextContainerNr); + } +} + +void UseChest(uint32 CreatureID, Object Chest){ + if(!Chest.exists()){ + error("UseChest: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType ChestType = Chest.getObjectType(); + if(!ChestType.getFlag(CHEST)){ + error("UseChest: Übergebenes Objekt ist keine Schatztruhe.\n"); + throw ERROR; + } + + int ChestX, ChestY, ChestZ; + GetObjectCoordinates(Chest, &ChestX, &ChestY, &ChestZ); + + int QuestNr = (int)Chest.getAttribute(CHESTQUESTNUMBER); + if(QuestNr < 0 || QuestNr >= NARRAY(TPlayer::QuestValues)){ + error("UseChest: Ungültige Nummer %d auf Schatztruhe an Position [%d,%d,%d].\n", + QuestNr, ChestX, ChestY, ChestZ); + throw ERROR; + } + + if(CountObjectsInContainer(Chest) != 1){ + error("UseChest: Schatztruhe auf Position [%d,%d,%d] enthält nicht genau ein Objekt.\n", + ChestX, ChestY, ChestZ); + throw ERROR; + } + + Object Treasure = GetFirstContainerObject(Chest); + ObjectType TreasureType = Treasure.getObjectType(); + if(TreasureType.getFlag(UNMOVE) || !TreasureType.getFlag(TAKE)){ + error("UseChest: Schatz auf Position [%d,%d,%d] ist nicht nehmbar.\n", + ChestX, ChestY, ChestZ); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseChest: Spieler %u existiert nicht.\n", CreatureID); + throw ERROR; + } + + if(Player->GetQuestValue(QuestNr) != 0){ + print(3, "Schatztruhe ist schon bekannt.\n"); + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "The %s is empty.", ChestType.getName(-1)); + return; + } + + if(!CheckRight(CreatureID, UNLIMITED_CAPACITY)){ + int TreasureWeight = GetCompleteWeight(Treasure); + int InventoryWeight = GetInventoryWeight(CreatureID); + int MaxWeight = Player->Skills[SKILL_CARRY_STRENGTH]->Get() * 100; + if((InventoryWeight + TreasureWeight) > MaxWeight + || CheckRight(CreatureID, ZERO_CAPACITY)){ + bool Multiple = TreasureType.getFlag(CUMULATIVE) + && Treasure.getAttribute(AMOUNT) > 1; + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "You have found %s. Weighing %d.%02d oz %s too heavy.", + GetName(Treasure), (TreasureWeight / 100), (TreasureWeight % 100), + (Multiple ? "they are" : "it is")); + return; + } + } + + // NOTE(fusion): Copy treasure object and attempt to move into the player's + // inventory. The original version was somewhat confusing but this should + // achieve the same end result. + Treasure = Copy(Chest, Treasure); + bool CheckContainers = TreasureType.getFlag(MOVEMENTEVENT); + bool TreasureMoved = false; + for(int i = 0; i < 2 && !TreasureMoved; i += 1){ + for(int Position = INVENTORY_FIRST; + Position <= INVENTORY_LAST && !TreasureMoved; + Position += 1){ + try{ + Object BodyObj = GetBodyObject(CreatureID, Position); + if(CheckContainers){ + if(BodyObj != NONE && BodyObj.getObjectType().getFlag(CONTAINER)){ + Move(CreatureID, Treasure, BodyObj, -1, true, NONE); + TreasureMoved = true; + } + }else{ + if(BodyObj == NONE){ + Object BodyCon = GetBodyContainer(CreatureID, Position); + Move(CreatureID, Treasure, BodyCon, -1, true, NONE); + TreasureMoved = true; + } + } + }catch(RESULT r){ + // no-op + } + } + CheckContainers = !CheckContainers; + } + + if(!TreasureMoved){ + bool Multiple = TreasureType.getFlag(CUMULATIVE) + && Treasure.getAttribute(AMOUNT) > 1; + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "You have found %s, but you have no room to take %s.\n", + GetName(Treasure), (Multiple ? "them" : "it")); + Delete(Treasure, -1); + return; + } + + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "You have found %s.\n", GetName(Treasure)); + Player->SetQuestValue(QuestNr, 1); +} + +void UseLiquidContainer(uint32 CreatureID, Object Obj, Object Dest){ + if(!Obj.exists()){ + error("UseLiquidContainer: Übergebenes Objekt Obj existiert nicht.\n"); + throw ERROR; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!Dest.exists()){ + error("UseLiquidContainer: Übergebenes Objekt Dest existiert nicht (Obj %d).\n", + ObjType.TypeID); + throw ERROR; + } + + if(!ObjType.getFlag(LIQUIDCONTAINER)){ + error("UseLiquidContainer: Übergebenes Objekt ist kein Flüssigkeitscontainer.\n"); + throw ERROR; + } + + ObjectType DestType = Dest.getObjectType(); + int LiquidType = Obj.getAttribute(CONTAINERLIQUIDTYPE); + + // NOTE(fusion): Fill liquid container. + if(DestType.getFlag(LIQUIDSOURCE) && LiquidType == LIQUID_NONE){ + int DestLiquidType = (int)DestType.getAttribute(SOURCELIQUIDTYPE); + Change(Obj, CONTAINERLIQUIDTYPE, DestLiquidType); + return; + } + + // NOTE(fusion): Transfer liquid to another container. + if(DestType.getFlag(LIQUIDCONTAINER) && LiquidType != LIQUID_NONE + && Dest.getAttribute(CONTAINERLIQUIDTYPE) == LIQUID_NONE){ + Change(Dest, CONTAINERLIQUIDTYPE, LiquidType); + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + return; + } + + // NOTE(fusion): This is similar to the target picking logic for runes except + // we want to prioritize the user drinking the liquid, instead of otherwise + // throwing it on the ground. + if(!DestType.isCreatureContainer()){ + Object Help = GetFirstContainerObject(Dest.getContainer()); + while(Help != NONE){ + ObjectType HelpType = Help.getObjectType(); + if(HelpType.isCreatureContainer() && Help.getCreatureID() == CreatureID){ + Dest = Help; + DestType = HelpType; + break; + } + Help = Help.getNextObject(); + } + } + + // NOTE(fusion): Spill liquid. + if(!DestType.isCreatureContainer() || Dest.getCreatureID() != CreatureID){ + if(LiquidType == LIQUID_NONE){ + throw NOTUSABLE; + } + + int DestX, DestY, DestZ; + GetObjectCoordinates(Dest, &DestX, &DestY, &DestZ); + if(!CoordinateFlag(DestX, DestY, DestZ, BANK) + || CoordinateFlag(DestX, DestY, DestZ, UNLAY)){ + throw NOROOM; + } + + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + CreatePool(GetMapContainer(DestX, DestY, DestZ), + GetSpecialObject(BLOOD_POOL), LiquidType); + return; + } + + // NOTE(fusion): Drink liquid. + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseLiquidContainer: Spieler %d existiert nicht.\n", CreatureID); + throw ERROR; + } + + switch(LiquidType){ + case LIQUID_NONE:{ + // no-op + break; + } + + case LIQUID_WINE: + case LIQUID_BEER:{ + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + int DrunkLevel = Player->Skills[SKILL_DRUNKEN]->TimerValue(); + if(DrunkLevel < 5){ + Player->SetTimer(SKILL_DRUNKEN, (DrunkLevel + 1), 120, 120, -1); + } + Talk(CreatureID, TALK_SAY, NULL, "Aah...", false); + break; + } + + case LIQUID_SLIME:{ + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + Player->Damage(NULL, 200, DAMAGE_POISON_PERIODIC); + Talk(CreatureID, TALK_SAY, NULL, "Urgh!", false); + break; + } + + case LIQUID_URINE:{ + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + Talk(CreatureID, TALK_SAY, NULL, "Urgh!", false); + break; + } + + case LIQUID_MANA: + case LIQUID_LIFE:{ + DrinkPotion(CreatureID, Obj); + Talk(CreatureID, TALK_SAY, NULL, "Aaaah...", false); + break; + } + + case LIQUID_LEMONADE:{ + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + Talk(CreatureID, TALK_SAY, NULL, "Mmmh.", false); + break; + } + + default:{ + Change(Obj, CONTAINERLIQUIDTYPE, LIQUID_NONE); + Talk(CreatureID, TALK_SAY, NULL, "Gulp.", false); + break; + } + } +} + +void UseFood(uint32 CreatureID, Object Obj){ + if(!Obj.exists()){ + error("UseFood: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.getFlag(FOOD)){ + error("UseFood: Übergebenes Objekt ist kein Nahrungsmittel.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseFood: Kreatur %u existiert nicht.\n", CreatureID); + throw ERROR; + } + + int ObjFoodTime = (int)ObjType.getAttribute(NUTRITION) * 12; + int CurFoodTime = Player->Skills[SKILL_FED]->TimerValue(); + int MaxFoodTime = Player->Skills[SKILL_FED]->Max; + if((CurFoodTime + ObjFoodTime) > MaxFoodTime){ + throw FEDUP; + } + + Player->SetTimer(SKILL_FED, (CurFoodTime + ObjFoodTime), 0, 0, -1); + Delete(Obj, -1); +} + +void UseTextObject(uint32 CreatureID, Object Obj){ + if(!Obj.exists()){ + error("UseTextObject: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.getFlag(TEXT)){ + error("UseTextObject: Übergebenes Objekt ist kein Schriftstück.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseTextObject: Kreatur %u existiert nicht.\n", CreatureID); + throw ERROR; + } + + SendEditText(Player->Connection, Obj); +} + +void UseAnnouncer(uint32 CreatureID, Object Obj){ + if(!Obj.exists()){ + error("UseAnnouncer: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType ObjType = Obj.getObjectType(); + if(!ObjType.getFlag(INFORMATION)){ + error("UseAnnouncer: Übergebenes Objekt liefert keine Informationen.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseAnnouncer: Kreatur %d existiert nicht.\n", CreatureID); + throw ERROR; + } + + int Information = (int)ObjType.getAttribute(INFORMATIONTYPE); + switch(Information){ + case 1:{ // INFORMATION_DATETIME + int Year, Cycle, Day, Hour, Minute; + GetDate(&Year, &Cycle, &Day); + GetTime(&Hour, &Minute); + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "It is the %dth day of the %dth cycle in the year %d. The time is %d:%.2d.", + Day, Cycle, Year, Hour, Minute); + break; + } + + case 2:{ // INFORMATION_TIME + int Hour, Minute; + GetTime(&Hour, &Minute); + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "The time is %d:%.2d.", Hour, Minute); + break; + } + + case 3:{ // INFORMATION_BLESSINGS + int NumBlessings = 0; + char Help[256] = {}; + strcpy(Help, "Received blessings:"); + + if(Player->GetQuestValue(101) != 0){ + strcat(Help, "\nWisdom of Solitude"); + NumBlessings += 1; + } + + if(Player->GetQuestValue(102) != 0){ + strcat(Help, "\nSpark of the Phoenix"); + NumBlessings += 1; + } + + if(Player->GetQuestValue(103) != 0){ + strcat(Help, "\nFire of the Suns"); + NumBlessings += 1; + } + + if(Player->GetQuestValue(104) != 0){ + strcat(Help, "\nSpiritual Shielding"); + NumBlessings += 1; + } + + if(Player->GetQuestValue(105) != 0){ + strcat(Help, "\nEmbrace of Tibia"); + NumBlessings += 1; + } + + if(NumBlessings == 0){ + strcpy(Help, "No blessings received."); + } + + SendMessage(Player->Connection, TALK_INFO_MESSAGE, "%s", Help); + break; + } + + case 4:{ // INFORMATION_SPELLBOOK + SendEditText(Player->Connection, Obj); + break; + } + + default:{ + error("UseAnnouncer: Ungültiger Informationstyp %d.\n", Information); + break; + } + } +} + +void UseKeyDoor(uint32 CreatureID, Object Key, Object Door){ + if(!Key.exists()){ + error("UseKeyDoor: Übergebenes Objekt Key existiert nicht.\n"); + throw ERROR; + } + + if(!Door.exists()){ + error("UseKeyDoor: Übergebenes Objekt Door existiert nicht.\n"); + throw ERROR; + } + + ObjectType KeyType = Key.getObjectType(); + if(!KeyType.getFlag(KEY)){ + error("UseKeyDoor: Übergebenes Objekt ist kein Schlüssel.\n"); + throw ERROR; + } + + ObjectType DoorType = Door.getObjectType(); + if(!DoorType.getFlag(KEYDOOR)){ + throw NOTUSABLE; + } + + int KeyNumber = (int)Key.getAttribute(KEYNUMBER); + int KeyHoleNumber = (int)Door.getAttribute(KEYHOLENUMBER); + if(KeyNumber == 0 || KeyHoleNumber == 0 || KeyNumber != KeyHoleNumber){ + throw NOKEYMATCH; + } + + ObjectType KeyDoorTarget = (int)DoorType.getAttribute(KEYDOORTARGET); + if(KeyDoorTarget.isMapContainer()){ + error("UseKeyDoor: Zieltür für Tür %d nicht spezifiziert.\n", + DoorType.TypeID); + throw ERROR; + } + + if(KeyDoorTarget.getFlag(UNPASS)){ + ClearField(Door, NONE); + } + + Change(Door, KeyDoorTarget, 0); +} + +void UseNameDoor(uint32 CreatureID, Object Door){ + if(!Door.exists()){ + error("UseNameDoor: Übergebenes Objekt Door existiert nicht.\n"); + throw ERROR; + } + + ObjectType DoorType = Door.getObjectType(); + if(!DoorType.getFlag(NAMEDOOR)){ + error("UseNameDoor: Übergebenes Objekt Door ist keine beschriftete Tür.\n"); + throw ERROR; + } + + if(!DoorType.getFlag(TEXT)){ + error("UseNameDoor: Übergebenes Objekt Door trägt keinen Text.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseNameDoor: Spieler existiert nicht.\n"); + throw ERROR; + } + + int DoorX, DoorY, DoorZ; + GetObjectCoordinates(Door, &DoorX, &DoorY, &DoorZ); + + uint16 HouseID = GetHouseID(DoorX, DoorY, DoorZ); + if(HouseID == 0){ + error("UseNameDoor: Koordinate [%d,%d,%d] gehört zu keinem Haus.\n", + DoorX, DoorY, DoorZ); + throw ERROR; + } + + if(!IsOwner(HouseID, Player) + && !CheckRight(CreatureID, OPEN_NAMEDOORS) + && !MayOpenDoor(Door, Player)){ + throw NOTACCESSIBLE; + } + + ObjectType NameDoorTarget = (int)DoorType.getAttribute(NAMEDOORTARGET); + if(NameDoorTarget.isMapContainer()){ + error("UseNameDoor: Zieltür für Tür %d nicht spezifiziert.\n", + DoorType.TypeID); + throw ERROR; + } + + if(NameDoorTarget.getFlag(UNPASS)){ + ClearField(Door, NONE); + } + + Change(Door, NameDoorTarget, 0); +} + +void UseLevelDoor(uint32 CreatureID, Object Door){ + if(!Door.exists() || !Door.getObjectType().getFlag(LEVELDOOR) + || !Door.getContainer().getObjectType().isMapContainer()){ + error("UseLevelDoor: Übergebenes Objekt Door ist keine Level-Tür.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseLevelDoor: Spieler existiert nicht.\n"); + throw ERROR; + } + + ObjectType DoorType = Door.getObjectType(); + if(!DoorType.getFlag(UNPASS)){ + throw NOTUSABLE; + } + + int DoorLevel = (int)Door.getAttribute(DOORLEVEL); + int PlayerLevel = Player->Skills[SKILL_LEVEL]->Get(); + if(PlayerLevel < DoorLevel){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, "%s.", GetInfo(Door)); + return; + } + + ObjectType LevelDoorTarget = (int)DoorType.getAttribute(LEVELDOORTARGET); + if(LevelDoorTarget.isMapContainer() || LevelDoorTarget.getFlag(UNPASS)){ + error("UseLevelDoor: Zieltür für Tür %d nicht spezifiziert oder nicht passierbar.\n", + DoorType.TypeID); + throw ERROR; + } + + Change(Door, LevelDoorTarget, 0); + Move(0, Player->CrObject, Door.getContainer(), -1, false, NONE); +} + +void UseQuestDoor(uint32 CreatureID, Object Door){ + if(!Door.exists() || !Door.getObjectType().getFlag(QUESTDOOR) + || !Door.getContainer().getObjectType().isMapContainer()){ + error("UseQuestDoor: Übergebenes Objekt Door ist keine Quest-Tür.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseQuestDoor: Spieler existiert nicht.\n"); + throw ERROR; + } + + ObjectType DoorType = Door.getObjectType(); + if(!DoorType.getFlag(UNPASS)){ + throw NOTUSABLE; + } + + int QuestNr = Door.getAttribute(DOORQUESTNUMBER); + int QuestValue = Door.getAttribute(DOORQUESTVALUE); + if(Player->GetQuestValue(QuestNr) != QuestValue){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, "%s.", GetInfo(Door)); + return; + } + + ObjectType QuestDoorTarget = (int)DoorType.getAttribute(QUESTDOORTARGET); + if(QuestDoorTarget.isMapContainer() || QuestDoorTarget.getFlag(UNPASS)){ + error("UseQuestDoor: Zieltür für Tür %d nicht spezifiziert oder nicht passierbar.\n", + DoorType.TypeID); + throw ERROR; + } + + Change(Door, QuestDoorTarget, 0); + Move(0, Player->CrObject, Door.getContainer(), -1, false, NONE); +} + +void UseWeapon(uint32 CreatureID, Object Weapon, Object Target){ + if(!Weapon.exists() || !Weapon.getObjectType().isCloseWeapon()){ + error("UseWeapon: Übergebene Waffe existiert nicht oder ist keine Waffe.\n"); + throw ERROR; + } + + if(!Target.exists() || !Target.getObjectType().getFlag(DESTROY)){ + error("UseWeapon: Übergebenes Ziel existiert nicht oder ist nicht zerstörbar.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseWeapon: Spieler %d existiert nicht.\n", CreatureID); + throw ERROR; + } + + if(!Target.getContainer().getObjectType().isMapContainer()){ + throw NOTACCESSIBLE; + } + + GraphicalEffect(Target, EFFECT_POFF); + if(random(1, 3) == 1){ + // TODO(fusion): This is very similar to what is done in `ProcessCronSystem` + // and it is probably some inlined helper function to transform items that + // might be containers. + ObjectType TargetType = Target.getObjectType(); + ObjectType DestroyTarget = (int)TargetType.getAttribute(DESTROYTARGET); + if(TargetType.getFlag(CONTAINER)){ + int Remainder = 0; + if(!DestroyTarget.isMapContainer() && DestroyTarget.getFlag(CONTAINER)){ + Remainder = (int)DestroyTarget.getAttribute(CAPACITY); + } + + Empty(Target, Remainder); + } + Change(Target, DestroyTarget, 0); + } +} + +void UseChangeObject(uint32 CreatureID, Object Obj){ + if(!Obj.exists() || !Obj.getObjectType().getFlag(CHANGEUSE)){ + error("UseChangeObject: Objekt existiert nicht oder ist kein CHANGEUSE-Objekt.\n"); + throw ERROR; + } + + TPlayer *Player = GetPlayer(CreatureID); + if(Player == NULL){ + error("UseChangeObject: Spieler %d existiert nicht.\n", CreatureID); + throw ERROR; + } + + ObjectType ObjType = Obj.getObjectType(); + ObjectType ChangeTarget = (int)ObjType.getAttribute(CHANGETARGET); + if(!ObjType.getFlag(UNPASS) + && !ChangeTarget.isMapContainer() + && ChangeTarget.getFlag(UNPASS)){ + ClearField(Obj, NONE); + }else if(!ObjType.getFlag(UNLAY) + && !ChangeTarget.isMapContainer() + && ChangeTarget.getFlag(UNLAY)){ + // TODO(fusion): This is similar to `ClearField` except we look for an + // field without `UNLAY`. It is probably an inlined function. + int ObjX, ObjY, ObjZ; + GetObjectCoordinates(Obj, &ObjX, &ObjY, &ObjZ); + + int OffsetX[4] = { 1, 0, -1, 0}; + int OffsetY[4] = { 0, 1, 0, -1}; + for(int i = 0; i < 4; i += 1){ + int DestX = ObjX + OffsetX[i]; + int DestY = ObjY + OffsetY[i]; + int DestZ = ObjZ; + if(CoordinateFlag(DestX, DestY, DestZ, BANK) + && !CoordinateFlag(DestX, DestY, DestZ, UNPASS)){ + Object Dest = GetMapContainer(DestX, DestY, DestZ); + MoveAllObjects(Obj.getNextObject(), Dest, NONE, true); + break; + } + } + } + + Change(Obj, ChangeTarget, 0); +} + +void UseObject(uint32 CreatureID, Object Obj){ + if(!Obj.exists()){ + error("UseObjects: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + if(!Obj.getObjectType().getFlag(USEEVENT)){ + error("UseObjects: Übergebenes Objekt ist nicht benutzbar.\n"); + throw ERROR; + } + + Object User = NONE; + if(CreatureID != 0){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature != NULL){ + User = Creature->CrObject; + } + } + + if(!HandleEvent(MOVEUSE_EVENT_USE, User, Obj, NONE)){ + throw NOTUSABLE; + } +} + +void UseObjects(uint32 CreatureID, Object Obj1, Object Obj2){ + if(!Obj1.exists()){ + error("UseObjects: Übergebenes Objekt Obj1 existiert nicht.\n"); + throw ERROR; + } + + if(!Obj2.exists()){ + error("UseObjects: Übergebenes Objekt Obj2 existiert nicht.\n"); + throw ERROR; + } + + if(!Obj1.getObjectType().getFlag(USEEVENT)){ + error("UseObjects: Übergebenes Objekt Obj1 ist nicht benutzbar.\n"); + throw ERROR; + } + + Object User = NONE; + if(CreatureID != 0){ + TCreature *Creature = GetCreature(CreatureID); + if(Creature != NULL){ + User = Creature->CrObject; + } + } + + if(!HandleEvent(MOVEUSE_EVENT_MULTIUSE, User, Obj1, Obj2)){ + throw NOTUSABLE; + } +} + +void MovementEvent(Object Obj, Object Start, Object Dest){ + if(!Obj.exists()){ + error("MovementEvent: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + ObjectType StartType = Start.getObjectType(); + if(!Start.exists() || (!StartType.getFlag(CONTAINER) && !StartType.getFlag(CHEST))){ + error("MovementEvent: \"Start\" ist kein Container.\n"); + throw ERROR; + } + + ObjectType DestType = Dest.getObjectType(); + if(!Dest.exists() || (!DestType.getFlag(CONTAINER) && !DestType.getFlag(CHEST))){ + error("MovementEvent: \"Dest\" ist kein Container.\n"); + throw ERROR; + } + + if(Obj.getObjectType().getFlag(MOVEMENTEVENT)){ + HandleEvent(MOVEUSE_EVENT_MOVEMENT, NONE, Obj, NONE); + if(!Obj.exists()){ + throw DESTROYED; + } + } +} + +void SeparationEvent(Object Obj, Object Start){ + if(!Obj.exists()){ + error("SeparationEvent: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + if(!Start.exists()){ + error("SeparationEvent: Übergebener Container existiert nicht.\n"); + throw ERROR; + } + + ObjectType StartType = Start.getObjectType(); + if(!StartType.isMapContainer()){ + return; + } + + // NOTE(fusion): Separation event for `Obj` against objects at `Start`. + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(SEPARATIONEVENT)){ + Object Help = GetFirstContainerObject(Start); + while(Help != NONE){ + Object Next = Help.getNextObject(); + if(Help != Obj){ + HandleEvent(MOVEUSE_EVENT_SEPARATION, NONE, Obj, Help); + if(!Obj.exists()){ + throw DESTROYED; + } + } + Help = Next; + } + } + + // NOTE(fusion): Separation event for objects at `Start` against `Obj`. + Object Help = GetFirstContainerObject(Start); + while(Help != NONE){ + Object Next = Help.getNextObject(); + if(Help != Obj){ + ObjectType HelpType = Help.getObjectType(); + if(ObjType.isCreatureContainer() + && (HelpType.getFlag(LEVELDOOR) || HelpType.getFlag(QUESTDOOR))){ + ObjectType DoorTarget = HelpType.getFlag(LEVELDOOR) + ? (int)HelpType.getAttribute(LEVELDOORTARGET) + : (int)HelpType.getAttribute(QUESTDOORTARGET); + if(DoorTarget.isMapContainer() || DoorTarget.getFlag(UNPASS)){ + error("SeparationEvent: Zieltür für Tür %d nicht spezifiziert oder passierbar.\n", + HelpType.TypeID); + throw ERROR; + } + + ClearField(Help, Obj); + Change(Help, DoorTarget, 0); + break; + } + + if(HelpType.getFlag(SEPARATIONEVENT)){ + HandleEvent(MOVEUSE_EVENT_SEPARATION, NONE, Help, Obj); + if(!Obj.exists()){ + throw DESTROYED; + } + } + } + Help = Next; + } +} + +void CollisionEvent(Object Obj, Object Dest){ + if(!Obj.exists()){ + error("CollisionEvent: Übergebenes Objekt existiert nicht.\n"); + throw ERROR; + } + + if(!Dest.exists()){ + error("CollisionEvent: Übergebener Container existiert nicht.\n"); + throw ERROR; + } + + ObjectType DestType = Dest.getObjectType(); + if(!DestType.isMapContainer()){ + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(TELEPORTABSOLUTE) || ObjType.getFlag(TELEPORTRELATIVE)){ + int TeleportEffect; + int TeleportDestX, TeleportDestY, TeleportDestZ; + if(ObjType.getFlag(TELEPORTABSOLUTE)){ + UnpackAbsoluteCoordinate((int)Obj.getAttribute(ABSTELEPORTDESTINATION), + &TeleportDestX, &TeleportDestY, &TeleportDestZ); + TeleportEffect = (int)ObjType.getAttribute(ABSTELEPORTEFFECT); + }else{ + int DisplacementX, DisplacementY, DisplacementZ; + GetObjectCoordinates(Obj, &TeleportDestX, &TeleportDestY, &TeleportDestZ); + UnpackRelativeCoordinate((int)ObjType.getAttribute(RELTELEPORTDISPLACEMENT), + &DisplacementX, &DisplacementY, &DisplacementZ); + TeleportDestX += DisplacementX; + TeleportDestY += DisplacementY; + TeleportDestZ += DisplacementZ; + TeleportEffect = (int)ObjType.getAttribute(RELTELEPORTEFFECT); + } + + Object TeleportDest = GetMapContainer(TeleportDestX, TeleportDestY, TeleportDestZ); + MoveAllObjects(Obj.getNextObject(), TeleportDest, NONE, true); + GraphicalEffect(TeleportDestX, TeleportDestY, TeleportDestZ, TeleportEffect); + + // TODO(fusion): Is this even possible? Maybe `MoveAllObjects` could + // trigger a separation event that destroys `Obj`? + if(!Obj.exists()){ + throw DESTROYED; + } + }else{ + // NOTE(fusion): Collision event for `Obj` against objects at `Dest`. + if(ObjType.getFlag(COLLISIONEVENT)){ + Object Help = GetFirstContainerObject(Dest); + while(Help != NONE){ + Object Next = Help.getNextObject(); + if(Help != Obj){ + HandleEvent(MOVEUSE_EVENT_COLLISION, NONE, Obj, Help); + if(!Obj.exists()){ + throw DESTROYED; + } + } + Help = Next; + } + } + + // NOTE(fusion): Collision event for objects at `Dest` against `Obj`. + Object Help = GetFirstContainerObject(Dest); + while(Help != NONE){ + Object Next = Help.getNextObject(); + if(Help != Obj){ + ObjectType HelpType = Help.getObjectType(); + if(HelpType.getFlag(TELEPORTABSOLUTE) || HelpType.getFlag(TELEPORTRELATIVE)){ + int TeleportEffect; + int TeleportDestX, TeleportDestY, TeleportDestZ; + if(HelpType.getFlag(TELEPORTABSOLUTE)){ + UnpackAbsoluteCoordinate((int)Help.getAttribute(ABSTELEPORTDESTINATION), + &TeleportDestX, &TeleportDestY, &TeleportDestZ); + TeleportEffect = (int)HelpType.getAttribute(ABSTELEPORTEFFECT); + }else{ + int DisplacementX, DisplacementY, DisplacementZ; + GetObjectCoordinates(Help, &TeleportDestX, &TeleportDestY, &TeleportDestZ); + UnpackRelativeCoordinate((int)HelpType.getAttribute(RELTELEPORTDISPLACEMENT), + &DisplacementX, &DisplacementY, &DisplacementZ); + TeleportDestX += DisplacementX; + TeleportDestY += DisplacementY; + TeleportDestZ += DisplacementZ; + TeleportEffect = (int)HelpType.getAttribute(RELTELEPORTEFFECT); + } + + Object TeleportDest = GetMapContainer(TeleportDestX, TeleportDestY, TeleportDestZ); + MoveOneObject(Obj, TeleportDest); + GraphicalEffect(TeleportDestX, TeleportDestY, TeleportDestZ, TeleportEffect); + }else if(HelpType.getFlag(COLLISIONEVENT)){ + HandleEvent(MOVEUSE_EVENT_COLLISION, NONE, Help, Obj); + } + + if(!Obj.exists()){ + throw DESTROYED; + } + } + Help = Next; + } + } +} + +// Event Loading / Initialization +// ============================================================================= +void LoadParameters(TReadScriptFile *Script, int *Parameters, int NumberOfParameters, ...){ + if(NumberOfParameters > MOVEUSE_MAX_PARAMETERS){ + error("LoadParameters: Zu viele Parameter (%d).\n", NumberOfParameters); + Script->error("too many parameters"); + } + + if(NumberOfParameters == 0){ + return; + } + + if(Script->Token != SPECIAL || Script->getSpecial() != '('){ + Script->error("'(' expected"); + } + + va_list ap; + va_start(ap, NumberOfParameters); + for(int i = 0; i < NumberOfParameters; i += 1){ + if(i > 0){ + Script->readSymbol(','); + } + + int ParamType = va_arg(ap, int); + switch(ParamType){ + case MOVEUSE_PARAMETER_OBJECT:{ + const char *Object = Script->readIdentifier(); + if(strcmp(Object, "null") == 0){ + Parameters[i] = 0; // MOVEUSE_OBJECT_NULL ? + }else if(strcmp(Object, "obj1") == 0){ + Parameters[i] = 1; // MOVEUSE_OBJECT_1 ? + }else if(strcmp(Object, "obj2") == 0){ + Parameters[i] = 2; // MOVEUSE_OBJECT_2 ? + }else if(strcmp(Object, "user") == 0){ + Parameters[i] = 3; // MOVEUSE_OBJECT_USER ? + }else if(strcmp(Object, "temp") == 0){ + Parameters[i] = 4; // MOVEUSE_OBJECT_TEMP ? + }else{ + Script->error("Object expected"); + } + break; + } + + case MOVEUSE_PARAMETER_TYPE:{ + int TypeID = Script->readNumber(); + Parameters[i] = TypeID; + if(!ObjectTypeExists(TypeID)){ + Script->error("Unknown object type"); + } + break; + } + + case MOVEUSE_PARAMETER_FLAG:{ + int Flag = GetFlagByName(Script->readIdentifier()); + Parameters[i] = Flag; + if(Flag == -1){ + Script->error("Unknown flag"); + } + break; + } + + case MOVEUSE_PARAMETER_TYPEATTRIBUTE:{ + int TypeAttribute = GetTypeAttributeByName(Script->readIdentifier()); + Parameters[i] = TypeAttribute; + if(TypeAttribute == -1){ + Script->error("Unknown type attribute"); + } + break; + } + + case MOVEUSE_PARAMETER_INSTANCEATTRIBUTE:{ + int InstanceAttribute = GetInstanceAttributeByName(Script->readIdentifier()); + Parameters[i] = InstanceAttribute; + if(InstanceAttribute == -1){ + Script->error("Unknown instance attribute"); + } + break; + } + + case MOVEUSE_PARAMETER_COORDINATE:{ + int AbsX, AbsY, AbsZ; + Script->readCoordinate(&AbsX, &AbsY, &AbsZ); + Parameters[i] = PackAbsoluteCoordinate(AbsX, AbsY, AbsZ); + break; + } + + case MOVEUSE_PARAMETER_VECTOR:{ + int RelX, RelY, RelZ; + Script->readCoordinate(&RelX, &RelY, &RelZ); + Parameters[i] = PackRelativeCoordinate(RelX, RelY, RelZ); + break; + } + + case MOVEUSE_PARAMETER_RIGHT:{ + const char *Right = Script->getIdentifier(); + if(strcmp(Right, "premium_account") == 0){ + Parameters[i] = PREMIUM_ACCOUNT; + }else if(strcmp(Right, "special_moveuse") == 0){ + Parameters[i] = SPECIAL_MOVEUSE; + }else{ + Script->error("Unknown right"); + } + break; + } + + case MOVEUSE_PARAMETER_SKILL:{ + int SkillNr = GetSkillByName(Script->readIdentifier()); + Parameters[i] = SkillNr; + if(SkillNr == -1){ + Script->error("Unknown skill"); + } + break; + } + + case MOVEUSE_PARAMETER_NUMBER:{ + Parameters[i] = Script->readNumber(); + break; + } + + case MOVEUSE_PARAMETER_TEXT:{ + const char *Text = Script->readString(); + Parameters[i] = AddDynamicString(Text); + break; + } + + case MOVEUSE_PARAMETER_COMPARISON:{ + int Operator = (int)Script->readSpecial(); + Parameters[i] = Operator; + if(strchr("<=>GLN", Operator) == NULL){ + Script->error("Unknown comparison operator"); + } + break; + } + } + } + va_end(ap); + + Script->readSymbol(')'); + Script->nextToken(); +} + +void LoadCondition(TReadScriptFile *Script, TMoveUseCondition *Condition){ + char Identifier[MAX_IDENT_LENGTH]; + strcpy(Identifier, Script->getIdentifier()); + + Script->nextToken(); + if(strcmp(Identifier, "isposition") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISPOSITION; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "istype") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISTYPE; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPE); + }else if(strcmp(Identifier, "iscreature") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISCREATURE; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "isplayer") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISPLAYER; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "hasflag") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASFLAG; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_FLAG); + }else if(strcmp(Identifier, "hastypeattribute") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASTYPEATTRIBUTE; + LoadParameters(Script, Condition->Parameters, 4, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPEATTRIBUTE, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "hasinstanceattribute") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASINSTANCEATTRIBUTE; + LoadParameters(Script, Condition->Parameters, 4, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_INSTANCEATTRIBUTE, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "hastext") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASTEXT; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TEXT); + }else if(strcmp(Identifier, "ispeaceful") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISPEACEFUL; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "maylogout") == 0){ + Condition->Condition = MOVEUSE_CONDITION_MAYLOGOUT; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "hasprofession") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASPROFESSION; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "haslevel") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASLEVEL; + LoadParameters(Script, Condition->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "hasright") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASRIGHT; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_RIGHT); + }else if(strcmp(Identifier, "hasquestvalue") == 0){ + Condition->Condition = MOVEUSE_CONDITION_HASQUESTVALUE; + LoadParameters(Script, Condition->Parameters, 4, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "testskill") == 0){ + Condition->Condition = MOVEUSE_CONDITION_TESTSKILL; + LoadParameters(Script, Condition->Parameters, 4, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_SKILL, + MOVEUSE_PARAMETER_NUMBER, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "countobjects") == 0){ + Condition->Condition = MOVEUSE_CONDITION_COUNTOBJECTS; + LoadParameters(Script, Condition->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "countobjectsonmap") == 0){ + Condition->Condition = MOVEUSE_CONDITION_COUNTOBJECTSONMAP; + LoadParameters(Script, Condition->Parameters, 3, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_COMPARISON, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "isobjectthere") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISOBJECTTHERE; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE); + }else if(strcmp(Identifier, "iscreaturethere") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISCREATURETHERE; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "isplayerthere") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISPLAYERTHERE; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "isobjectininventory") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISOBJECTININVENTORY; + LoadParameters(Script, Condition->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "isprotectionzone") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISPROTECTIONZONE; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "ishouse") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISHOUSE; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "ishouseowner") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISHOUSEOWNER; + LoadParameters(Script, Condition->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "isdressed") == 0){ + Condition->Condition = MOVEUSE_CONDITION_ISDRESSED; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "random") == 0){ + Condition->Condition = MOVEUSE_CONDITION_RANDOM; + LoadParameters(Script, Condition->Parameters, 1, + MOVEUSE_PARAMETER_NUMBER); + }else{ + Script->error("invalid condition"); + } +} + +void LoadAction(TReadScriptFile *Script, TMoveUseAction *Action){ + char Identifier[MAX_IDENT_LENGTH]; + strcpy(Identifier, Script->getIdentifier()); + + Script->nextToken(); + if(strcmp(Identifier, "createonmap") == 0){ + Action->Action = MOVEUSE_ACTION_CREATEONMAP; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "create") == 0){ + Action->Action = MOVEUSE_ACTION_CREATE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "monsteronmap") == 0){ + Action->Action = MOVEUSE_ACTION_MONSTERONMAP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "monster") == 0){ + Action->Action = MOVEUSE_ACTION_MONSTER; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "effectonmap") == 0){ + Action->Action = MOVEUSE_ACTION_EFFECTONMAP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "effect") == 0){ + Action->Action = MOVEUSE_ACTION_EFFECT; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "textonmap") == 0){ + Action->Action = MOVEUSE_ACTION_TEXTONMAP; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TEXT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "text") == 0){ + Action->Action = MOVEUSE_ACTION_TEXT; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TEXT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "changeonmap") == 0){ + Action->Action = MOVEUSE_ACTION_CHANGEONMAP; + LoadParameters(Script, Action->Parameters, 4, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "change") == 0){ + Action->Action = MOVEUSE_ACTION_CHANGE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "changerel") == 0){ + Action->Action = MOVEUSE_ACTION_CHANGEREL; + LoadParameters(Script, Action->Parameters, 5, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_VECTOR, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "setattribute") == 0){ + Action->Action = MOVEUSE_ACTION_SETATTRIBUTE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_INSTANCEATTRIBUTE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "changeattribute") == 0){ + Action->Action = MOVEUSE_ACTION_CHANGEATTRIBUTE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_INSTANCEATTRIBUTE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "setquestvalue") == 0){ + Action->Action = MOVEUSE_ACTION_SETQUESTVALUE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "damage") == 0){ + Action->Action = MOVEUSE_ACTION_DAMAGE; + LoadParameters(Script, Action->Parameters, 4, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "setstart") == 0){ + Action->Action = MOVEUSE_ACTION_SETSTART; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "writename") == 0){ + Action->Action = MOVEUSE_ACTION_WRITENAME; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TEXT, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "writetext") == 0){ + Action->Action = MOVEUSE_ACTION_WRITETEXT; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_TEXT, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "logout") == 0){ + Action->Action = MOVEUSE_ACTION_LOGOUT; + LoadParameters(Script, Action->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "moveallonmap") == 0){ + Action->Action = MOVEUSE_ACTION_MOVEALLONMAP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "moveall") == 0){ + Action->Action = MOVEUSE_ACTION_MOVEALL; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "moveallrel") == 0){ + Action->Action = MOVEUSE_ACTION_MOVEALLREL; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_VECTOR); + }else if(strcmp(Identifier, "movetoponmap") == 0){ + Action->Action = MOVEUSE_ACTION_MOVETOPONMAP; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "movetop") == 0){ + Action->Action = MOVEUSE_ACTION_MOVETOP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "movetoprel") == 0){ + Action->Action = MOVEUSE_ACTION_MOVETOPREL; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_VECTOR); + }else if(strcmp(Identifier, "move") == 0){ + Action->Action = MOVEUSE_ACTION_MOVE; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "moverel") == 0){ + Action->Action = MOVEUSE_ACTION_MOVEREL; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_VECTOR); + }else if(strcmp(Identifier, "retrieve") == 0){ + Action->Action = MOVEUSE_ACTION_RETRIEVE; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_VECTOR, + MOVEUSE_PARAMETER_VECTOR); + }else if(strcmp(Identifier, "deleteallonmap") == 0){ + Action->Action = MOVEUSE_ACTION_DELETEALLONMAP; + LoadParameters(Script, Action->Parameters, 1, + MOVEUSE_PARAMETER_COORDINATE); + }else if(strcmp(Identifier, "deletetoponmap") == 0){ + Action->Action = MOVEUSE_ACTION_DELETETOPONMAP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE); + }else if(strcmp(Identifier, "deleteonmap") == 0){ + Action->Action = MOVEUSE_ACTION_DELETEONMAP; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE); + }else if(strcmp(Identifier, "delete") == 0){ + Action->Action = MOVEUSE_ACTION_DELETE; + LoadParameters(Script, Action->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "deleteininventory") == 0){ + Action->Action = MOVEUSE_ACTION_DELETEININVENTORY; + LoadParameters(Script, Action->Parameters, 3, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "description") == 0){ + Action->Action = MOVEUSE_ACTION_DESCRIPTION; + LoadParameters(Script, Action->Parameters, 2, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "loaddepot") == 0){ + Action->Action = MOVEUSE_ACTION_LOADDEPOT; + LoadParameters(Script, Action->Parameters, 4, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "savedepot") == 0){ + Action->Action = MOVEUSE_ACTION_SAVEDEPOT; + LoadParameters(Script, Action->Parameters, 4, + MOVEUSE_PARAMETER_COORDINATE, + MOVEUSE_PARAMETER_TYPE, + MOVEUSE_PARAMETER_OBJECT, + MOVEUSE_PARAMETER_NUMBER); + }else if(strcmp(Identifier, "sendmail") == 0){ + Action->Action = MOVEUSE_ACTION_SENDMAIL; + LoadParameters(Script, Action->Parameters, 1, + MOVEUSE_PARAMETER_OBJECT); + }else if(strcmp(Identifier, "nop") == 0){ + Action->Action = MOVEUSE_ACTION_NOP; + LoadParameters(Script, Action->Parameters, 0); + }else{ + Script->error("invalid action"); + } +} + +void LoadDataBase(void){ + print(1, "Lade Move/Use-Datenbank ...\n"); + + char FileName[4096]; + snprintf(FileName, sizeof(FileName), "%s/moveuse.dat", DATAPATH); + + for(int i = 0; i < NARRAY(MoveUseDatabases); i += 1){ + MoveUseDatabases[i].NumberOfRules = 0; + } + + TReadScriptFile Script; + Script.open(FileName); + Script.nextToken(); + while(Script.Token != ENDOFFILE){ + const char *Identifier = Script.getIdentifier(); + + if(strcmp(Identifier, "begin") == 0){ + Script.readString(); + continue; + }else if(strcmp(Identifier, "end") == 0){ + continue; + } + + int EventType; + if(strcmp(Identifier, "use") == 0){ + EventType = MOVEUSE_EVENT_MULTIUSE; + }else if(strcmp(Identifier, "multiuse") == 0){ + EventType = MOVEUSE_EVENT_MULTIUSE; + }else if(strcmp(Identifier, "movement") == 0){ + EventType = MOVEUSE_EVENT_MULTIUSE; + }else if(strcmp(Identifier, "collision") == 0){ + EventType = MOVEUSE_EVENT_MULTIUSE; + }else if(strcmp(Identifier, "separation") == 0){ + EventType = MOVEUSE_EVENT_MULTIUSE; + }else{ + Script.error("Unknown event type"); + } + + Script.readSymbol(','); + + MoveUseDatabases[EventType].NumberOfRules += 1; + TMoveUseRule *Rule = MoveUseDatabases[EventType].Rules.at( + MoveUseDatabases[EventType].NumberOfRules); + + // NOTE(fusion): Conditions. + Rule->FirstCondition = NumberOfMoveUseConditions + 1; + while(true){ + Script.nextToken(); + NumberOfMoveUseConditions += 1; + TMoveUseCondition *Condition = MoveUseConditions.at(NumberOfMoveUseConditions); + Condition->Modifier = MOVEUSE_MODIFIER_NORMAL; + if(Script.Token == SPECIAL){ + if(Script.getSpecial() == '!'){ + Script.nextToken(); + Condition->Modifier = MOVEUSE_MODIFIER_INVERT; + }else if(Script.getSpecial() == '~'){ + Script.nextToken(); + Condition->Modifier = MOVEUSE_MODIFIER_TRUE; + } + } + LoadCondition(&Script, Condition); + + if(Script.Token != SPECIAL || Script.getSpecial() != ','){ + break; + } + } + Rule->LastCondition = NumberOfMoveUseConditions; + + if(Script.Token != SPECIAL || Script.getSpecial() != 'I'){ + Script.error("'->' expected"); + } + + // NOTE(fusion): Actions. + Rule->FirstAction = NumberOfMoveUseActions + 1; + while(true){ + Script.nextToken(); + NumberOfMoveUseActions += 1; + TMoveUseAction *Action = MoveUseActions.at(NumberOfMoveUseActions); + LoadAction(&Script, Action); + + if(Script.Token != SPECIAL || Script.getSpecial() != ','){ + break; + } + } + Rule->LastAction = NumberOfMoveUseActions; + + // NOTE(fusion): Optional tag? + if(Script.Token == STRING){ + Script.nextToken(); + } + } + + Script.close(); + + print(1, "Move/Use-Datenbank mit %d/%d/%d/%d/%d Regeln gelesen.\n", + MoveUseDatabases[MOVEUSE_EVENT_USE].NumberOfRules, + MoveUseDatabases[MOVEUSE_EVENT_MULTIUSE].NumberOfRules, + MoveUseDatabases[MOVEUSE_EVENT_MOVEMENT].NumberOfRules, + MoveUseDatabases[MOVEUSE_EVENT_COLLISION].NumberOfRules, + MoveUseDatabases[MOVEUSE_EVENT_SEPARATION].NumberOfRules); +} + +void InitMoveUse(void){ + NumberOfMoveUseConditions = 0; + NumberOfMoveUseActions = 0; + DelayedMails = 0; + LoadDataBase(); +} + +void ExitMoveUse(void){ + for(int i = 0; i < DelayedMails; i += 1){ + error("ExitMoveUse: Paket an %u wurde nicht zugestellt.\n", + DelayedMail.at(i)->CharacterID); + } +} diff --git a/src/moveuse.hh b/src/moveuse.hh index 1036142..83d0944 100644 --- a/src/moveuse.hh +++ b/src/moveuse.hh @@ -2,8 +2,194 @@ #define TIBIA_MOVEUSE_HH_ 1 #include "common.hh" +#include "containers.hh" #include "map.hh" +#include "script.hh" +#define MOVEUSE_MAX_PARAMETERS 5 + +struct TPlayerData; + +enum MoveUseActionType: int { + MOVEUSE_ACTION_CREATEONMAP = 0, + MOVEUSE_ACTION_CREATE = 1, + MOVEUSE_ACTION_MONSTERONMAP = 2, + MOVEUSE_ACTION_MONSTER = 3, + MOVEUSE_ACTION_EFFECTONMAP = 4, + MOVEUSE_ACTION_EFFECT = 5, + MOVEUSE_ACTION_TEXTONMAP = 6, + MOVEUSE_ACTION_TEXT = 7, + MOVEUSE_ACTION_CHANGEONMAP = 8, + MOVEUSE_ACTION_CHANGE = 9, + MOVEUSE_ACTION_CHANGEREL = 10, + MOVEUSE_ACTION_SETATTRIBUTE = 11, + MOVEUSE_ACTION_CHANGEATTRIBUTE = 12, + MOVEUSE_ACTION_SETQUESTVALUE = 13, + MOVEUSE_ACTION_DAMAGE = 14, + MOVEUSE_ACTION_SETSTART = 15, + MOVEUSE_ACTION_WRITENAME = 16, + MOVEUSE_ACTION_WRITETEXT = 17, + MOVEUSE_ACTION_LOGOUT = 18, + MOVEUSE_ACTION_MOVEALLONMAP = 19, + MOVEUSE_ACTION_MOVEALL = 20, + MOVEUSE_ACTION_MOVEALLREL = 21, + MOVEUSE_ACTION_MOVETOPONMAP = 22, + MOVEUSE_ACTION_MOVETOP = 23, + MOVEUSE_ACTION_MOVETOPREL = 24, + MOVEUSE_ACTION_MOVE = 25, + MOVEUSE_ACTION_MOVEREL = 26, + MOVEUSE_ACTION_RETRIEVE = 27, + MOVEUSE_ACTION_DELETEALLONMAP = 28, + MOVEUSE_ACTION_DELETETOPONMAP = 29, + MOVEUSE_ACTION_DELETEONMAP = 30, + MOVEUSE_ACTION_DELETE = 31, + MOVEUSE_ACTION_DELETEININVENTORY = 32, + MOVEUSE_ACTION_DESCRIPTION = 33, + MOVEUSE_ACTION_LOADDEPOT = 34, + MOVEUSE_ACTION_SAVEDEPOT = 35, + MOVEUSE_ACTION_SENDMAIL = 36, + MOVEUSE_ACTION_NOP = 37, +}; + +enum MoveUseConditionType: int { + MOVEUSE_CONDITION_ISPOSITION = 0, + MOVEUSE_CONDITION_ISTYPE = 1, + MOVEUSE_CONDITION_ISCREATURE = 2, + MOVEUSE_CONDITION_ISPLAYER = 3, + MOVEUSE_CONDITION_HASFLAG = 4, + MOVEUSE_CONDITION_HASTYPEATTRIBUTE = 5, + MOVEUSE_CONDITION_HASINSTANCEATTRIBUTE = 6, + MOVEUSE_CONDITION_HASTEXT = 7, + MOVEUSE_CONDITION_ISPEACEFUL = 8, + MOVEUSE_CONDITION_MAYLOGOUT = 9, + MOVEUSE_CONDITION_HASPROFESSION = 10, + MOVEUSE_CONDITION_HASLEVEL = 11, + MOVEUSE_CONDITION_HASRIGHT = 12, + MOVEUSE_CONDITION_HASQUESTVALUE = 13, + MOVEUSE_CONDITION_TESTSKILL = 14, + MOVEUSE_CONDITION_COUNTOBJECTS = 15, + MOVEUSE_CONDITION_COUNTOBJECTSONMAP = 16, + MOVEUSE_CONDITION_ISOBJECTTHERE = 17, + MOVEUSE_CONDITION_ISCREATURETHERE = 18, + MOVEUSE_CONDITION_ISPLAYERTHERE = 19, + MOVEUSE_CONDITION_ISOBJECTININVENTORY = 20, + MOVEUSE_CONDITION_ISPROTECTIONZONE = 21, + MOVEUSE_CONDITION_ISHOUSE = 22, + MOVEUSE_CONDITION_ISHOUSEOWNER = 23, + MOVEUSE_CONDITION_ISDRESSED = 24, + MOVEUSE_CONDITION_RANDOM = 25, +}; + +enum MoveUseEventType: int { + MOVEUSE_EVENT_USE = 0, + MOVEUSE_EVENT_MULTIUSE = 1, + MOVEUSE_EVENT_MOVEMENT = 2, + MOVEUSE_EVENT_COLLISION = 3, + MOVEUSE_EVENT_SEPARATION = 4, +}; + +enum MoveUseModifierType: int { + MOVEUSE_MODIFIER_NORMAL = 0, + MOVEUSE_MODIFIER_INVERT = 1, + MOVEUSE_MODIFIER_TRUE = 2, +}; + +enum MoveUseParameterType: int { + MOVEUSE_PARAMETER_OBJECT = 0, + MOVEUSE_PARAMETER_TYPE = 1, + MOVEUSE_PARAMETER_FLAG = 2, + MOVEUSE_PARAMETER_TYPEATTRIBUTE = 3, + MOVEUSE_PARAMETER_INSTANCEATTRIBUTE = 4, + MOVEUSE_PARAMETER_COORDINATE = 5, + MOVEUSE_PARAMETER_VECTOR = 6, + MOVEUSE_PARAMETER_RIGHT = 7, + MOVEUSE_PARAMETER_SKILL = 8, + MOVEUSE_PARAMETER_NUMBER = 9, + MOVEUSE_PARAMETER_TEXT = 10, + MOVEUSE_PARAMETER_COMPARISON = 11, +}; + +struct TMoveUseAction { + MoveUseActionType Action; + int Parameters[MOVEUSE_MAX_PARAMETERS]; +}; + +struct TMoveUseRule { + int FirstCondition; + int LastCondition; + int FirstAction; + int LastAction; +}; + +struct TMoveUseCondition { + MoveUseModifierType Modifier; + MoveUseConditionType Condition; + int Parameters[MOVEUSE_MAX_PARAMETERS]; +}; + +struct TMoveUseDatabase { + TMoveUseDatabase(void) : Rules(1, 100, 100), NumberOfRules(0) {} + + vector Rules; + int NumberOfRules; +}; + +struct TDelayedMail { + uint32 CharacterID; + int DepotNumber; + uint8 *Packet; + int PacketSize; +}; + +int PackAbsoluteCoordinate(int x, int y, int z); +void UnpackAbsoluteCoordinate(int Packed, int *x, int *y, int *z); +int PackRelativeCoordinate(int x, int y, int z); +void UnpackRelativeCoordinate(int Packed, int *x, int *y, int *z); + +Object GetEventObject(int Nr, Object User, Object Obj1, Object Obj2, Object Temp); +bool Compare(int Value1, int Operator, int Value2); +bool CheckCondition(MoveUseEventType EventType, TMoveUseCondition *Condition, + Object User, Object Obj1, Object Obj2, Object *Temp); +Object CreateObject(Object Con, ObjectType Type, uint32 Value); void ChangeObject(Object Obj, ObjectType NewType, uint32 Value); +void MoveOneObject(Object Obj, Object Con); +void MoveAllObjects(Object Obj, Object Dest, Object Exclude, bool MoveUnmovable); +void DeleteAllObjects(Object Obj, Object Exclude, bool DeleteUnmovable); +void ClearField(Object Obj, Object Exclude); +void LoadDepotBox(uint32 CreatureID, int Nr, Object Con); +void SaveDepotBox(uint32 CreatureID, int Nr, Object Con); +void SendMail(Object Obj); +void SendMails(TPlayerData *PlayerData); +void TextEffect(const char *Text, int x, int y, int z, int Radius); +void ExecuteAction(MoveUseEventType EventType, TMoveUseAction *Action, + Object User, Object Obj1, Object Obj2, Object *Temp); +bool HandleEvent(MoveUseEventType EventType, Object User, Object Obj1, Object Obj2); + +void UseContainer(uint32 CreatureID, Object Con, int NextContainerNr); +void UseChest(uint32 CreatureID, Object Chest); +void UseLiquidContainer(uint32 CreatureID, Object Obj, Object Dest); +void UseFood(uint32 CreatureID, Object Obj); +void UseTextObject(uint32 CreatureID, Object Obj); +void UseAnnouncer(uint32 CreatureID, Object Obj); +void UseKeyDoor(uint32 CreatureID, Object Key, Object Door); +void UseNameDoor(uint32 CreatureID, Object Door); +void UseLevelDoor(uint32 CreatureID, Object Door); +void UseQuestDoor(uint32 CreatureID, Object Door); +void UseWeapon(uint32 CreatureID, Object Weapon, Object Target); +void UseChangeObject(uint32 CreatureID, Object Obj); +void UseObject(uint32 CreatureID, Object Obj); +void UseObjects(uint32 CreatureID, Object Obj1, Object Obj2); +void MovementEvent(Object Obj, Object Start, Object Dest); +void SeparationEvent(Object Obj, Object Start); +void CollisionEvent(Object Obj, Object Dest); + +void LoadParameters(TReadScriptFile *Script, int *Parameters, int NumberOfParameters, ...); +void LoadCondition(TReadScriptFile *Script, TMoveUseCondition *Condition); +void LoadAction(TReadScriptFile *Script, TMoveUseAction *Action); +void LoadDataBase(void); + + +void InitMoveUse(void); +void ExitMoveUse(void); #endif //TIBIA_MOVEUSE_HH_ diff --git a/src/operate.cc b/src/operate.cc index e742806..8123ba0 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -1,6 +1,7 @@ #include "operate.hh" #include "config.hh" #include "info.hh" +#include "moveuse.hh" #include "stubs.hh" @@ -2107,15 +2108,12 @@ void Look(uint32 CreatureID, Object Obj){ if(CreatureID == 0 || ObjectInRange(CreatureID, Obj, 1)){ if(ObjType.getFlag(TAKE) && GetWeight(Obj, -1) > 0){ int ObjWeight = GetCompleteWeight(Obj); - if(ObjType.getFlag(CUMULATIVE) + bool Multiple = ObjType.getFlag(CUMULATIVE) && Obj.getAttribute(AMOUNT) > 1 - && IsCountable(ObjType.getName(1))){ - snprintf(Help, sizeof(Help), "\nThey weigh %d.%02d oz.", - ObjWeight / 100, ObjWeight % 100); - }else{ - snprintf(Help, sizeof(Help), "\nIt weighs %d.%02d oz.", - ObjWeight / 100, ObjWeight % 100); - } + && IsCountable(ObjType.getName(1)); + snprintf(Help, sizeof(Help), "\n%s %d.%02d oz.", + (Multiple ? "They weigh" : "It weighs"), + (ObjWeight / 100), (ObjWeight % 100)); strcat(Description, Help); } @@ -2570,7 +2568,7 @@ void Turn(uint32 CreatureID, Object Obj){ throw NOTTURNABLE; } - ObjectType RotateTarget = ObjType.getAttribute(ROTATETARGET); + ObjectType RotateTarget = (int)ObjType.getAttribute(ROTATETARGET); if(RotateTarget == ObjType){ error("Turn: Objekt %d wird durch Drehen zerstört.\n", ObjType.TypeID); } @@ -2753,7 +2751,7 @@ void ProcessCronSystem(void){ } ObjectType ObjType = Obj.getObjectType(); - ObjectType ExpireTarget = ObjType.getAttribute(EXPIRETARGET); + ObjectType ExpireTarget = (int)ObjType.getAttribute(EXPIRETARGET); if(ObjType.getFlag(CONTAINER)){ int Remainder = 0; if(!ExpireTarget.isMapContainer() && ExpireTarget.getFlag(CONTAINER)){ diff --git a/src/stubs.hh b/src/stubs.hh index 4b9e3cc..191c733 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -31,11 +31,14 @@ extern const char *GetHouseName(uint16 HouseID); extern const char *GetHouseOwner(uint16 HouseID); extern void InitLog(const char *ProtocolName); extern bool IsInvited(uint16 HouseID, TPlayer *Player, int TimeStamp); +extern bool IsOwner(uint16 HouseID, TPlayer *Player); extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest); extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures); +extern void LoadCharacterOrder(uint32 CharacterID); extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ); extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3); extern void LogoutOrder(TPlayer *Player); +extern bool MayOpenDoor(Object Door, TPlayer *Player); extern void PrepareHouseCleanup(void); extern void FinishHouseCleanup(void); extern void PlayerlistOrder(int NumberOfPlayers, char *PlayerNames, int *PlayerLevels, int *PlayerProfessions); @@ -49,28 +52,8 @@ extern void SavePlayerData(TPlayerData *Slot); extern bool LoadPlayerData(TPlayerData *Slot); extern bool PlayerDataExists(uint32 CharacterID); extern void SavePlayerDataOrder(void); -extern void SendMails(TPlayerData *PlayerData); 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); -// 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); - #endif //TIBIA_STUBS_HH_ -- cgit v1.2.3