From 76f6ecb7c809c6e93447efb91bdf50f2a9d50d6b Mon Sep 17 00:00:00 2001 From: fusion32 Date: Fri, 6 Jun 2025 19:36:18 -0300 Subject: [PATCH] some work on `crmain.cc` and `cract.cc` + merge creature headers --- Makefile | 6 +- TODO.md | 12 +- reference/game.c | 3443 -------------------------------------------- reference/types.hh | 32 +- src/connection.hh | 84 +- src/containers.hh | 4 +- src/cr.hh | 77 +- src/cract.cc | 809 +++++++++++ src/crcombat.cc | 6 +- src/crmain.cc | 581 +++++++- src/crskill.cc | 12 +- src/magic.cc | 7 +- src/map.cc | 28 +- src/map.hh | 15 + src/stubs.hh | 12 +- 15 files changed, 1553 insertions(+), 3575 deletions(-) create mode 100644 src/cract.cc diff --git a/Makefile b/Makefile index c958d5b..e3acc48 100644 --- a/Makefile +++ b/Makefile @@ -15,13 +15,17 @@ endif HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/config.hh $(SRCDIR)/connection.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/enums.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/objects.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/thread.hh -$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/config.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj +$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/config.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj $(CC) -c $(CFLAGS) $(LFLAGS) -o $@ $^ $(BUILDDIR)/config.obj: $(SRCDIR)/config.cc $(HEADERS) @mkdir -p $(@D) $(CC) -c $(CFLAGS) -o $@ $< +$(BUILDDIR)/cract.obj: $(SRCDIR)/cract.cc $(HEADERS) + @mkdir -p $(@D) + $(CC) -c $(CFLAGS) -o $@ $< + $(BUILDDIR)/crcombat.obj: $(SRCDIR)/crcombat.cc $(HEADERS) @mkdir -p $(@D) $(CC) -c $(CFLAGS) -o $@ $< diff --git a/TODO.md b/TODO.md index e237083..12dc857 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,12 @@ ## TODO NEXT -- merge creature headers into a single one CR.HH - - this should help preventing dependency cycles and centralize creature data - structures and globals in a single place -- CRMAIN.CC, CRPLAYER.CC, CRNONPL.CC, CRACT.CC +- CRACT.CC +- CRMAIN.CC + - TCreature::CreatureMoveStimulus + - FINDCREATURES + - KILL STATS + - RACE + - RAIDS +- CRPLAYER.CC, CRNONPL.CC - HOUSES.CC - INFO.CC - OPERATE.CC diff --git a/reference/game.c b/reference/game.c index 9fbabaf..65f96be 100644 --- a/reference/game.c +++ b/reference/game.c @@ -29623,370 +29623,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -TCreature * GetCreature(ulong id) - -{ - TCreature *pTVar1; - ulong m; - - if ((id != 0) && (pTVar1 = HashList[id % 1000], pTVar1 != (TCreature *)0x0)) { - if (pTVar1->ID == id) { - return pTVar1; - } - for (pTVar1 = pTVar1->NextHashEntry; pTVar1 != (TCreature *)0x0; - pTVar1 = pTVar1->NextHashEntry) { - if (pTVar1->ID == id) { - return pTVar1; - } - } - } - return (TCreature *)0x0; -} - - - -TCreature * GetCreature(Object *Obj) - -{ - ulong id; - TCreature *pTVar1; - - id = Object::getCreatureID(Obj); - pTVar1 = GetCreature(id); - return pTVar1; -} - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ProcessSkills(void) - -{ - TCreature *pTVar1; - TCreature *cr; - TCreature **ppTVar2; - int i; - int i_00; - - i_00 = 0; - if (0 < FirstFreeCreature) { - do { - ppTVar2 = vector::operator()(&CreatureList,i_00); - pTVar1 = *ppTVar2; - if (pTVar1 == (TCreature *)0x0) { - error("ProcessSkills: Kreatur %d existiert nicht.\n",i_00); - } - else if ((pTVar1->super_TSkillBase).FirstFreeTimer != 0) { - TSkillBase::ProcessSkills(&pTVar1->super_TSkillBase); - } - i_00 = i_00 + 1; - } while (i_00 < FirstFreeCreature); - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ProcessCreatures(void) - -{ - TPlayer *this; - bool bVar1; - TCreature **ppTVar2; - int iVar3; - uint uVar4; - CreatureType CVar5; - TCreature *cr; - int i; - int i_00; - - i_00 = 0; - if (0 < FirstFreeCreature) { - do { - ppTVar2 = vector::operator()(&CreatureList,i_00); - this = (TPlayer *)*ppTVar2; - if (this == (TPlayer *)0x0) { - error("ProcessCreatures: Kreatur %d existiert nicht.\n",i_00); - } - else { - iVar3 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0xe]); - if ((((iVar3 < 1) || - (uVar4 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0xe]), - RoundNr % uVar4 != 0)) || ((this->super_TCreature).IsDead != false)) || - (bVar1 = IsProtectionZone(), bVar1)) { -LAB_0809e093: - if ((this->super_TCreature).Type == PLAYER) { - CVar5 = PLAYER; - if ((this->super_TCreature).Connection != (TConnection *)0x0) { - TPlayer::CheckState(this); - CVar5 = (this->super_TCreature).Type; - } - if (((CVar5 == PLAYER) && - (uVar4 = (this->super_TCreature).EarliestLogoutRound, uVar4 != 0)) && - (uVar4 <= RoundNr)) { - TPlayer::ClearPlayerkillingMarks(this); - (this->super_TCreature).EarliestLogoutRound = 0; - } - } - } - else { - TSkill::Change((this->super_TCreature).super_TSkillBase.Skills[2],1); - TSkill::Change((this->super_TCreature).super_TSkillBase.Skills[3],4); - if ((this->super_TCreature).Type == PLAYER) { - SendPlayerData((this->super_TCreature).Connection); - goto LAB_0809e093; - } - } - if (((this->super_TCreature).IsDead == false) && - (iVar3 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[2]), - iVar3 < 1)) { - error("ProcessCreatures: Kreatur %s ist nicht tot, obwohl sie keine HP mehr hat.\n" - ,(this->super_TCreature).Name); - (*(this->super_TCreature)._vptr_TCreature[2])(this); - } - if (((this->super_TCreature).LoggingOut != false) && - (iVar3 = TCreature::LogoutPossible((TCreature *)this), iVar3 == 0)) { - if (((this->super_TCreature).IsDead != false) && - (iVar3 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[2]), - 0 < iVar3)) { - error("ProcessCreatures: Kreatur %s hat HP, obwohl sie tot ist.\n", - (this->super_TCreature).Name); - (*(this->super_TCreature).super_TSkillBase.Skills[2]->_vptr_TSkill[2]) - ((this->super_TCreature).super_TSkillBase.Skills[2],0); - } - if (this != (TPlayer *)0x0) { - (*(this->super_TCreature)._vptr_TCreature[1])(this); - } - i_00 = i_00 + -1; - } - } - i_00 = i_00 + 1; - } while (i_00 < FirstFreeCreature); - } - return; -} - - - -void MoveCreatures(int Delay) - -{ - uint uVar1; - ulong id; - bool Found; - TCreature *this; - priority_queue_entry<> *ppVar2; - ulong CreatureID; - ulong ExecutionTime; - - ServerMilliseconds = ServerMilliseconds + Delay; - while( true ) { - if (ToDoQueue.Entries == 0) { - return; - } - ppVar2 = vector<>::operator()(ToDoQueue.Entry,1); - uVar1 = ppVar2->Key; - ppVar2 = vector<>::operator()(ToDoQueue.Entry,1); - id = ppVar2->Data; - if (ServerMilliseconds < uVar1) break; - priority_queue<>::deleteMin(&ToDoQueue); - this = GetCreature(id); - if (this != (TCreature *)0x0) { - TCreature::Execute(this); - } - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: blockx - -void DeleteChainCreature(TCreature *cr) - -{ - ulong id; - matrix<> *pmVar1; - ulong ID; - uint uVar2; - uint uVar3; - int iVar4; - ulong *puVar5; - TCreature *pTVar6; - TCreature *Help; - int iVar7; - int blocky; - int blockx; - - pmVar1 = FirstChainCreature; - if (cr == (TCreature *)0x0) { - cr = (TCreature *)&DAT_08101a00; -LAB_0809e38b: - error((char *)cr); - return; - } - uVar2 = cr->posx; - if (0x7fffffff < uVar2) { - uVar2 = uVar2 + 0xf; - } - uVar3 = cr->posy; - if (0x7fffffff < uVar3) { - uVar3 = uVar3 + 0xf; - } - iVar4 = ((int)uVar3 >> 4) - FirstChainCreature->ymin; - iVar7 = ((int)uVar2 >> 4) - FirstChainCreature->xmin; - if ((((iVar7 < 0) || (FirstChainCreature->dx <= iVar7)) || (iVar4 < 0)) || - (FirstChainCreature->dy <= iVar4)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar7 + FirstChainCreature->xmin, - iVar4 + FirstChainCreature->ymin); - puVar5 = pmVar1->entry; - } - else { - puVar5 = FirstChainCreature->entry + iVar7 + iVar4 * FirstChainCreature->dx; - } - pmVar1 = FirstChainCreature; - id = *puVar5; - if (id == cr->ID) { - iVar4 = ((int)uVar3 >> 4) - FirstChainCreature->ymin; - iVar7 = ((int)uVar2 >> 4) - FirstChainCreature->xmin; - if (((iVar7 < 0) || (FirstChainCreature->dx <= iVar7)) || - ((iVar4 < 0 || (FirstChainCreature->dy <= iVar4)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar7 + FirstChainCreature->xmin, - iVar4 + FirstChainCreature->ymin); - puVar5 = pmVar1->entry; - } - else { - puVar5 = FirstChainCreature->entry + iVar7 + iVar4 * FirstChainCreature->dx; - } - *puVar5 = cr->NextChainCreature; - } - else { - do { - if (id == 0) { - cr = (TCreature *)s_DeleteChainCreature__Kreatur_nic_08101980; - goto LAB_0809e38b; - } - pTVar6 = GetCreature(id); - if (pTVar6 == (TCreature *)0x0) { - cr = (TCreature *)s_DeleteChainCreature__Kreatur_exi_081019c0; - goto LAB_0809e38b; - } - id = pTVar6->NextChainCreature; - } while (id != cr->ID); - pTVar6->NextChainCreature = cr->NextChainCreature; - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: cr_local - -void InsertChainCreature(TCreature *cr,int newx,int newy) - -{ - matrix<> *pmVar1; - int iVar2; - ulong *puVar3; - int iVar4; - int blocky; - int blockx; - TCreature *cr_local; - - pmVar1 = FirstChainCreature; - if (cr == (TCreature *)0x0) { - error(&DAT_08101a00); - return; - } - if (newx == 0) { - newx = cr->posx; - if (0x7fffffff < (uint)newx) { - newx = newx + 0xf; - } - } - else if (0x7fffffff < (uint)newx) { - newx = newx + 0xf; - } - if (newy == 0) { - newy = cr->posy; - if (0x7fffffff < (uint)newy) { - newy = newy + 0xf; - } - } - else if (0x7fffffff < (uint)newy) { - newy = newy + 0xf; - } - iVar2 = (newy >> 4) - FirstChainCreature->ymin; - iVar4 = (newx >> 4) - FirstChainCreature->xmin; - if ((((iVar4 < 0) || (FirstChainCreature->dx <= iVar4)) || (iVar2 < 0)) || - (FirstChainCreature->dy <= iVar2)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + FirstChainCreature->xmin, - iVar2 + FirstChainCreature->ymin); - puVar3 = pmVar1->entry; - } - else { - puVar3 = FirstChainCreature->entry + iVar4 + iVar2 * FirstChainCreature->dx; - } - cr->NextChainCreature = *puVar3; - pmVar1 = FirstChainCreature; - iVar2 = (newy >> 4) - FirstChainCreature->ymin; - iVar4 = (newx >> 4) - FirstChainCreature->xmin; - if (((iVar4 < 0) || (FirstChainCreature->dx <= iVar4)) || - ((iVar2 < 0 || (FirstChainCreature->dy <= iVar2)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + FirstChainCreature->xmin, - iVar2 + FirstChainCreature->ymin); - puVar3 = pmVar1->entry; - } - else { - puVar3 = FirstChainCreature->entry + iVar4 + iVar2 * FirstChainCreature->dx; - } - *puVar3 = cr->ID; - return; -} - - - -void MoveChainCreature(TCreature *cr,int newx,int newy) - -{ - uint uVar1; - int iVar2; - - if (cr == (TCreature *)0x0) { - error(&DAT_08101a00); - return; - } - uVar1 = cr->posx; - if (0x7fffffff < uVar1) { - uVar1 = uVar1 + 0xf; - } - iVar2 = newx + 0xf; - if (-1 < newx) { - iVar2 = newx; - } - if ((int)uVar1 >> 4 == iVar2 >> 4) { - uVar1 = cr->posy; - if (0x7fffffff < uVar1) { - uVar1 = uVar1 + 0xf; - } - iVar2 = newy + 0xf; - if (-1 < newy) { - iVar2 = newy; - } - if ((int)uVar1 >> 4 == iVar2 >> 4) { - return; - } - } - DeleteChainCreature(cr); - InsertChainCreature(cr,newx,newy); - return; -} - - - // DWARF original prototype: void TFindCreatures(TFindCreatures * this, int radx, int rady, int x, // int y, int Mask) @@ -30459,1088 +30095,6 @@ void ExitKillStatistics(void) return; } -// DWARF original prototype: void ~TCreature(TCreature * this, int __in_chrg) - -void __thiscall TCreature::~TCreature(TCreature *this,int __in_chrg) - -{ - TKnownCreature *pTVar1; - TToDoEntry *pTVar2; - bool bVar3; - bool bVar4; - RESULT r_2; - ObjectType *pOVar5; - TCreature **ppTVar6; - TCreature **ppTVar7; - long lVar8; - ulong Value; - RESULT r; - TKnownCreature *KnownCreature; - int iVar9; - int i_1; - Object *pOVar10; - char *in_stack_fffffef8; - char *__src; - Object local_ec; - char s [128]; - Object Corpse; - Object local_5c; - Object Obj; - ObjectType local_4c; - ObjectType CorpseType; - Object local_3c; - Object Obj_1; - Object local_2c [7]; - - this->_vptr_TCreature = (_func_int_varargs **)&PTR__TCreature_08127be8; - if (this->IsDead != false) { - iVar9 = this->Race; - if (RaceData[iVar9].Blood == BT_BLOOD) { - GetSpecialObject((SPECIALMEANING)local_2c); - local_4c.TypeID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (RaceData[iVar9].Blood == BT_SLIME) { - // try { // try from 0809f7ce to 0809f85d has its CatchHandler @ 0809f869 - GetSpecialObject((SPECIALMEANING)&local_4c); - local_2c[0].ObjectID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (this->Sex == 1) { - pOVar5 = &RaceData[iVar9].MaleCorpse; - } - else { - pOVar5 = &RaceData[iVar9].FemaleCorpse; - } - // try { // try from 0809f31c to 0809f4ab has its CatchHandler @ 0809f957 - ObjectType::setTypeID(&local_4c,pOVar5->TypeID); - bVar3 = ObjectType::getFlag(&local_4c,MAGICFIELD); - if (bVar3) { - GetFirstObject(); - local_5c = (Object)::NONE.ObjectID; - local_2c[0].ObjectID = local_5c.ObjectID; - if (local_3c.ObjectID != ::NONE.ObjectID) { - do { - local_5c.ObjectID = local_3c.ObjectID; - local_2c[0].ObjectID = ::NONE.ObjectID; - Object::getNextObject((Object *)(s + 0x7c)); - local_3c.ObjectID._0_1_ = s[0x7c]; - local_3c.ObjectID._1_1_ = s[0x7d]; - local_3c.ObjectID._2_1_ = s[0x7e]; - local_3c.ObjectID._3_1_ = s[0x7f]; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - Object::getObjectType((Object *)(s + 0x7c)); - bVar3 = ObjectType::getFlag((ObjectType *)(s + 0x7c),MAGICFIELD); - if (bVar3) { - s[0x7c] = (undefined1)local_5c.ObjectID; - s[0x7d] = local_5c.ObjectID._1_1_; - s[0x7e] = local_5c.ObjectID._2_1_; - s[0x7f] = local_5c.ObjectID._3_1_; - // try { // try from 0809f7a4 to 0809f7a8 has its CatchHandler @ 0809f8d4 - Delete((Object *)(s + 0x7c),-1); - } - local_2c[0].ObjectID = ::NONE.ObjectID; - local_5c.ObjectID = ::NONE.ObjectID; - } while (local_3c.ObjectID != ::NONE.ObjectID); - } - } - ObjectType::setTypeID((ObjectType *)&local_5c,local_4c.TypeID); - GetMapContainer((int)&local_3c,this->posx,this->posy); - Create((Object *)(s + 0x7c),(ObjectType *)&local_3c,(ulong)&local_5c); - in_stack_fffffef8 = "Tod von %s: LoseInventory=%d.\n"; - Log("game","Tod von %s: LoseInventory=%d.\n",this->Name,this->LoseInventory); - if (this->Type == PLAYER) { - sprintf((char *)&local_ec,"You recognize %s",this->Name); - if (this->Murderer[0] != '\0') { - if (this->Sex == 1) { - __src = ". He "; - } - else { - __src = ". She "; - } - strcat((char *)&local_ec,__src); - strcat((char *)&local_ec,"was killed by "); - strcat((char *)&local_ec,this->Murderer); - } - Value = AddDynamicString((char *)&local_ec); - in_stack_fffffef8 = (char *)0x9; - local_5c.ObjectID._0_1_ = s[0x7c]; - local_5c.ObjectID._1_1_ = s[0x7d]; - local_5c.ObjectID._2_1_ = s[0x7e]; - local_5c.ObjectID._3_1_ = s[0x7f]; - Change(&local_5c,TEXTSTRING,Value); - } - if (this->LoseInventory != 0) { - iVar9 = 1; - do { - in_stack_fffffef8 = (char *)this->ID; - GetBodyObject((ulong)&local_5c,(int)in_stack_fffffef8); - local_3c.ObjectID = ::NONE.ObjectID; - if (local_5c.ObjectID != ::NONE.ObjectID) { - if (this->LoseInventory != 2) { - Object::getObjectType(&local_3c); - bVar3 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER); - if (!bVar3) { - in_stack_fffffef8 = (char *)0x9; - // try { // try from 0809f63b to 0809f76e has its CatchHandler @ 0809f957 - lVar8 = random(); - if (lVar8 != 0) goto LAB_0809f487; - } - } - local_3c.ObjectID = ::NONE.ObjectID; - local_ec.ObjectID = local_5c.ObjectID; - in_stack_fffffef8 = (char *)&local_ec; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - ::Move(0,(Object *)in_stack_fffffef8,local_2c,-1,false,&local_3c); - } -LAB_0809f487: - iVar9 = iVar9 + 1; - } while (iVar9 < 0xb); - } - if ((this->Type == PLAYER) && (this->LoseInventory != 2)) { - TPlayer::SaveInventory((TPlayer *)this); - } - } - bVar3 = false; - local_ec.ObjectID = ::NONE.ObjectID; - s[0x7c] = (undefined1)::NONE.ObjectID; - s[0x7d] = ::NONE.ObjectID._1_1_; - s[0x7e] = ::NONE.ObjectID._2_1_; - s[0x7f] = ::NONE.ObjectID._3_1_; - if (((this->CrObject).ObjectID != ::NONE.ObjectID) && - (bVar4 = Object::exists(&this->CrObject), bVar4)) { - bVar3 = true; - } - if (bVar3) { - DelOnMap(this); - } - ToDoClear(this); - if ((this->Type == PLAYER) && (this->Connection != (TConnection *)0x0)) { - in_stack_fffffef8 = (char *)0x1e; - TConnection::Logout(this->Connection,0x1e,true); - } - pOVar10 = (Object *)0x0; - if (0 < FirstFreeCreature) { - do { - in_stack_fffffef8 = (char *)pOVar10; - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - if (*ppTVar6 == this) { - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - ppTVar7 = vector::operator()(&CreatureList,FirstFreeCreature + -1); - *ppTVar6 = *ppTVar7; - in_stack_fffffef8 = (char *)(FirstFreeCreature + -1); - ppTVar6 = vector::operator()(&CreatureList,(int)in_stack_fffffef8); - *ppTVar6 = (TCreature *)0x0; - FirstFreeCreature = FirstFreeCreature + -1; - } - pOVar10 = (Object *)((int)&pOVar10->ObjectID + 1); - } while ((int)pOVar10 < FirstFreeCreature); - } - if (this->ID != 0) { - DelID(this); - } - for (pTVar1 = this->FirstKnowingConnection; pTVar1 != (TKnownCreature *)0x0; - pTVar1 = pTVar1->Next) { - pOVar10 = (Object *)this->ID; - if ((Object *)pTVar1->CreatureID != pOVar10) { - error("TCreature::~TCreature: Verkettungsfehler bei Kreatur %lu.\n"); - in_stack_fffffef8 = (char *)pOVar10; - } - pTVar1->State = KNOWNCREATURE_FREE; - } - pTVar2 = (this->ToDoList).entry; - if (pTVar2 != (TToDoEntry *)0x0) { - operator_delete__(pTVar2); - } - TSkillBase::~TSkillBase(&this->super_TSkillBase,(int)in_stack_fffffef8); - return; -} - - - -// DWARF original prototype: void ~TCreature(TCreature * this, int __in_chrg) - -void __thiscall TCreature::~TCreature(TCreature *this,int __in_chrg) - -{ - TKnownCreature *pTVar1; - TToDoEntry *pTVar2; - bool bVar3; - bool bVar4; - RESULT r_2; - ObjectType *pOVar5; - TCreature **ppTVar6; - TCreature **ppTVar7; - long lVar8; - ulong Value; - RESULT r; - TKnownCreature *KnownCreature; - int iVar9; - int i_1; - Object *pOVar10; - char *in_stack_fffffef8; - char *__src; - Object local_ec; - char s [128]; - Object Corpse; - Object local_5c; - Object Obj; - ObjectType local_4c; - ObjectType CorpseType; - Object local_3c; - Object Obj_1; - Object local_2c [7]; - - this->_vptr_TCreature = (_func_int_varargs **)&PTR__TCreature_08127be8; - if (this->IsDead != false) { - iVar9 = this->Race; - if (RaceData[iVar9].Blood == BT_BLOOD) { - GetSpecialObject((SPECIALMEANING)local_2c); - local_4c.TypeID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (RaceData[iVar9].Blood == BT_SLIME) { - // try { // try from 0809fe8e to 0809ff1d has its CatchHandler @ 0809ff29 - GetSpecialObject((SPECIALMEANING)&local_4c); - local_2c[0].ObjectID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (this->Sex == 1) { - pOVar5 = &RaceData[iVar9].MaleCorpse; - } - else { - pOVar5 = &RaceData[iVar9].FemaleCorpse; - } - // try { // try from 0809f9dc to 0809fb6b has its CatchHandler @ 080a0017 - ObjectType::setTypeID(&local_4c,pOVar5->TypeID); - bVar3 = ObjectType::getFlag(&local_4c,MAGICFIELD); - if (bVar3) { - GetFirstObject(); - local_5c = (Object)::NONE.ObjectID; - local_2c[0].ObjectID = local_5c.ObjectID; - if (local_3c.ObjectID != ::NONE.ObjectID) { - do { - local_5c.ObjectID = local_3c.ObjectID; - local_2c[0].ObjectID = ::NONE.ObjectID; - Object::getNextObject((Object *)(s + 0x7c)); - local_3c.ObjectID._0_1_ = s[0x7c]; - local_3c.ObjectID._1_1_ = s[0x7d]; - local_3c.ObjectID._2_1_ = s[0x7e]; - local_3c.ObjectID._3_1_ = s[0x7f]; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - Object::getObjectType((Object *)(s + 0x7c)); - bVar3 = ObjectType::getFlag((ObjectType *)(s + 0x7c),MAGICFIELD); - if (bVar3) { - s[0x7c] = (undefined1)local_5c.ObjectID; - s[0x7d] = local_5c.ObjectID._1_1_; - s[0x7e] = local_5c.ObjectID._2_1_; - s[0x7f] = local_5c.ObjectID._3_1_; - // try { // try from 0809fe64 to 0809fe68 has its CatchHandler @ 0809ff94 - Delete((Object *)(s + 0x7c),-1); - } - local_2c[0].ObjectID = ::NONE.ObjectID; - local_5c.ObjectID = ::NONE.ObjectID; - } while (local_3c.ObjectID != ::NONE.ObjectID); - } - } - ObjectType::setTypeID((ObjectType *)&local_5c,local_4c.TypeID); - GetMapContainer((int)&local_3c,this->posx,this->posy); - Create((Object *)(s + 0x7c),(ObjectType *)&local_3c,(ulong)&local_5c); - in_stack_fffffef8 = "Tod von %s: LoseInventory=%d.\n"; - Log("game","Tod von %s: LoseInventory=%d.\n",this->Name,this->LoseInventory); - if (this->Type == PLAYER) { - sprintf((char *)&local_ec,"You recognize %s",this->Name); - if (this->Murderer[0] != '\0') { - if (this->Sex == 1) { - __src = ". He "; - } - else { - __src = ". She "; - } - strcat((char *)&local_ec,__src); - strcat((char *)&local_ec,"was killed by "); - strcat((char *)&local_ec,this->Murderer); - } - Value = AddDynamicString((char *)&local_ec); - in_stack_fffffef8 = (char *)0x9; - local_5c.ObjectID._0_1_ = s[0x7c]; - local_5c.ObjectID._1_1_ = s[0x7d]; - local_5c.ObjectID._2_1_ = s[0x7e]; - local_5c.ObjectID._3_1_ = s[0x7f]; - Change(&local_5c,TEXTSTRING,Value); - } - if (this->LoseInventory != 0) { - iVar9 = 1; - do { - in_stack_fffffef8 = (char *)this->ID; - GetBodyObject((ulong)&local_5c,(int)in_stack_fffffef8); - local_3c.ObjectID = ::NONE.ObjectID; - if (local_5c.ObjectID != ::NONE.ObjectID) { - if (this->LoseInventory != 2) { - Object::getObjectType(&local_3c); - bVar3 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER); - if (!bVar3) { - in_stack_fffffef8 = (char *)0x9; - // try { // try from 0809fcfb to 0809fe2e has its CatchHandler @ 080a0017 - lVar8 = random(); - if (lVar8 != 0) goto LAB_0809fb47; - } - } - local_3c.ObjectID = ::NONE.ObjectID; - local_ec.ObjectID = local_5c.ObjectID; - in_stack_fffffef8 = (char *)&local_ec; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - ::Move(0,(Object *)in_stack_fffffef8,local_2c,-1,false,&local_3c); - } -LAB_0809fb47: - iVar9 = iVar9 + 1; - } while (iVar9 < 0xb); - } - if ((this->Type == PLAYER) && (this->LoseInventory != 2)) { - TPlayer::SaveInventory((TPlayer *)this); - } - } - bVar3 = false; - local_ec.ObjectID = ::NONE.ObjectID; - s[0x7c] = (undefined1)::NONE.ObjectID; - s[0x7d] = ::NONE.ObjectID._1_1_; - s[0x7e] = ::NONE.ObjectID._2_1_; - s[0x7f] = ::NONE.ObjectID._3_1_; - if (((this->CrObject).ObjectID != ::NONE.ObjectID) && - (bVar4 = Object::exists(&this->CrObject), bVar4)) { - bVar3 = true; - } - if (bVar3) { - DelOnMap(this); - } - ToDoClear(this); - if ((this->Type == PLAYER) && (this->Connection != (TConnection *)0x0)) { - in_stack_fffffef8 = (char *)0x1e; - TConnection::Logout(this->Connection,0x1e,true); - } - pOVar10 = (Object *)0x0; - if (0 < FirstFreeCreature) { - do { - in_stack_fffffef8 = (char *)pOVar10; - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - if (*ppTVar6 == this) { - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - ppTVar7 = vector::operator()(&CreatureList,FirstFreeCreature + -1); - *ppTVar6 = *ppTVar7; - in_stack_fffffef8 = (char *)(FirstFreeCreature + -1); - ppTVar6 = vector::operator()(&CreatureList,(int)in_stack_fffffef8); - *ppTVar6 = (TCreature *)0x0; - FirstFreeCreature = FirstFreeCreature + -1; - } - pOVar10 = (Object *)((int)&pOVar10->ObjectID + 1); - } while ((int)pOVar10 < FirstFreeCreature); - } - if (this->ID != 0) { - DelID(this); - } - for (pTVar1 = this->FirstKnowingConnection; pTVar1 != (TKnownCreature *)0x0; - pTVar1 = pTVar1->Next) { - pOVar10 = (Object *)this->ID; - if ((Object *)pTVar1->CreatureID != pOVar10) { - error("TCreature::~TCreature: Verkettungsfehler bei Kreatur %lu.\n"); - in_stack_fffffef8 = (char *)pOVar10; - } - pTVar1->State = KNOWNCREATURE_FREE; - } - pTVar2 = (this->ToDoList).entry; - if (pTVar2 != (TToDoEntry *)0x0) { - operator_delete__(pTVar2); - } - TSkillBase::~TSkillBase(&this->super_TSkillBase,(int)in_stack_fffffef8); - return; -} - - - -// DWARF original prototype: void ~TCreature(TCreature * this, int __in_chrg) - -void __thiscall TCreature::~TCreature(TCreature *this,int __in_chrg) - -{ - TKnownCreature *pTVar1; - TToDoEntry *pTVar2; - bool bVar3; - bool bVar4; - RESULT r_2; - ObjectType *pOVar5; - TCreature **ppTVar6; - TCreature **ppTVar7; - long lVar8; - ulong Value; - RESULT r; - TKnownCreature *KnownCreature; - int iVar9; - int i_1; - Object *pOVar10; - char *in_stack_fffffef8; - char *__src; - Object local_ec; - char s [128]; - Object Corpse; - Object local_5c; - Object Obj; - ObjectType local_4c; - ObjectType CorpseType; - Object local_3c; - Object Obj_1; - Object local_2c [7]; - - this->_vptr_TCreature = (_func_int_varargs **)&PTR__TCreature_08127be8; - if (this->IsDead != false) { - iVar9 = this->Race; - if (RaceData[iVar9].Blood == BT_BLOOD) { - GetSpecialObject((SPECIALMEANING)local_2c); - local_4c.TypeID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (RaceData[iVar9].Blood == BT_SLIME) { - // try { // try from 080a054e to 080a05dd has its CatchHandler @ 080a05e9 - GetSpecialObject((SPECIALMEANING)&local_4c); - local_2c[0].ObjectID = (this->CrObject).ObjectID; - GetMapContainer(&local_3c); - CreatePool(); - iVar9 = this->Race; - } - if (this->Sex == 1) { - pOVar5 = &RaceData[iVar9].MaleCorpse; - } - else { - pOVar5 = &RaceData[iVar9].FemaleCorpse; - } - // try { // try from 080a009c to 080a022b has its CatchHandler @ 080a06d7 - ObjectType::setTypeID(&local_4c,pOVar5->TypeID); - bVar3 = ObjectType::getFlag(&local_4c,MAGICFIELD); - if (bVar3) { - GetFirstObject(); - local_5c = (Object)::NONE.ObjectID; - local_2c[0].ObjectID = local_5c.ObjectID; - if (local_3c.ObjectID != ::NONE.ObjectID) { - do { - local_5c.ObjectID = local_3c.ObjectID; - local_2c[0].ObjectID = ::NONE.ObjectID; - Object::getNextObject((Object *)(s + 0x7c)); - local_3c.ObjectID._0_1_ = s[0x7c]; - local_3c.ObjectID._1_1_ = s[0x7d]; - local_3c.ObjectID._2_1_ = s[0x7e]; - local_3c.ObjectID._3_1_ = s[0x7f]; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - Object::getObjectType((Object *)(s + 0x7c)); - bVar3 = ObjectType::getFlag((ObjectType *)(s + 0x7c),MAGICFIELD); - if (bVar3) { - s[0x7c] = (undefined1)local_5c.ObjectID; - s[0x7d] = local_5c.ObjectID._1_1_; - s[0x7e] = local_5c.ObjectID._2_1_; - s[0x7f] = local_5c.ObjectID._3_1_; - // try { // try from 080a0524 to 080a0528 has its CatchHandler @ 080a0654 - Delete((Object *)(s + 0x7c),-1); - } - local_2c[0].ObjectID = ::NONE.ObjectID; - local_5c.ObjectID = ::NONE.ObjectID; - } while (local_3c.ObjectID != ::NONE.ObjectID); - } - } - ObjectType::setTypeID((ObjectType *)&local_5c,local_4c.TypeID); - GetMapContainer((int)&local_3c,this->posx,this->posy); - Create((Object *)(s + 0x7c),(ObjectType *)&local_3c,(ulong)&local_5c); - in_stack_fffffef8 = "Tod von %s: LoseInventory=%d.\n"; - Log("game","Tod von %s: LoseInventory=%d.\n",this->Name,this->LoseInventory); - if (this->Type == PLAYER) { - sprintf((char *)&local_ec,"You recognize %s",this->Name); - if (this->Murderer[0] != '\0') { - if (this->Sex == 1) { - __src = ". He "; - } - else { - __src = ". She "; - } - strcat((char *)&local_ec,__src); - strcat((char *)&local_ec,"was killed by "); - strcat((char *)&local_ec,this->Murderer); - } - Value = AddDynamicString((char *)&local_ec); - in_stack_fffffef8 = (char *)0x9; - local_5c.ObjectID._0_1_ = s[0x7c]; - local_5c.ObjectID._1_1_ = s[0x7d]; - local_5c.ObjectID._2_1_ = s[0x7e]; - local_5c.ObjectID._3_1_ = s[0x7f]; - Change(&local_5c,TEXTSTRING,Value); - } - if (this->LoseInventory != 0) { - iVar9 = 1; - do { - in_stack_fffffef8 = (char *)this->ID; - GetBodyObject((ulong)&local_5c,(int)in_stack_fffffef8); - local_3c.ObjectID = ::NONE.ObjectID; - if (local_5c.ObjectID != ::NONE.ObjectID) { - if (this->LoseInventory != 2) { - Object::getObjectType(&local_3c); - bVar3 = ObjectType::getFlag((ObjectType *)&local_3c,CONTAINER); - if (!bVar3) { - in_stack_fffffef8 = (char *)0x9; - // try { // try from 080a03bc to 080a04ee has its CatchHandler @ 080a06d7 - lVar8 = random(); - if (lVar8 != 0) goto LAB_080a0207; - } - } - local_3c.ObjectID = ::NONE.ObjectID; - local_ec.ObjectID = local_5c.ObjectID; - in_stack_fffffef8 = (char *)&local_ec; - local_2c[0].ObjectID._0_1_ = s[0x7c]; - local_2c[0].ObjectID._1_1_ = s[0x7d]; - local_2c[0].ObjectID._2_1_ = s[0x7e]; - local_2c[0].ObjectID._3_1_ = s[0x7f]; - ::Move(0,(Object *)in_stack_fffffef8,local_2c,-1,false,&local_3c); - } -LAB_080a0207: - iVar9 = iVar9 + 1; - } while (iVar9 < 0xb); - } - if ((this->Type == PLAYER) && (this->LoseInventory != 2)) { - TPlayer::SaveInventory((TPlayer *)this); - } - } - bVar3 = false; - local_ec.ObjectID = ::NONE.ObjectID; - s[0x7c] = (undefined1)::NONE.ObjectID; - s[0x7d] = ::NONE.ObjectID._1_1_; - s[0x7e] = ::NONE.ObjectID._2_1_; - s[0x7f] = ::NONE.ObjectID._3_1_; - if (((this->CrObject).ObjectID != ::NONE.ObjectID) && - (bVar4 = Object::exists(&this->CrObject), bVar4)) { - bVar3 = true; - } - if (bVar3) { - DelOnMap(this); - } - ToDoClear(this); - if ((this->Type == PLAYER) && (this->Connection != (TConnection *)0x0)) { - in_stack_fffffef8 = (char *)0x1e; - TConnection::Logout(this->Connection,0x1e,true); - } - pOVar10 = (Object *)0x0; - if (0 < FirstFreeCreature) { - do { - in_stack_fffffef8 = (char *)pOVar10; - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - if (*ppTVar6 == this) { - ppTVar6 = vector::operator()(&CreatureList,(int)pOVar10); - ppTVar7 = vector::operator()(&CreatureList,FirstFreeCreature + -1); - *ppTVar6 = *ppTVar7; - in_stack_fffffef8 = (char *)(FirstFreeCreature + -1); - ppTVar6 = vector::operator()(&CreatureList,(int)in_stack_fffffef8); - *ppTVar6 = (TCreature *)0x0; - FirstFreeCreature = FirstFreeCreature + -1; - } - pOVar10 = (Object *)((int)&pOVar10->ObjectID + 1); - } while ((int)pOVar10 < FirstFreeCreature); - } - if (this->ID != 0) { - DelID(this); - } - for (pTVar1 = this->FirstKnowingConnection; pTVar1 != (TKnownCreature *)0x0; - pTVar1 = pTVar1->Next) { - pOVar10 = (Object *)this->ID; - if ((Object *)pTVar1->CreatureID != pOVar10) { - error("TCreature::~TCreature: Verkettungsfehler bei Kreatur %lu.\n"); - in_stack_fffffef8 = (char *)pOVar10; - } - pTVar1->State = KNOWNCREATURE_FREE; - } - pTVar2 = (this->ToDoList).entry; - if (pTVar2 != (TToDoEntry *)0x0) { - operator_delete__(pTVar2); - } - TSkillBase::~TSkillBase(&this->super_TSkillBase,(int)in_stack_fffffef8); - operator_delete(this); - return; -} - - - -// DWARF original prototype: void SetID(TCreature * this, ulong CharacterID) - -void __thiscall TCreature::SetID(TCreature *this,ulong CharacterID) - -{ - TCreature *pTVar1; - ulong m; - uint uVar2; - int iVar3; - char *Text; - ulong uVar4; - - if (this->ID != 0) { - error("TCreature::SetID: ID ist schon gesetzt.\n"); - } - if (CharacterID == 0) { - iVar3 = 0; - this->ID = NextCreatureID; - NextCreatureID = NextCreatureID + 1; - do { - pTVar1 = GetCreature(this->ID); - if (pTVar1 == (TCreature *)0x0) goto LAB_080a0775; - iVar3 = iVar3 + 1; - error("TCreature::SetID: Doppelte Nonplayer-ID %d gefunden.\n",this->ID); - this->ID = NextCreatureID; - NextCreatureID = NextCreatureID + 1; - } while (iVar3 < 0x11); - uVar4 = this->ID; - Text = "TCreature::SetID: 16x hintereinander doppelte ID. Verwende nun doppelte ID %d\n"; - } - else { - this->ID = CharacterID; - pTVar1 = GetCreature(CharacterID); - if (pTVar1 == (TCreature *)0x0) goto LAB_080a0775; - uVar4 = this->ID; - Text = "TCreature::SetID: Doppelte Character-ID %d gefunden.\n"; - } - error(Text,uVar4); -LAB_080a0775: - uVar2 = this->ID % 1000; - this->NextHashEntry = HashList[uVar2]; - HashList[uVar2] = this; - return; -} - - - -// DWARF original prototype: void DelID(TCreature * this) - -void __thiscall TCreature::DelID(TCreature *this) - -{ - uint uVar1; - TCreature *pTVar2; - uint uVar3; - TCreature *pTVar4; - TCreature *pTVar5; - ulong m; - TCreature *ocr; - TCreature *pTVar6; - char *Text; - - uVar1 = this->ID; - pTVar2 = HashList[uVar1 % 1000]; - if (pTVar2 == (TCreature *)0x0) { - Text = "TCreature::DelID: Hasheintrag nicht gefunden id = %d\n"; - } - else { - uVar3 = pTVar2->ID; - if (uVar3 == uVar1) { - HashList[uVar1 % 1000] = pTVar2->NextHashEntry; - return; - } - pTVar4 = pTVar2->NextHashEntry; - pTVar6 = (TCreature *)0x0; - while (pTVar4 != (TCreature *)0x0) { - pTVar5 = pTVar2->NextHashEntry; - uVar3 = pTVar5->ID; - pTVar6 = pTVar2; - if (uVar3 == uVar1) goto LAB_080a0867; - pTVar2 = pTVar5; - pTVar4 = pTVar5->NextHashEntry; - } - pTVar5 = pTVar2; - if (uVar3 == uVar1) { -LAB_080a0867: - pTVar6->NextHashEntry = pTVar5->NextHashEntry; - return; - } - Text = "TCreature::DelID: id=%d nicht gefunden.\n"; - } - error(Text,uVar1); - return; -} - - - -// DWARF original prototype: void SetInCrList(TCreature * this) - -void __thiscall TCreature::SetInCrList(TCreature *this) - -{ - TCreature **ppTVar1; - - ppTVar1 = vector::operator()(&CreatureList,FirstFreeCreature); - FirstFreeCreature = FirstFreeCreature + 1; - *ppTVar1 = this; - return; -} - - - -// DWARF original prototype: void DelInCrList(TCreature * this) - -void __thiscall TCreature::DelInCrList(TCreature *this) - -{ - TCreature **ppTVar1; - TCreature **ppTVar2; - int i; - int i_00; - - i_00 = 0; - if (0 < FirstFreeCreature) { - do { - ppTVar1 = vector::operator()(&CreatureList,i_00); - if (*ppTVar1 == this) { - ppTVar1 = vector::operator()(&CreatureList,i_00); - ppTVar2 = vector::operator()(&CreatureList,FirstFreeCreature + -1); - *ppTVar1 = *ppTVar2; - ppTVar1 = vector::operator()(&CreatureList,FirstFreeCreature + -1); - *ppTVar1 = (TCreature *)0x0; - FirstFreeCreature = FirstFreeCreature + -1; - } - i_00 = i_00 + 1; - } while (i_00 < FirstFreeCreature); - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: StopFight_local -// DWARF original prototype: void StartLogout(TCreature * this, bool Force, bool StopFight) - -void __thiscall TCreature::StartLogout(TCreature *this,bool Force,bool StopFight) - -{ - bool bVar1; - int Delay; - bool StopFight_local; - - this->LoggingOut = true; - if ((Force) || (bVar1 = LagDetected(), bVar1)) { - this->LogoutAllowed = true; - } - if ((this->Type == PLAYER) && (this->Connection != (TConnection *)0x0)) { - TConnection::Logout(this->Connection,0,true); - } - Delay = 0; - if (!StopFight) { - Delay = 0x3c; - } - TCombat::StopAttack(&this->Combat,Delay); - return; -} - - - -// DWARF original prototype: int LogoutPossible(TCreature * this) - -int __thiscall TCreature::LogoutPossible(TCreature *this) - -{ - bool bVar1; - - if (((this->LogoutAllowed == false) && (bVar1 = GameEnding(), !bVar1)) && - (this->IsDead == false)) { - if ((RoundNr < this->EarliestLogoutRound) && (bVar1 = LagDetected(), !bVar1)) { - return 1; - } - bVar1 = IsNoLogoutField(); - if (bVar1) { - return 2; - } - this->LogoutAllowed = true; - } - return 0; -} - - - -// WARNING: Variable defined which should be unmapped: BlockProtectionZone_local -// DWARF original prototype: void BlockLogout(TCreature * this, int Delay, bool BlockProtectionZone) - -void __thiscall TCreature::BlockLogout(TCreature *this,int Delay,bool BlockProtectionZone) - -{ - uint uVar1; - bool bVar2; - ulong Round; - uint uVar3; - char local_d; - bool BlockProtectionZone_local; - - local_d = BlockProtectionZone; - if (WorldType == NON_PVP) { - local_d = '\0'; - } - if ((this->Type == PLAYER) && (bVar2 = CheckRight(this->ID,NO_LOGOUT_BLOCK), !bVar2)) { - if (local_d == '\0') { - uVar3 = this->EarliestProtectionZoneRound; - if (((uVar3 < RoundNr) && (this->Type == PLAYER)) && - (this->Connection == (TConnection *)0x0)) { - return; - } - } - else { - uVar3 = this->EarliestProtectionZoneRound; - } - uVar1 = Delay + RoundNr; - if (((local_d != '\0') || (RoundNr < uVar3)) && (uVar3 < uVar1)) { - this->EarliestProtectionZoneRound = uVar1; - } - if (this->EarliestLogoutRound < uVar1) { - this->EarliestLogoutRound = uVar1; - } - TPlayer::CheckState((TPlayer *)this); - return; - } - return; -} - - - -// DWARF original prototype: int GetHealth(TCreature * this) - -int __thiscall TCreature::GetHealth(TCreature *this) - -{ - TSkill *this_00; - int iVar1; - uint uVar2; - int iVar3; - int MaxHitpoints; - TSkill *sk; - - this_00 = (this->super_TSkillBase).Skills[2]; - iVar3 = this_00->Max; - if (iVar3 < 1) { - if (this->IsDead == false) { - error("TCreature::GetHealth: MaxHitpoints von %s ist %d, obwohl sie nicht tot ist.\n", - this->Name,iVar3); - } - uVar2 = 0; - } - else { - iVar1 = TSkill::Get(this_00); - uVar2 = (iVar1 * 100) / iVar3; - if ((int)uVar2 < 1) { - iVar3 = TSkill::Get(this_00); - uVar2 = (uint)(iVar3 != 0); - } - } - return uVar2; -} - - - -// DWARF original prototype: int GetSpeed(TCreature * this) - -int __thiscall TCreature::GetSpeed(TCreature *this) - -{ - TSkill *this_00; - int iVar1; - - this_00 = (this->super_TSkillBase).Skills[4]; - if (this_00 == (TSkill *)0x0) { - error("TCreature::GetSpeed: Kein Skill GOSTRENGTH vorhanden.\n"); - iVar1 = 0; - } - else { - iVar1 = TSkill::Get(this_00); - iVar1 = iVar1 * 2 + 0x50; - } - return iVar1; -} - - - -// DWARF original prototype: void Death(TCreature * this) - -void __thiscall TCreature::Death(TCreature *this) - -{ - this->IsDead = true; - this->LoggingOut = true; - return; -} - -// WARNING: Variable defined which should be unmapped: Execute_local -// DWARF original prototype: bool MovePossible(TCreature * this, int x, int y, int z, bool Execute, -// bool Jump) - -bool __thiscall TCreature::MovePossible(TCreature *this,int x,int y,int z,bool Execute,bool Jump) - -{ - bool bVar1; - bool local_18; - bool Execute_local; - - if (Jump) { - local_18 = JumpPossible(x,y,z,false); - } - else { - local_18 = false; - // try { // try from 080a2053 to 080a20dd has its CatchHandler @ 080a20e7 - bVar1 = CoordinateFlag(); - if (bVar1) { - local_18 = CoordinateFlag(); - local_18 = !local_18; - } - } - bVar1 = false; - if (local_18 != false) { - if ((!Execute) && (bVar1 = CoordinateFlag(), bVar1)) { - return false; - } - bVar1 = true; - } - return bVar1; -} - - - -// DWARF original prototype: void TRaceData(TRaceData * this) - -void __thiscall TRaceData::TRaceData(TRaceData *this) - -{ - int i; - int iVar1; - - ObjectType::setTypeID(&this->MaleCorpse,0); - ObjectType::setTypeID(&this->FemaleCorpse,0); - vector::vector(&this->Skill,1,5,5); - // try { // try from 080a2181 to 080a2185 has its CatchHandler @ 080a22e4 - vector<>::vector(&this->Talk,1,5,5,0); - // try { // try from 080a21a7 to 080a21ab has its CatchHandler @ 080a22e0 - vector::vector(&this->Item,1,5,5); - // try { // try from 080a21cd to 080a21d1 has its CatchHandler @ 080a22a0 - vector::vector(&this->Spell,1,5,5); - this->Name[0] = '\0'; - iVar1 = 1; - this->Article[0] = '\0'; - (this->Outfit).OutfitID = 0; - (this->Outfit).field_1 = (anon_union_4_2_730cd3ca_for_TOutfit_2)0x0; - this->Blood = BT_BLOOD; - this->ExperiencePoints = 0; - this->FleeThreshold = 0; - this->Attack = 0; - this->Defend = 0; - this->Armor = 0; - this->Poison = 0; - this->SummonCost = 0; - this->LoseTarget = 0; - this->Strategy[0] = 100; - do { - this->Strategy[iVar1] = 0; - iVar1 = iVar1 + 1; - } while (iVar1 < 4); - this->KickBoxes = false; - this->KickCreatures = false; - this->SeeInvisible = false; - this->Unpushable = false; - this->DistanceFighting = false; - this->NoSummon = false; - this->NoIllusion = false; - this->NoConvince = false; - this->NoBurning = false; - this->NoPoison = false; - this->NoEnergy = false; - this->NoHit = false; - this->NoLifeDrain = false; - this->NoParalyze = false; - this->Skills = 0; - this->Talks = 0; - this->Items = 0; - this->Spells = 0; - return; -} - - - -// DWARF original prototype: void TRaceData(TRaceData * this) - -void __thiscall TRaceData::TRaceData(TRaceData *this) - -{ - int i; - int iVar1; - - ObjectType::setTypeID(&this->MaleCorpse,0); - ObjectType::setTypeID(&this->FemaleCorpse,0); - vector::vector(&this->Skill,1,5,5); - // try { // try from 080a2371 to 080a2375 has its CatchHandler @ 080a24d4 - vector<>::vector(&this->Talk,1,5,5,0); - // try { // try from 080a2397 to 080a239b has its CatchHandler @ 080a24d0 - vector::vector(&this->Item,1,5,5); - // try { // try from 080a23bd to 080a23c1 has its CatchHandler @ 080a2490 - vector::vector(&this->Spell,1,5,5); - this->Name[0] = '\0'; - iVar1 = 1; - this->Article[0] = '\0'; - (this->Outfit).OutfitID = 0; - (this->Outfit).field_1 = (anon_union_4_2_730cd3ca_for_TOutfit_2)0x0; - this->Blood = BT_BLOOD; - this->ExperiencePoints = 0; - this->FleeThreshold = 0; - this->Attack = 0; - this->Defend = 0; - this->Armor = 0; - this->Poison = 0; - this->SummonCost = 0; - this->LoseTarget = 0; - this->Strategy[0] = 100; - do { - this->Strategy[iVar1] = 0; - iVar1 = iVar1 + 1; - } while (iVar1 < 4); - this->KickBoxes = false; - this->KickCreatures = false; - this->SeeInvisible = false; - this->Unpushable = false; - this->DistanceFighting = false; - this->NoSummon = false; - this->NoIllusion = false; - this->NoConvince = false; - this->NoBurning = false; - this->NoPoison = false; - this->NoEnergy = false; - this->NoHit = false; - this->NoLifeDrain = false; - this->NoParalyze = false; - this->Skills = 0; - this->Talks = 0; - this->Items = 0; - this->Spells = 0; - return; -} - - - char * GetRaceName(int Race) { @@ -33734,64 +32288,6 @@ LAB_080a4d67: } while( true ); } - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void InitCr(void) - -{ - int i; - matrix<> *this; - int iVar1; - - // try { // try from 080a5106 to 080a510a has its CatchHandler @ 080a51e0 - this = (matrix<> *)operator_new(0x14); - // try { // try from 080a5148 to 080a514c has its CatchHandler @ 080a51b0 - matrix<>::matrix(this,SectorXMin * 2,SectorXMax * 2 + 1,SectorYMin * 2,SectorYMax * 2 + 1,0); - NextCreatureID = 0x40000000; - FirstChainCreature = this; - // try { // try from 080a515d to 080a517c has its CatchHandler @ 080a51e0 - LoadRaces(); - LoadMonsterRaids(); - FirstFreeCreature = 0; - InitPlayer(); - InitCrskill(); - InitNonplayer(); - iVar1 = 0; - do { - KilledCreatures[iVar1] = 0; - KilledPlayers[iVar1] = 0; - iVar1 = iVar1 + 1; - } while (iVar1 < 0x200); - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void ExitCr(void) - -{ - matrix<> *pmVar1; - - WriteKillStatistics(); - ExitPlayer(); - ExitNonplayer(); - ExitCrskill(); - pmVar1 = FirstChainCreature; - if (FirstChainCreature != (matrix<> *)0x0) { - if (FirstChainCreature->entry != (ulong *)0x0) { - operator_delete__(FirstChainCreature->entry); - } - operator_delete(pmVar1); - } - return; -} - - - void __tcf_0(void *param_1) { @@ -33880,67 +32376,6 @@ void _GLOBAL__I_HashList(void) return; } - - -// DWARF original prototype: bool IsPeaceful(TCreature * this) - -bool __thiscall TCreature::IsPeaceful(TCreature *this) - -{ - return true; -} - - - -// DWARF original prototype: ulong GetMaster(TCreature * this) - -ulong __thiscall TCreature::GetMaster(TCreature *this) - -{ - return 0; -} - - - -// DWARF original prototype: void TalkStimulus(TCreature * this, ulong param_1, char * param_2) - -void __thiscall TCreature::TalkStimulus(TCreature *this,ulong param_1,char *param_2) - -{ - return; -} - - - -// DWARF original prototype: void DamageStimulus(TCreature * this, ulong param_1, int param_2, int -// param_3) - -void __thiscall TCreature::DamageStimulus(TCreature *this,ulong param_1,int param_2,int param_3) - -{ - return; -} - - - -// DWARF original prototype: void IdleStimulus(TCreature * this) - -void __thiscall TCreature::IdleStimulus(TCreature *this) - -{ - return; -} - - - -// DWARF original prototype: void AttackStimulus(TCreature * this, ulong param_1) - -void __thiscall TCreature::AttackStimulus(TCreature *this,ulong param_1) - -{ - return; -} - void __static_initialization_and_destruction_0(int __initialize_p,int __priority) { @@ -47534,763 +45969,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -// DWARF original prototype: void TShortway(TShortway * this, TCreature * cr, int VisibleX, int -// VisibleY) - -void __thiscall TShortway::TShortway(TShortway *this,TCreature *cr,int VisibleX,int VisibleY) - -{ - matrix<> *this_00; - - this->Map = (matrix<> *)0x0; - if (cr == (TCreature *)0x0) { - error(&DAT_08106b80); - return; - } - if ((((0 < VisibleX) && (0 < VisibleY)) && (VisibleX < 0x65)) && (VisibleY < 0x65)) { - this->cr = cr; - this->VisibleX = VisibleX; - this->VisibleY = VisibleY; - this->StartX = cr->posx; - this->StartY = cr->posy; - this->StartZ = cr->posz; - this_00 = (matrix<> *)operator_new(0x14); - // try { // try from 080bdfe3 to 080bdfe7 has its CatchHandler @ 080be019 - matrix<>::matrix(this_00,~VisibleX,VisibleX + 1,~VisibleY,VisibleY + 1); - this->Map = this_00; - FillMap(this); - return; - } - error(&DAT_08106b40); - return; -} - - - -// DWARF original prototype: void TShortway(TShortway * this, TCreature * cr, int VisibleX, int -// VisibleY) - -void __thiscall TShortway::TShortway(TShortway *this,TCreature *cr,int VisibleX,int VisibleY) - -{ - matrix<> *this_00; - - this->Map = (matrix<> *)0x0; - if (cr == (TCreature *)0x0) { - error(&DAT_08106b80); - return; - } - if ((((0 < VisibleX) && (0 < VisibleY)) && (VisibleX < 0x65)) && (VisibleY < 0x65)) { - this->cr = cr; - this->VisibleX = VisibleX; - this->VisibleY = VisibleY; - this->StartX = cr->posx; - this->StartY = cr->posy; - this->StartZ = cr->posz; - this_00 = (matrix<> *)operator_new(0x14); - // try { // try from 080be0f3 to 080be0f7 has its CatchHandler @ 080be129 - matrix<>::matrix(this_00,~VisibleX,VisibleX + 1,~VisibleY,VisibleY + 1); - this->Map = this_00; - FillMap(this); - return; - } - error(&DAT_08106b40); - return; -} - - - -// DWARF original prototype: void ~TShortway(TShortway * this, int __in_chrg) - -void __thiscall TShortway::~TShortway(TShortway *this,int __in_chrg) - -{ - matrix<> *pmVar1; - - pmVar1 = this->Map; - if (pmVar1 != (matrix<> *)0x0) { - if (pmVar1->entry != (TShortwayPoint *)0x0) { - operator_delete__(pmVar1->entry); - } - operator_delete(pmVar1); - return; - } - return; -} - - - -// DWARF original prototype: void ~TShortway(TShortway * this, int __in_chrg) - -void __thiscall TShortway::~TShortway(TShortway *this,int __in_chrg) - -{ - matrix<> *pmVar1; - - pmVar1 = this->Map; - if (pmVar1 != (matrix<> *)0x0) { - if (pmVar1->entry != (TShortwayPoint *)0x0) { - operator_delete__(pmVar1->entry); - } - operator_delete(pmVar1); - return; - } - return; -} - - - -// DWARF original prototype: void FillMap(TShortway * this) - -void __thiscall TShortway::FillMap(TShortway *this) - -{ - matrix<> *pmVar1; - bool bVar2; - int iVar3; - int iVar4; - TShortwayPoint *pTVar5; - ulong uVar6; - uint uVar7; - int iVar8; - uint uVar9; - int x_1; - uint uVar10; - int y; - int iVar11; - ulong local_44; - int Waypoints; - int x; - Object local_2c; - Object Obj; - - this->MinWaypoints = 1000; - uVar7 = this->VisibleX; - Waypoints = -uVar7; - if (-uVar7 == uVar7 || SBORROW4(Waypoints,uVar7) != (int)(uVar7 * -2) < 0) { - uVar9 = this->VisibleY; - do { - iVar11 = -uVar9; - if (-uVar9 == uVar9 || iVar11 < (int)uVar9) { - do { - local_44 = 0xffffffff; - iVar4 = this->StartZ; - GetFirstObject(); - bVar2 = Object::exists(&local_2c); - if (bVar2) { - Object::getObjectType((Object *)&x); - bVar2 = ObjectType::getFlag((ObjectType *)&x,BANK); - if (bVar2) { - Object::getObjectType((Object *)&x); - bVar2 = ObjectType::getFlag((ObjectType *)&x,UNPASS); - if (!bVar2) { - Object::getObjectType((Object *)&x); - local_44 = ObjectType::getAttribute((ObjectType *)&x,WAYPOINTS); - if (local_44 == 0) { - Object::getObjectType((Object *)&x); - error(&DAT_08106bc0,0,x); - local_44 = 0xffffffff; - } - iVar4 = this->StartZ; - iVar3 = (*this->cr->_vptr_TCreature[3]) - (this->cr,Waypoints + this->StartX, - this->StartY + iVar11,iVar4,0,0); - uVar6 = 0xffffffff; - if ((char)iVar3 != '\0') { - uVar6 = local_44; - } - local_44 = uVar6; - if ((0 < (int)uVar6) && ((int)uVar6 < this->MinWaypoints)) { - this->MinWaypoints = uVar6; - } - } - } - } - pmVar1 = this->Map; - iVar3 = iVar11 - pmVar1->ymin; - iVar8 = Waypoints - pmVar1->xmin; - if ((((iVar8 < 0) || (pmVar1->dx <= iVar8)) || (iVar3 < 0)) || - (pmVar1->dy <= iVar3)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar8 + pmVar1->xmin, - iVar3 + pmVar1->ymin,iVar4); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar3 * pmVar1->dx + iVar8; - } - pTVar5->Waypoints = local_44; - pmVar1 = this->Map; - iVar3 = iVar11 - pmVar1->ymin; - iVar8 = Waypoints - pmVar1->xmin; - if (((iVar8 < 0) || (pmVar1->dx <= iVar8)) || - ((iVar3 < 0 || (pmVar1->dy <= iVar3)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar8 + pmVar1->xmin, - iVar3 + pmVar1->ymin,iVar4); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar3 * pmVar1->dx + iVar8; - } - pTVar5->x = Waypoints; - pmVar1 = this->Map; - iVar4 = iVar11 - pmVar1->ymin; - iVar3 = Waypoints - pmVar1->xmin; - if (((iVar3 < 0) || (pmVar1->dx <= iVar3)) || - ((iVar4 < 0 || (pmVar1->dy <= iVar4)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar3 + pmVar1->xmin, - iVar4 + pmVar1->ymin); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar4 * pmVar1->dx + iVar3; - } - pTVar5->y = iVar11; - iVar11 = iVar11 + 1; - uVar9 = this->VisibleY; - } while (iVar11 <= (int)uVar9); - uVar7 = this->VisibleX; - } - Waypoints = Waypoints + 1; - } while (Waypoints <= (int)uVar7); - } - else { - uVar9 = this->VisibleY; - } - uVar10 = ~uVar7; - if ((int)uVar10 <= (int)(uVar7 + 1)) { - while( true ) { - pmVar1 = this->Map; - iVar11 = ~uVar9 - pmVar1->ymin; - iVar4 = uVar10 - pmVar1->xmin; - if ((((iVar4 < 0) || (pmVar1->dx <= iVar4)) || (iVar11 < 0)) || (pmVar1->dy <= iVar11)) - { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar11 + pmVar1->ymin); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar11 * pmVar1->dx + iVar4; - } - pTVar5->Waypoints = -1; - pmVar1 = this->Map; - iVar11 = (this->VisibleY + 1) - pmVar1->ymin; - iVar4 = uVar10 - pmVar1->xmin; - if (((iVar4 < 0) || (pmVar1->dx <= iVar4)) || ((iVar11 < 0 || (pmVar1->dy <= iVar11)))) - { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar11 + pmVar1->ymin); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar11 * pmVar1->dx + iVar4; - } - pTVar5->Waypoints = -1; - uVar10 = uVar10 + 1; - uVar7 = this->VisibleX; - if ((int)(uVar7 + 1) < (int)uVar10) break; - uVar9 = this->VisibleY; - } - uVar9 = this->VisibleY; - } - iVar11 = -uVar9; - if (-uVar9 == uVar9 || iVar11 < (int)uVar9) { - while( true ) { - pmVar1 = this->Map; - iVar4 = iVar11 - pmVar1->ymin; - iVar3 = ~uVar7 - pmVar1->xmin; - if (((iVar3 < 0) || (pmVar1->dx <= iVar3)) || ((iVar4 < 0 || (pmVar1->dy <= iVar4)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar3 + pmVar1->xmin, - iVar4 + pmVar1->ymin); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar4 * pmVar1->dx + iVar3; - } - pTVar5->Waypoints = -1; - pmVar1 = this->Map; - iVar4 = iVar11 - pmVar1->ymin; - iVar3 = (this->VisibleX + 1) - pmVar1->xmin; - if ((((iVar3 < 0) || (pmVar1->dx <= iVar3)) || (iVar4 < 0)) || (pmVar1->dy <= iVar4)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar3 + pmVar1->xmin, - iVar4 + pmVar1->ymin); - pTVar5 = pmVar1->entry; - } - else { - pTVar5 = pmVar1->entry + iVar4 * pmVar1->dx + iVar3; - } - pTVar5->Waypoints = -1; - iVar11 = iVar11 + 1; - if (this->VisibleY < iVar11) break; - uVar7 = this->VisibleX; - } - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: x -// DWARF original prototype: void ClearMap(TShortway * this) - -void __thiscall TShortway::ClearMap(TShortway *this) - -{ - matrix<> *pmVar1; - int iVar2; - TShortwayPoint *pTVar3; - int iVar4; - int y; - int iVar5; - int local_14; - int x; - - iVar2 = this->VisibleX; - local_14 = -iVar2; - if (-iVar2 == iVar2 || SBORROW4(local_14,iVar2) != iVar2 * -2 < 0) { - iVar4 = this->VisibleY; - do { - iVar5 = -iVar4; - if (-iVar4 == iVar4 || iVar5 < iVar4) { - do { - pmVar1 = this->Map; - iVar2 = iVar5 - pmVar1->ymin; - iVar4 = local_14 - pmVar1->xmin; - if ((((iVar4 < 0) || (pmVar1->dx <= iVar4)) || (iVar2 < 0)) || - (pmVar1->dy <= iVar2)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar2 + pmVar1->ymin); - pTVar3 = pmVar1->entry; - } - else { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar4; - } - pTVar3->Predecessor = (TShortwayPoint *)0x0; - pmVar1 = this->Map; - iVar2 = iVar5 - pmVar1->ymin; - iVar4 = local_14 - pmVar1->xmin; - if (((iVar4 < 0) || (pmVar1->dx <= iVar4)) || - ((iVar2 < 0 || (pmVar1->dy <= iVar2)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar2 + pmVar1->ymin); - pTVar3 = pmVar1->entry; - } - else { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar4; - } - pTVar3->NextToExpand = (TShortwayPoint *)0x0; - pmVar1 = this->Map; - iVar2 = iVar5 - pmVar1->ymin; - iVar4 = local_14 - pmVar1->xmin; - if (((iVar4 < 0) || (pmVar1->dx <= iVar4)) || - ((iVar2 < 0 || (pmVar1->dy <= iVar2)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar2 + pmVar1->ymin); - pTVar3 = pmVar1->entry; - } - else { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar4; - } - pTVar3->Waylength = 0x7fffffff; - pmVar1 = this->Map; - iVar2 = iVar5 - pmVar1->ymin; - iVar4 = local_14 - pmVar1->xmin; - if ((((iVar4 < 0) || (pmVar1->dx <= iVar4)) || (iVar2 < 0)) || - (pmVar1->dy <= iVar2)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar4 + pmVar1->xmin, - iVar2 + pmVar1->ymin); - pTVar3 = pmVar1->entry; - } - else { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar4; - } - pTVar3->Heuristic = 0x7fffffff; - iVar5 = iVar5 + 1; - iVar4 = this->VisibleY; - } while (iVar5 <= iVar4); - iVar2 = this->VisibleX; - } - local_14 = local_14 + 1; - } while (local_14 <= iVar2); - } - this->FirstToExpand = (TShortwayPoint *)0x0; - return; -} - - - -// DWARF original prototype: bool Calculate(TShortway * this, int DestX, int DestY, bool MustReach, -// int MaxSteps) - -bool __thiscall -TShortway::Calculate(TShortway *this,int DestX,int DestY,bool MustReach,int MaxSteps) - -{ - matrix<> *pmVar1; - int iVar2; - int iVar3; - int iVar4; - TCreature *this_00; - bool bVar5; - int iVar6; - int iVar7; - int iVar8; - TShortwayPoint *pTVar9; - TToDoEntry *pTVar10; - int iVar11; - TShortwayPoint *pTVar12; - TShortwayPoint *local_4c; - TShortwayPoint *Search; - int dy; - int dx; - bool MustReach_local; - TToDoEntry TD; - - if (this->Map == (matrix<> *)0x0) { - error("TShortway::Calculate: Karte existiert nicht.\n"); - } - else { - iVar6 = DestX - this->StartX; - iVar7 = DestY - this->StartY; - iVar8 = -iVar6; - if (-1 < iVar6) { - iVar8 = iVar6; - } - if (iVar8 <= this->VisibleX) { - iVar8 = -iVar7; - if (-1 < iVar7) { - iVar8 = iVar7; - } - if (iVar8 <= this->VisibleY) { - if ((iVar6 == 0) && (iVar7 == 0)) { - return true; - } - ClearMap(this); - pmVar1 = this->Map; - iVar8 = iVar7 - pmVar1->ymin; - iVar11 = iVar6 - pmVar1->xmin; - if ((((iVar11 < 0) || (pmVar1->dx <= iVar11)) || (iVar8 < 0)) || - (pmVar1->dy <= iVar8)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar11 + pmVar1->xmin, - iVar8 + pmVar1->ymin); - pTVar9 = pmVar1->entry; - } - else { - pTVar9 = pmVar1->entry + iVar8 * pmVar1->dx + iVar11; - } - pTVar9->Waylength = 0; - pmVar1 = this->Map; - iVar8 = iVar7 - pmVar1->ymin; - iVar11 = iVar6 - pmVar1->xmin; - if (((iVar11 < 0) || (pmVar1->dx <= iVar11)) || - ((iVar8 < 0 || (pmVar1->dy <= iVar8)))) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar11 + pmVar1->xmin, - iVar8 + pmVar1->ymin); - pTVar9 = pmVar1->entry; - } - else { - pTVar9 = pmVar1->entry + iVar8 * pmVar1->dx + iVar11; - } - this->FirstToExpand = pTVar9; - while (pTVar9 != (TShortwayPoint *)0x0) { - Expand(this,pTVar9); - pTVar9 = this->FirstToExpand; - } - pmVar1 = this->Map; - iVar11 = -pmVar1->xmin; - iVar8 = -pmVar1->ymin; - if (((pmVar1->xmin < 1) && (iVar11 < pmVar1->dx)) && - ((pmVar1->ymin < 1 && (iVar8 < pmVar1->dy)))) { - pTVar9 = pmVar1->entry + iVar8 * pmVar1->dx + iVar11; - } - else { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar11 + pmVar1->xmin,0); - pTVar9 = pmVar1->entry; - } - if (pTVar9->Waylength != 0x7fffffff) { - pmVar1 = this->Map; - iVar11 = -pmVar1->xmin; - iVar8 = -pmVar1->ymin; - if ((((pmVar1->xmin < 1) && (iVar11 < pmVar1->dx)) && (pmVar1->ymin < 1)) && - (iVar8 < pmVar1->dy)) { - local_4c = pmVar1->entry + iVar8 * pmVar1->dx + iVar11; - } - else { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar11 + pmVar1->xmin - ,0); - local_4c = pmVar1->entry; - } - if ((local_4c->Predecessor != (TShortwayPoint *)0x0) && - (pTVar9 = local_4c->Predecessor, 0 < MaxSteps)) { - while ((pTVar12 = pTVar9, MustReach || - ((2 < (local_4c->x - iVar6) + 1U || (2 < (local_4c->y - iVar7) + 1U)) - ))) { - iVar8 = pTVar12->x; - iVar11 = this->StartX; - iVar2 = this->StartY; - iVar3 = pTVar12->y; - iVar4 = this->StartZ; - this_00 = this->cr; - if ((this_00->LockToDo != false) && - ((bVar5 = TCreature::ToDoClear(this_00), bVar5 && - (this_00->Type == PLAYER)))) { - SendSnapback(this_00->Connection); - } - pTVar10 = vector::operator() - (&this_00->ToDoList,this_00->NrToDo); - pTVar10->Code = TDGo; - (pTVar10->field_1).Go.x = iVar8 + iVar11; - (pTVar10->field_1).Go.y = iVar3 + iVar2; - (pTVar10->field_1).Go.z = iVar4; - (pTVar10->field_1).Move.z = TD.field_1.Go.z; - (pTVar10->field_1).Move.Count = TD.field_1.Move.z; - this_00->NrToDo = this_00->NrToDo + 1; - MaxSteps = MaxSteps + -1; - if (pTVar12->Predecessor == (TShortwayPoint *)0x0) { - return true; - } - pTVar9 = pTVar12->Predecessor; - local_4c = pTVar12; - if (MaxSteps < 1) { - return true; - } - } - } - return true; - } - } - } - } - return false; -} - - - -// WARNING: Variable defined which should be unmapped: this_local -// DWARF original prototype: void Expand(TShortway * this, TShortwayPoint * Node) - -void __thiscall TShortway::Expand(TShortway *this,TShortwayPoint *Node) - -{ - matrix<> *pmVar1; - int iVar2; - TShortwayPoint *pTVar3; - uint uVar4; - TShortwayPoint *Search_1; - TShortwayPoint *pTVar5; - TShortwayPoint *Search; - int iVar6; - int iVar7; - TShortwayPoint *pTVar8; - uint uVar9; - int Waylength; - int iVar10; - int local_24; - int y; - int x; - int BasicWaylength; - TShortwayPoint *Node_local; - TShortway *this_local; - - if (Node == (TShortwayPoint *)0x0) { - error(&DAT_08106c80); - return; - } - this->FirstToExpand = Node->NextToExpand; - iVar6 = Node->Waypoints + Node->Waylength; - pmVar1 = this->Map; - iVar7 = -pmVar1->xmin; - iVar2 = -pmVar1->ymin; - if ((((pmVar1->xmin < 1) && (iVar7 < pmVar1->dx)) && (pmVar1->ymin < 1)) && (iVar2 < pmVar1->dy) - ) { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar7; - } - else { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar7 + pmVar1->xmin,0); - pTVar3 = pmVar1->entry; - } - if (iVar6 < pTVar3->Waylength) { - y = -1; - do { - local_24 = -1; - do { - if ((y != 0) || (local_24 != 0)) { - pmVar1 = this->Map; - iVar2 = (local_24 + Node->y) - pmVar1->ymin; - iVar7 = (y + Node->x) - pmVar1->xmin; - if (((iVar7 < 0) || ((pmVar1->dx <= iVar7 || (iVar2 < 0)))) || - (pmVar1->dy <= iVar2)) { - error("matrix::operator(): Ungueltiger Index %d/%d.\n",iVar7 + pmVar1->xmin, - iVar2 + pmVar1->ymin); - pTVar3 = pmVar1->entry; - } - else { - pTVar3 = pmVar1->entry + iVar2 * pmVar1->dx + iVar7; - } - iVar2 = -y; - if (-1 < y) { - iVar2 = y; - } - iVar7 = -local_24; - if (-1 < local_24) { - iVar7 = local_24; - } - iVar10 = iVar6; - if (iVar2 + iVar7 != 1) { - iVar10 = iVar6 + Node->Waypoints * 2; - } - if (iVar10 < pTVar3->Waylength) { - pTVar3->Waylength = iVar10; - uVar9 = pTVar3->x; - pTVar3->Predecessor = Node; - if (((uVar9 != 0) || (pTVar3->y != 0)) && - (iVar2 = pTVar3->Waypoints, iVar2 != -1)) { - if (pTVar3->Heuristic != 0x7fffffff) { - pTVar5 = this->FirstToExpand; - if (pTVar5 == pTVar3) { - this->FirstToExpand = pTVar3->NextToExpand; - } - else { - for (pTVar8 = pTVar5->NextToExpand; - pTVar8 != (TShortwayPoint *)0x0; - pTVar8 = pTVar8->NextToExpand) { - if (pTVar8 == pTVar3) { - if (pTVar8 != (TShortwayPoint *)0x0) { - pTVar5->NextToExpand = pTVar3->NextToExpand; - goto LAB_080bedc6; - } - break; - } - pTVar5 = pTVar8; - } - error( - "TShortway::Expand: Knoten steht nicht in der ExpandList.\n" - ); - } - uVar9 = pTVar3->x; - iVar2 = pTVar3->Waypoints; - } -LAB_080bedc6: - uVar4 = pTVar3->y; - if (0x7fffffff < uVar9) { - uVar9 = -uVar9; - } - if (0x7fffffff < uVar4) { - uVar4 = -uVar4; - } - iVar2 = ((uVar4 - 1) + uVar9) * this->MinWaypoints + iVar2 + iVar10; - pTVar3->Heuristic = iVar2; - pTVar5 = this->FirstToExpand; - if ((pTVar5 == (TShortwayPoint *)0x0) || (iVar2 <= pTVar5->Heuristic)) { - pTVar3->NextToExpand = pTVar5; - this->FirstToExpand = pTVar3; - } - else { - pTVar8 = pTVar5->NextToExpand; - if ((pTVar8 != (TShortwayPoint *)0x0) && (pTVar8->Heuristic < iVar2) - ) { - do { - pTVar5 = pTVar8; - pTVar8 = pTVar5->NextToExpand; - if (pTVar8 == (TShortwayPoint *)0x0) break; - } while (pTVar8->Heuristic < pTVar3->Heuristic); - } - pTVar3->NextToExpand = pTVar8; - pTVar5->NextToExpand = pTVar3; - } - } - } - } - local_24 = local_24 + 1; - } while (local_24 < 2); - y = y + 1; - } while (y < 2); - } - return; -} - - - -// DWARF original prototype: bool SetOnMap(TCreature * this) - -bool __thiscall TCreature::SetOnMap(TCreature *this) - -{ - int *z; - int *y; - int *x; - bool bVar1; - bool bVar2; - ushort HouseID; - ushort HouseID_00; - bool NoRoom; - ObjectType local_5c [4]; - ObjectType local_4c [4]; - Object local_3c [4]; - ulong local_2c; - Object Obj; - - z = &this->posz; - y = &this->posy; - x = &this->posx; - bVar1 = SearchLoginField(x,y,z,1,this->Type == PLAYER); - bVar1 = !bVar1; - if (bVar1) { - bVar2 = IsHouse(this->posx,this->posy,this->posz); - if (bVar2) { - HouseID_00 = GetHouseID(this->posx,this->posy,this->posz); - GetExitPosition(HouseID_00,x,y,z); - bVar1 = SearchLoginField(x,y,z,1,this->Type == PLAYER); - bVar1 = !bVar1; - } - if (bVar1) { - this->posx = this->startx; - this->posy = this->starty; - this->posz = this->startz; - } - } - GetMapContainer((int)&local_2c,this->posx,this->posy); - bVar1 = local_2c != ::NONE.ObjectID; - local_3c[0].ObjectID = ::NONE.ObjectID; - if (bVar1) { - // try { // try from 080befa5 to 080befcc has its CatchHandler @ 080bf0a5 - ObjectType::setTypeID(local_4c,99); - local_5c[0].TypeID = local_2c; - Create(local_3c,local_5c,(ulong)local_4c); - } - else { - error(&DAT_08106cc0,this->posx,this->posy,this->posz); - } - return bVar1; -} - - - -// DWARF original prototype: bool DelOnMap(TCreature * this) - -bool __thiscall TCreature::DelOnMap(TCreature *this) - -{ - RESULT r; - Object local_4c [4]; - ulong local_3c; - ulong local_2c; - Object Help; - - local_3c = ::NONE.ObjectID; - local_4c[0].ObjectID = (this->CrObject).ObjectID; - if (local_4c[0].ObjectID != ::NONE.ObjectID) { - (this->CrObject).ObjectID = ::NONE.ObjectID; - local_2c = local_4c[0].ObjectID; - // try { // try from 080bf180 to 080bf184 has its CatchHandler @ 080bf187 - Delete(local_4c,-1); - } - return true; -} - - - // DWARF original prototype: void Go(TCreature * this, int x, int y, int z) void __thiscall TCreature::Go(TCreature *this,int x,int y,int z) @@ -49496,174 +47174,6 @@ LAB_080c12f2: return; } - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void CreatureMoveStimulus(TCreature * this, ulong CreatureID, int Type) - -void __thiscall TCreature::CreatureMoveStimulus(TCreature *this,ulong CreatureID,int Type) - -{ - vector *this_00; - uint uVar1; - bool bVar2; - TToDoEntry *pTVar3; - TCreature *pTVar4; - int iVar5; - int *piVar6; - int Delay_1; - int Delay; - int local_64; - int local_60; - undefined1 local_5c [4]; - TToDoEntry TD; - Object local_3c [4]; - Object local_2c [7]; - - if (((((CreatureID != this->ID) && (CreatureID != 0)) && - (CreatureID == (this->Combat).AttackDest)) && ((Type == 2 && (this->LockToDo != false)))) - && ((this->IsDead == false && (this->ActToDo < this->NrToDo)))) { - this_00 = &this->ToDoList; - pTVar3 = vector::operator()(this_00,this->ActToDo); - if ((pTVar3->Code == TDAttack) && ((this->Combat).ChaseMode == '\x01')) { - uVar1 = (this->Combat).EarliestAttackTime; - if ((ServerMilliseconds < uVar1) && (200 < (int)(uVar1 - ServerMilliseconds))) { - pTVar4 = GetCreature((this->Combat).AttackDest); - if (pTVar4 != (TCreature *)0x0) { - local_2c[0].ObjectID = (pTVar4->CrObject).ObjectID; - local_3c[0].ObjectID = (this->CrObject).ObjectID; - iVar5 = ObjectDistance(local_3c,local_2c); - if (1 < iVar5) { - bVar2 = ToDoClear(this); - if ((bVar2) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - local_5c = (undefined1 [4])0x0; - TD.Code = ServerMilliseconds + 200; - if (this->LockToDo != false) { - // try { // try from 080c16d0 to 080c16fb has its CatchHandler @ 080c19b4 - bVar2 = ToDoClear(this); - if ((bVar2) && (this->Type == PLAYER)) { - // try { // try from 080c184b to 080c184f has its CatchHandler @ 080c19b4 - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(this_00,this->NrToDo); - pTVar3->Code = (ToDoType)local_5c; - (pTVar3->field_1).Move.Obj = TD.Code; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar3->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - // try { // try from 080c1728 to 080c17c0 has its CatchHandler @ 080c1868 - TCombat::CanToDoAttack(&this->Combat); - iVar5 = TCombat::GetDistance(&this->Combat); - if (iVar5 != 1) { - local_5c = (undefined1 [4])0x0; - TD.Code = ServerMilliseconds + 100; - if (this->LockToDo != false) { - bVar2 = ToDoClear(this); - if ((bVar2) && (this->Type == PLAYER)) { - // try { // try from 080c1838 to 080c183c has its CatchHandler @ 080c1868 - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(this_00,this->NrToDo); - pTVar3->Code = (ToDoType)local_5c; - (pTVar3->field_1).Move.Obj = TD.Code; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar3->field_1 + 4))->Time - = (ulong)TD.field_1.Wait.Time; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - } - local_5c = (undefined1 [4])0x7; - ToDoAdd(this,(TToDoEntry *)local_5c); - if (this->NrToDo != 0) { - this->LockToDo = true; - this->ActToDo = 0; - // try { // try from 080c17e1 to 080c181c has its CatchHandler @ 080c19b4 - local_60 = CalculateDelay(this); - local_64 = 1; - piVar6 = &local_64; - if (0 < local_60) { - piVar6 = &local_60; - } - iVar5 = *piVar6; - priority_queue<>::insert(&ToDoQueue); - this->NextWakeup = iVar5 + ServerMilliseconds; - } - } - } - } - } - } - return; -} - - - -// DWARF original prototype: int CalculateDelay(TCreature * this) - -int __thiscall TCreature::CalculateDelay(TCreature *this) - -{ - ToDoType TVar1; - uint uVar2; - TToDoEntry *pTVar3; - ToDoType TVar4; - int *piVar5; - uint uVar6; - int local_34; - int local_30 [2]; - TToDoEntry TD; - - pTVar3 = vector::operator()(&this->ToDoList,this->ActToDo); - TVar1 = pTVar3->Code; - TD.Code = (pTVar3->field_1).Move.Obj; - TD.field_1.Wait.Time = (anon_struct_4_1_898373eb_for_Wait)(pTVar3->field_1).Go.y; - TD.field_1.Go.y = (pTVar3->field_1).Go.z; - TD.field_1.Go.z = (pTVar3->field_1).Move.z; - TD.field_1.Move.z = (pTVar3->field_1).Move.Count; - if ((TVar1 == TDGo) && (ServerMilliseconds < this->EarliestWalkTime)) { - return this->EarliestWalkTime - ServerMilliseconds; - } - if (((TVar1 != TDUse) || (TD.field_1.Go.x == 0)) || - (TVar4 = this->EarliestMultiuseTime, TVar4 <= ServerMilliseconds)) { - if (TVar1 == TDAttack) { - uVar2 = (this->Combat).EarliestAttackTime; - if (ServerMilliseconds < uVar2) { - uVar6 = this->EarliestSpellTime; -LAB_080c1a7f: - local_30[0] = uVar2 - ServerMilliseconds; - local_34 = uVar6 - ServerMilliseconds; - piVar5 = &local_34; - if ((int)(uVar6 - ServerMilliseconds) <= local_30[0]) { - piVar5 = local_30; - } - return *piVar5; - } - uVar6 = this->EarliestSpellTime; - if (ServerMilliseconds < uVar6) goto LAB_080c1a7f; - } - if ((TVar1 != TDWait) || - ((this->EarliestWalkTime <= ServerMilliseconds && (TD.Code <= ServerMilliseconds)))) { - return 0; - } - pTVar3 = &TD; - if (TD.Code <= this->EarliestWalkTime) { - pTVar3 = (TToDoEntry *)&this->EarliestWalkTime; - } - TVar4 = pTVar3->Code; - } - return TVar4 - ServerMilliseconds; -} - - - // DWARF original prototype: void Execute(TCreature * this) void __thiscall TCreature::Execute(TCreature *this) @@ -49796,959 +47306,6 @@ LAB_080c1d33: } while( true ); } - - -// WARNING: Variable defined which should be unmapped: SnapbackNecessary -// DWARF original prototype: bool ToDoClear(TCreature * this) - -bool __thiscall TCreature::ToDoClear(TCreature *this) - -{ - TToDoEntry *pTVar1; - TToDoEntry *TD; - int i; - int i_00; - bool local_11; - bool SnapbackNecessary; - - local_11 = false; - if (0 < this->NrToDo) { - i_00 = 0; - do { - pTVar1 = vector::operator()(&this->ToDoList,i_00); - switch(pTVar1->Code) { - case TDGo: - if (this->ActToDo <= i_00) { - local_11 = true; - } - break; - case TDTalk: - DeleteDynamicString((pTVar1->field_1).Move.Obj); - DeleteDynamicString((pTVar1->field_1).Talk.Addressee); - break; - case TDChangeState: - if ((this->ActToDo <= i_00) && (this->Type == NPC)) { - ChangeNPCState(this,(pTVar1->field_1).Go.x,false); - } - } - i_00 = i_00 + 1; - } while (i_00 < this->NrToDo); - } - this->LockToDo = false; - this->ActToDo = 0; - this->NrToDo = 0; - this->Stop = false; - return local_11; -} - - - -// DWARF original prototype: void ToDoStop(TCreature * this) - -void __thiscall TCreature::ToDoStop(TCreature *this) - -{ - if (this->LockToDo == false) { - if (this->Type == PLAYER) { - SendSnapback(this->Connection); - return; - } - } - else { - this->Stop = true; - } - return; -} - - - -// DWARF original prototype: void ToDoAdd(TCreature * this, TToDoEntry * TD) - -void __thiscall TCreature::ToDoAdd(TCreature *this,TToDoEntry *TD) - -{ - bool bVar1; - TToDoEntry *pTVar2; - - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = TD->Code; - (pTVar2->field_1).Wait.Time = (TD->field_1).Wait.Time; - (pTVar2->field_1).Go.y = (TD->field_1).Go.y; - (pTVar2->field_1).Go.z = (TD->field_1).Go.z; - (pTVar2->field_1).Move.z = (TD->field_1).Move.z; - (pTVar2->field_1).Move.Count = (TD->field_1).Move.Count; - this->NrToDo = this->NrToDo + 1; - return; -} - - - -// DWARF original prototype: void ToDoStart(TCreature * this) - -void __thiscall TCreature::ToDoStart(TCreature *this) - -{ - int iVar1; - int *piVar2; - int Delay; - int local_14; - int local_10; - - if (this->NrToDo != 0) { - this->LockToDo = true; - this->ActToDo = 0; - local_10 = CalculateDelay(this); - piVar2 = &local_14; - if (0 < local_10) { - piVar2 = &local_10; - } - local_14 = 1; - iVar1 = *piVar2; - priority_queue<>::insert(&ToDoQueue); - this->NextWakeup = iVar1 + ServerMilliseconds; - } - return; -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoYield(TCreature * this) - -void __thiscall TCreature::ToDoYield(TCreature *this) - -{ - ulong uVar1; - TToDoEntry *pTVar2; - TToDoEntry TD; - - uVar1 = ServerMilliseconds; - if (this->LockToDo == false) { - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = TDWait; - (pTVar2->field_1).Move.Obj = uVar1; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar2->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar2->field_1).Go.z = TD.field_1.Go.y; - (pTVar2->field_1).Move.z = TD.field_1.Go.z; - (pTVar2->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - ToDoStart(this); - } - return; -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoWait(TCreature * this, int Delay) - -void __thiscall TCreature::ToDoWait(TCreature *this,int Delay) - -{ - bool bVar1; - int iVar2; - TToDoEntry *pTVar3; - TToDoEntry TD; - - iVar2 = Delay + ServerMilliseconds; - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = TDWait; - (pTVar3->field_1).Go.x = iVar2; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar3->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; -} - - - -// DWARF original prototype: void ToDoTalk(TCreature * this, int Mode, char * Addressee, char * -// Text, bool CheckSpamming) - -void __thiscall TCreature::ToDoTalk(TCreature *this) - -{ - bool bVar1; - ulong uVar2; - TToDoEntry *pTVar3; - int in_stack_00000008; - char *in_stack_0000000c; - char *in_stack_00000010; - undefined1 in_stack_00000014; - TToDoEntry TD; - - if (in_stack_0000000c == (char *)0x0) { - TD.field_1.Go.y = 0; - } - else { - TD.field_1.Trade.Partner = AddDynamicString(in_stack_0000000c); - } - TD.field_1.Go.z._0_1_ = in_stack_00000014; - if (in_stack_00000010 == (char *)0x0) { - error("TCreature::ToDoTalk: Text ist NULL bei %s.\n",this->Name); - } - uVar2 = AddDynamicString(in_stack_00000010); - if (uVar2 == 0) { - error("TCreature::ToDoTalk: TD.Text ist Null bei %s.\n",this->Name); - } - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = TDTalk; - (pTVar3->field_1).Move.Obj = uVar2; - (pTVar3->field_1).Go.y = in_stack_00000008; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoChangeState(TCreature * this, int NewState) - -void __thiscall TCreature::ToDoChangeState(TCreature *this,int NewState) - -{ - bool bVar1; - TToDoEntry *pTVar2; - TToDoEntry TD; - - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = TDChangeState; - (pTVar2->field_1).Go.x = NewState; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar2->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar2->field_1).Go.z = TD.field_1.Go.y; - (pTVar2->field_1).Move.z = TD.field_1.Go.z; - (pTVar2->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; -} - - - -// DWARF original prototype: void ToDoGo(TCreature * this, int DestX, int DestY, int DestZ, bool -// Dest, int MaxSteps) - -void __thiscall -TCreature::ToDoGo(TCreature *this,int DestX,int DestY,int DestZ,bool Dest,int MaxSteps) - -{ - vector *this_00; - bool bVar1; - undefined4 *puVar2; - TToDoEntry *pTVar3; - int dx; - uint uVar4; - int dy; - uint uVar5; - undefined1 local_6c [3]; - bool Dest_local; - TShortway Shortway; - TToDoEntry TD; - - if (this->posz < DestZ) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x18; - } - else { - if (this->posz <= DestZ) { - if (this->LockToDo != false) { - this_00 = &this->ToDoList; - pTVar3 = vector::operator()(this_00,this->NrToDo + -1); - if ((((pTVar3->Code == TDGo) && - (pTVar3 = vector::operator()(this_00,this->NrToDo + -1), - (pTVar3->field_1).Go.x == DestX)) && - (pTVar3 = vector::operator()(this_00,this->NrToDo + -1), - (pTVar3->field_1).Go.y == DestY)) && - (pTVar3 = vector::operator()(this_00,this->NrToDo + -1), - (pTVar3->field_1).Go.z == DestZ)) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0; - goto LAB_080c2810; - } - } - uVar5 = DestY - this->posy; - uVar4 = DestX - this->posx; - if (((uVar4 != 0) || (uVar5 != 0)) && ((Dest || ((2 < uVar4 + 1 || (2 < uVar5 + 1)))))) - { - if (0x7fffffff < uVar4) { - uVar4 = -uVar4; - } - if (0x7fffffff < uVar5) { - uVar5 = -uVar5; - } - if (uVar5 + uVar4 == 1) { - if (((this->LockToDo != false) && (bVar1 = ToDoClear(this), bVar1)) && - (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - // try { // try from 080c272a to 080c2827 has its CatchHandler @ 080c2870 - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = TDGo; - (pTVar3->field_1).Go.x = DestX; - (pTVar3->field_1).Go.y = DestY; - (pTVar3->field_1).Go.z = DestZ; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - } - else { - // try { // try from 080c2660 to 080c2664 has its CatchHandler @ 080c2870 - TShortway::TShortway - ((TShortway *)local_6c,this,(uint)(this->Type != PLAYER) * 3 + 7, - (uint)(this->Type != PLAYER) * 3 + 7); - // try { // try from 080c2685 to 080c26f4 has its CatchHandler @ 080c2850 - bVar1 = TShortway::Calculate((TShortway *)local_6c,DestX,DestY,Dest,MaxSteps); - if (!bVar1) { - ToDoClear(this); - if (this->Type == PLAYER) { - SendSnapback(this->Connection); - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x2c; - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); - } - TShortway::~TShortway((TShortway *)local_6c,DestX); - } - } - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x17; - } -LAB_080c2810: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoRotate(TCreature * this, int Direction) - -void __thiscall TCreature::ToDoRotate(TCreature *this,int Direction) - -{ - bool bVar1; - TToDoEntry *pTVar2; - undefined4 *puVar3; - TToDoEntry TD; - - if (Direction < 4) { - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - // try { // try from 080c28c4 to 080c294f has its CatchHandler @ 080c2950 - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = TDRotate; - (pTVar2->field_1).Go.x = Direction; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar2->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar2->field_1).Go.z = TD.field_1.Go.y; - (pTVar2->field_1).Move.z = TD.field_1.Go.z; - (pTVar2->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; - } - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -// DWARF original prototype: void ToDoMove(TCreature * this, int sx, int sy, int sz, ObjectType * -// Type, uchar RNum, int zx, int zy, int zz, uchar Count) - -void __thiscall -TCreature::ToDoMove(TCreature *this,int sx,int sy,int sz,ObjectType *Type,uchar RNum,int zx,int zy, - int zz,uchar Count) - -{ - bool bVar1; - TCreature *pTVar2; - int iVar3; - TToDoEntry *pTVar4; - undefined4 *puVar5; - ObjectType *Type_00; - ulong x; - int iVar6; - int iVar7; - Object *pOVar8; - uchar Count_local; - TToDoEntry TD; - Object local_4c [4]; - Object local_3c; - Object Dest; - Object local_2c; - Object Obj; - - // try { // try from 080c299f to 080c2c56 has its CatchHandler @ 080c2c90 - ObjectType::setTypeID((ObjectType *)&local_3c,Type->TypeID); - Type_00 = (ObjectType *)(uint)RNum; - x = this->ID; - iVar3 = sx; - iVar6 = sy; - iVar7 = sz; - pOVar8 = &local_3c; - GetObject((ulong)&local_2c,x,sx,sy,sz,Type_00); - bVar1 = Object::exists(&local_2c); - if (bVar1) { - if (sx != 0xffff) { - if (this->posz < sz) { - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0x18; - goto LAB_080c2be8; - } - if (sz < this->posz) { - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0x17; - goto LAB_080c2be8; - } - local_3c.ObjectID = local_2c.ObjectID; - bVar1 = ObjectInRange(this->ID,&local_3c,1); - if (!bVar1) { - Type_00 = (ObjectType *)0x7fffffff; - iVar7 = 0; - ToDoGo(this,sx,sy,sz,false,0x7fffffff); - } - } - Object::getObjectType(&local_3c); - if (local_3c.ObjectID != 99) { - iVar3 = 100; -LAB_080c2b08: - ToDoWait(this,iVar3); - if (((this->LockToDo != false) && (bVar1 = ToDoClear(this), bVar1)) && - (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - pTVar4 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar4->Code = TDMove; - (pTVar4->field_1).Wait.Time = local_2c.ObjectID; - (pTVar4->field_1).Go.y = zx; - (pTVar4->field_1).Go.z = zy; - (pTVar4->field_1).Move.z = zz; - *(uint *)((int)&pTVar4->field_1 + 0x10) = (uint)Count; - this->NrToDo = this->NrToDo + 1; - return; - } - x = zx; - iVar3 = zy; - iVar6 = zz; - GetFirstObject(); - bVar1 = Object::exists(&local_3c); - if (bVar1) { - Object::getObjectType(local_4c); - x = 0; - bVar1 = ObjectType::getFlag((ObjectType *)local_4c,BANK); - if (bVar1) { - Object::getObjectType(local_4c); - ObjectType::getAttribute((ObjectType *)local_4c,WAYPOINTS); - local_4c[0].ObjectID = local_2c.ObjectID; - pTVar2 = GetCreature(local_4c); - if (pTVar2 != (TCreature *)0x0) { - if (ServerMilliseconds < pTVar2->EarliestWalkTime) { - iVar3 = (pTVar2->EarliestWalkTime - ServerMilliseconds) + 1000; - } - else { - iVar3 = 1000; - } - goto LAB_080c2b08; - } - error("TCreature::ToDoMove: Kreatur existiert nicht.\n"); - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0xffffffff; - goto LAB_080c2be8; - } - } - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4,x,iVar3,iVar6,iVar7,Type_00,pOVar8); - *puVar5 = 1; -LAB_080c2be8: - // WARNING: Subroutine does not return - __cxa_throw(puVar5,&RESULT::typeinfo,0); -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoMove(TCreature * this, Object * Obj, int zx, int zy, int zz, -// uchar Count) - -void __thiscall TCreature::ToDoMove(TCreature *this,Object *Obj,int zx,int zy,int zz,uchar Count) - -{ - bool bVar1; - TToDoEntry *pTVar2; - undefined4 *puVar3; - int Delay; - int iStack_68; - uchar Count_local; - int x; - int y; - int z; - TToDoEntry TD; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 080c2cd2 to 080c2e61 has its CatchHandler @ 080c2e62 - bVar1 = Object::exists(Obj); - if (!bVar1) { - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 1; - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); - } - local_2c[0] = (Object)Obj->ObjectID; - bVar1 = ObjectInRange(this->ID,local_2c,1); - if (!bVar1) { - local_3c[0] = (Object)Obj->ObjectID; - GetObjectCoordinates(local_3c,&stack0xffffff98,&x,&y); - ToDoGo(this,iStack_68,x,y,false,0x7fffffff); - } - Object::getObjectType(local_3c); - Delay = 1000; - if (local_3c[0].ObjectID != 99) { - Delay = 100; - } - ToDoWait(this,Delay); - z = 3; - TD.Code = Obj->ObjectID; - TD.field_1.Move.z = (int)Count; - TD.field_1.Go.x = zx; - TD.field_1.Go.y = zy; - TD.field_1.Go.z = zz; - if (((this->LockToDo != false) && (bVar1 = ToDoClear(this), bVar1)) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = z; - (pTVar2->field_1).Move.Obj = TD.Code; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar2->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar2->field_1).Go.z = TD.field_1.Go.y; - (pTVar2->field_1).Move.z = TD.field_1.Go.z; - (pTVar2->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; -} - - - -// DWARF original prototype: void ToDoTrade(TCreature * this, int x, int y, int z, ObjectType * -// Type, uchar RNum, ulong TradePartner) - -void __thiscall -TCreature::ToDoTrade - (TCreature *this,int x,int y,int z,ObjectType *Type,uchar RNum,ulong TradePartner) - -{ - bool bVar1; - TCreature *pTVar2; - TToDoEntry *pTVar3; - undefined4 *puVar4; - char *Text; - Object *this_00; - TToDoEntry TD; - Object local_3c [4]; - Object local_2c; - Object Obj; - - this_00 = &local_2c; - // try { // try from 080c2ea5 to 080c3132 has its CatchHandler @ 080c3185 - ObjectType::setTypeID((ObjectType *)local_3c,Type->TypeID); - GetObject((ulong)this_00,this->ID,x,y,z,(ObjectType *)(uint)RNum); - bVar1 = Object::exists(this_00); - if (!bVar1) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 1; - goto LAB_080c30bb; - } - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,UNMOVE); - if (bVar1) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 2; - goto LAB_080c30bb; - } - Object::getObjectType(local_3c); - bVar1 = ObjectType::getFlag((ObjectType *)local_3c,TAKE); - if (!bVar1) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 3; - goto LAB_080c30bb; - } - Object::getObjectType(local_3c); - if (local_3c[0].ObjectID == 99) { - Text = "TCreature::ToDoTrade: Objekt ist eine Kreatur.\n"; -LAB_080c312e: - error(Text,this_00); - } - else { - if (TradePartner == 0) { - Text = "TCreature::ToDoTrade: Handelspartner ist Null.\n"; - goto LAB_080c312e; - } - pTVar2 = GetCreature(TradePartner); - if (pTVar2 == (TCreature *)0x0) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x1b; - goto LAB_080c30bb; - } - if (pTVar2->Type == PLAYER) { - if (x == 0xffff) { -LAB_080c2fd4: - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = TDTrade; - (pTVar3->field_1).Wait.Time = local_2c.ObjectID; - (pTVar3->field_1).Trade.Partner = TradePartner; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; - } - if (this->posz < z) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x18; - } - else { - if (this->posz <= z) { - local_3c[0].ObjectID = local_2c.ObjectID; - bVar1 = ObjectInRange(this->ID,local_3c,1); - if (!bVar1) { - ToDoGo(this,x,y,z,false,0x7fffffff); - } - goto LAB_080c2fd4; - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x17; - } - goto LAB_080c30bb; - } - error("TCreature::ToDoTrade: Handelspartner von %s ist kein Spieler.\n",this->Name); - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_080c30bb: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -// DWARF original prototype: void ToDoUse(TCreature * this, uchar Count, int x1, int y1, int z1, -// ObjectType * Type1, uchar RNum1, uchar Dummy, int x2, int y2, int z2, ObjectType * Type2, uchar -// RNum2) - -void __thiscall -TCreature::ToDoUse(TCreature *this,uchar Count,int x1,int y1,int z1,ObjectType *Type1,uchar RNum1, - uchar Dummy,int x2,int y2,int z2,ObjectType *Type2,uchar RNum2) - -{ - Object OVar1; - Object OVar2; - bool bVar3; - TToDoEntry *pTVar4; - undefined4 *puVar5; - uchar RNum2_local; - uchar Dummy_local; - uchar Count_local; - TToDoEntry TD; - Object local_6c [4]; - ulong local_5c [4]; - ObjectType local_4c [4]; - Object local_3c; - Object Obj2; - Object local_2c; - Object Obj1; - - local_3c.ObjectID = 0; - local_2c.ObjectID = 0; - // try { // try from 080c31ee to 080c3453 has its CatchHandler @ 080c3473 - ObjectType::setTypeID((ObjectType *)local_6c,Type1->TypeID); - GetObject((ulong)local_5c,this->ID,x1,y1,z1,(ObjectType *)(uint)RNum1); - local_2c.ObjectID = local_5c[0]; - local_4c[0].TypeID = local_5c[0]; - bVar3 = Object::exists(&local_2c); - if (bVar3) { - if (Count < 2) { - local_5c[0] = ::NONE.ObjectID; - local_3c.ObjectID = ::NONE.ObjectID; - local_6c[0].ObjectID = ::NONE.ObjectID; - } - else { - ObjectType::setTypeID(local_4c,Type2->TypeID); - GetObject((ulong)local_5c,this->ID,x2,y2,z2,(ObjectType *)(uint)RNum2); - local_3c.ObjectID = local_5c[0]; - local_6c[0].ObjectID = local_5c[0]; - bVar3 = Object::exists(&local_3c); - if (!bVar3) goto LAB_080c345c; - } - if (x1 == 0xffff) { -LAB_080c32b4: - ToDoWait(this,100); - OVar2.ObjectID = local_2c.ObjectID; - OVar1.ObjectID = local_3c.ObjectID; - if (this->LockToDo != false) { - bVar3 = ToDoClear(this); - if ((bVar3) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar4 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar4->Code = TDUse; - (pTVar4->field_1).Wait.Time = OVar2.ObjectID; - (pTVar4->field_1).Go.y = OVar1.ObjectID; - *(uint *)((int)&pTVar4->field_1 + 8) = (uint)Dummy; - (pTVar4->field_1).Move.z = TD.field_1.Go.z; - (pTVar4->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; - } - if (this->posz < z1) { - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0x18; - } - else { - if (this->posz <= z1) { - local_6c[0].ObjectID = local_2c.ObjectID; - bVar3 = ObjectInRange(this->ID,local_6c,1); - if (!bVar3) { - ToDoGo(this,x1,y1,z1,false,0x7fffffff); - } - goto LAB_080c32b4; - } - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 0x17; - } - } - else { -LAB_080c345c: - puVar5 = (undefined4 *)__cxa_allocate_exception(4); - *puVar5 = 1; - } - // WARNING: Subroutine does not return - __cxa_throw(puVar5,&RESULT::typeinfo,0); -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoUse(TCreature * this, uchar Count, Object * Obj1, Object * -// Obj2) - -void __thiscall TCreature::ToDoUse(TCreature *this,uchar Count,Object *Obj1,Object *Obj2) - -{ - Object OVar1; - bool bVar2; - TToDoEntry *pTVar3; - undefined4 *puVar4; - int iStack_68; - uchar Count_local; - int x; - int y; - int z; - TToDoEntry TD; - Object local_3c [4]; - Object local_2c [7]; - - // try { // try from 080c34b5 to 080c3640 has its CatchHandler @ 080c3641 - bVar2 = Object::exists(Obj1); - OVar1 = ::NONE; - if (bVar2) { - if (Count < 2) { - Obj2->ObjectID = (ulong)::NONE; - local_2c[0].ObjectID = OVar1.ObjectID; - } - else { - bVar2 = Object::exists(Obj2); - if (!bVar2) goto LAB_080c3617; - } - local_3c[0] = (Object)Obj1->ObjectID; - bVar2 = ObjectInRange(this->ID,local_3c,1); - if (!bVar2) { - local_2c[0] = (Object)Obj1->ObjectID; - GetObjectCoordinates(local_2c,&stack0xffffff98,&x,&y); - ToDoGo(this,iStack_68,x,y,false,0x7fffffff); - } - ToDoWait(this,100); - z = 5; - TD.Code = Obj1->ObjectID; - TD.field_1.Go.y = (int)Count; - TD.field_1.Wait.Time = (anon_struct_4_1_898373eb_for_Wait)Obj2->ObjectID; - if (this->LockToDo != false) { - bVar2 = ToDoClear(this); - if ((bVar2) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = z; - (pTVar3->field_1).Move.Obj = TD.Code; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar3->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; - } -LAB_080c3617: - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 1; - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoTurn(TCreature * this, int x, int y, int z, ObjectType * Type, -// uchar RNum) - -void __thiscall TCreature::ToDoTurn(TCreature *this,int x,int y,int z,ObjectType *Type,uchar RNum) - -{ - bool bVar1; - TToDoEntry *pTVar2; - undefined4 *puVar3; - TToDoEntry TD; - Object local_3c [4]; - Object local_2c; - Object Obj; - - // try { // try from 080c3685 to 080c382e has its CatchHandler @ 080c3857 - ObjectType::setTypeID((ObjectType *)local_3c,Type->TypeID); - GetObject((ulong)&local_2c,this->ID,x,y,z,(ObjectType *)(uint)RNum); - bVar1 = Object::exists(&local_2c); - if (bVar1) { - if (x == 0xffff) { -LAB_080c3721: - ToDoWait(this,100); - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar2 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar2->Code = TDTurn; - (pTVar2->field_1).Wait.Time = local_2c.ObjectID; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar2->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar2->field_1).Go.z = TD.field_1.Go.y; - (pTVar2->field_1).Move.z = TD.field_1.Go.z; - (pTVar2->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; - } - if (this->posz < z) { - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x18; - } - else { - if (this->posz <= z) { - local_3c[0].ObjectID = local_2c.ObjectID; - bVar1 = ObjectInRange(this->ID,local_3c,1); - if (!bVar1) { - ToDoGo(this,x,y,z,false,0x7fffffff); - } - goto LAB_080c3721; - } - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x17; - } - } - else { - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 1; - } - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); -} - - - -// WARNING: Type propagation algorithm not settling -// DWARF original prototype: void ToDoAttack(TCreature * this) - -void __thiscall TCreature::ToDoAttack(TCreature *this) - -{ - bool bVar1; - int iVar2; - TToDoEntry *pTVar3; - TToDoEntry TD; - - // try { // try from 080c3888 to 080c3928 has its CatchHandler @ 080c3930 - TCombat::CanToDoAttack(&this->Combat); - iVar2 = TCombat::GetDistance(&this->Combat); - if (iVar2 != 1) { - ToDoWait(this,100); - } - if (this->LockToDo != false) { - bVar1 = ToDoClear(this); - if ((bVar1) && (this->Type == PLAYER)) { - SendSnapback(this->Connection); - } - } - pTVar3 = vector::operator()(&this->ToDoList,this->NrToDo); - pTVar3->Code = TDAttack; - (pTVar3->field_1).Move.Obj = TD.Code; - ((anon_struct_4_1_898373eb_for_Wait *)((int)&pTVar3->field_1 + 4))->Time = - (ulong)TD.field_1.Wait.Time; - (pTVar3->field_1).Go.z = TD.field_1.Go.y; - (pTVar3->field_1).Move.z = TD.field_1.Go.z; - (pTVar3->field_1).Move.Count = TD.field_1.Move.z; - this->NrToDo = this->NrToDo + 1; - return; -} - - - // WARNING: Unknown calling convention -- yet parameter storage is locked void _GLOBAL__I__ZN9TShortwayC2EP9TCreatureii(void) diff --git a/reference/types.hh b/reference/types.hh index 6840fc3..42caab1 100644 --- a/reference/types.hh +++ b/reference/types.hh @@ -1,15 +1,9 @@ struct TXTEASymmetricKey { int (**_vptr.TXTEASymmetricKey)(...); // VTABLE? - uint8 m_SymmetricKey[16]; + uchar m_SymmetricKey[16]; }; - -// NOTE(fusion): Some minimal processing up until here. Then I realized the file would be huge. -//================================================================================================== -//================================================================================================== -//================================================================================================== - struct TDatabasePoolConnection { TDatabaseConnectionPool *DatabaseConnectionPool; TDatabaseConnection *DatabaseConnection; @@ -131,16 +125,6 @@ struct TDelayedMail { int PacketSize; }; -struct TShortwayPoint { - int x; - int y; - int Waypoints; - int Waylength; - int Heuristic; - struct TShortwayPoint *Predecessor; - struct TShortwayPoint *NextToExpand; -}; - struct TMonsterhome { int Race; int x; @@ -153,8 +137,6 @@ struct TMonsterhome { int Timer; }; - - struct TChannel { ulong Moderator; char ModeratorName[30]; @@ -394,15 +376,3 @@ struct TRSAPrivateKey { struct vlong m_DP; struct vlong m_DQ; }; - -struct TShortway { - struct matrix *Map; - struct TShortwayPoint *FirstToExpand; - struct TCreature *cr; - int VisibleX; - int VisibleY; - int StartX; - int StartY; - int StartZ; - int MinWaypoints; -}; diff --git a/src/connection.hh b/src/connection.hh index 2eafcde..d3a53df 100644 --- a/src/connection.hh +++ b/src/connection.hh @@ -7,50 +7,54 @@ struct TConnection; struct TKnownCreature { - KNOWNCREATURESTATE State; - uint32 CreatureID; - TKnownCreature *Next; - TConnection *Connection; + KNOWNCREATURESTATE State; + uint32 CreatureID; + TKnownCreature *Next; + TConnection *Connection; }; struct TConnection { - uint8 InData[2048]; - int InDataSize; - bool SigIOPending; - bool WaitingForACK; - uint8 OutData[16384]; - uint8 field5_0x4806; - uint8 field6_0x4807; - int NextToSend; - int NextToCommit; - int NextToWrite; - bool Overflow; - bool WillingToSend; - uint8 field12_0x4816; - uint8 field13_0x4817; - TConnection *NextSendingConnection; - uint32 RandomSeed; + void Logout(int Delay, bool StopFight); + + // DATA + // ================= + uint8 InData[2048]; + int InDataSize; + bool SigIOPending; + bool WaitingForACK; + uint8 OutData[16384]; + uint8 field5_0x4806; + uint8 field6_0x4807; + int NextToSend; + int NextToCommit; + int NextToWrite; + bool Overflow; + bool WillingToSend; + uint8 field12_0x4816; + uint8 field13_0x4817; + TConnection *NextSendingConnection; + uint32 RandomSeed; CONNECTIONSTATE State; - pid_t PID; - int Socket; - char IPAddress[16]; - // TXTEASymmetricKey SymmetricKey; // TODO - bool ConnectionIsOk; - bool ClosingIsDelayed; - uint8 field23_0x4852; - uint8 field24_0x4853; - uint32 TimeStamp; - uint32 TimeStampAction; - int TerminalType; - int TerminalVersion; - int TerminalOffsetX; - int TerminalOffsetY; - int TerminalWidth; - int TerminalHeight; - uint32 CharacterID; - char Name[31]; - uint8 field35_0x4897; - TKnownCreature KnownCreatureTable[150]; + pid_t PID; + int Socket; + char IPAddress[16]; + // TXTEASymmetricKey SymmetricKey; // TODO + bool ConnectionIsOk; + bool ClosingIsDelayed; + uint8 field23_0x4852; + uint8 field24_0x4853; + uint32 TimeStamp; + uint32 TimeStampAction; + int TerminalType; + int TerminalVersion; + int TerminalOffsetX; + int TerminalOffsetY; + int TerminalWidth; + int TerminalHeight; + uint32 CharacterID; + char Name[31]; + uint8 field35_0x4897; + TKnownCreature KnownCreatureTable[150]; }; #endif // TIBIA_CONNECTION_HH_ diff --git a/src/containers.hh b/src/containers.hh index 2533445..fafe5b7 100644 --- a/src/containers.hh +++ b/src/containers.hh @@ -137,10 +137,10 @@ struct priority_queue{ delete Entry; } - void insert(K Key, T *Data){ + void insert(K Key, T Data){ this->Entries += 1; int CurrentIndex = this->Entries; - *this->Entry->at(CurrentIndex) = {Key, *Data}; + *this->Entry->at(CurrentIndex) = {Key, Data}; while(CurrentIndex > 1){ int ParentIndex = CurrentIndex / 2; priority_queue_entry *Current = this->Entry->at(CurrentIndex); diff --git a/src/cr.hh b/src/cr.hh index dc9bd7b..8f8e0de 100644 --- a/src/cr.hh +++ b/src/cr.hh @@ -421,7 +421,7 @@ struct TToDoEntry { } Turn; struct{ - uint32 Text; // POINTER? Probably a reference from `AddDynamicString`? + uint32 Text; int Mode; uint32 Addressee; bool CheckSpamming; @@ -434,12 +434,45 @@ struct TToDoEntry { }; struct TCreature: TSkillBase { + // crmain.cc TCreature(void); - void Attack(void); - int Damage(TCreature *Attacker, int Damage, int DamageType); + void SetID(uint32 CharacterID); + void DelID(void); + void SetInCrList(void); + void DelInCrList(void); void StartLogout(bool Force, bool StopFight); + int LogoutPossible(void); void BlockLogout(int Delay, bool BlockProtectionZone); - void ToDoGo(int DestX, int DestY, int DestZ, bool Dest, int MaxSteps); + int GetHealth(void); + int GetSpeed(void); + int Damage(TCreature *Attacker, int Damage, int DamageType); + + // cract.cc + bool SetOnMap(void); + bool DelOnMap(void); + void Attack(void); + void Execute(void); + uint32 CalculateDelay(void); + bool ToDoClear(void); + void ToDoAdd(TToDoEntry TD); + void ToDoStop(void); + void ToDoStart(void); + void ToDoYield(void); + void ToDoWait(int Delay); + void ToDoGo(int DestX, int DestY, int DestZ, bool MustReach, int MaxSteps); + void ToDoRotate(int Direction); + void ToDoMove(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum, + int DestX, int DestY, int DestZ, uint8 Count); + void ToDoMove(Object Obj, int DestX, int DestY, int DestZ, uint8 Count); + void ToDoTrade(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum, + uint32 TradePartner); + void ToDoUse(uint8 Count, int ObjX1, int ObjY1, int ObjZ1, ObjectType Type1, uint8 RNum1, + uint8 Dummy, int ObjX2, int ObjY2, int ObjZ2, ObjectType Type2, uint8 RNum2); + void ToDoUse(uint8 Count, Object Obj1, Object Obj2); + void ToDoTurn(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum); + void ToDoAttack(void); + void ToDoTalk(int Mode, const char *Addressee, const char *Text, bool CheckSpamming); + void ToDoChangeState(int NewState); // VIRTUAL FUNCTIONS // ================= @@ -613,6 +646,9 @@ struct TPlayer: TCreature { void CheckState(void); + void ClearPlayerkillingMarks(void); + void SaveInventory(void); + // VIRTUAL FUNCTIONS // ================= // TODO @@ -658,19 +694,42 @@ struct TPlayer: TCreature { uint32 AddresseesTimes[20]; }; -// Creature API +// crmain.cc // ============================================================================= #define MAX_RACES 512 - -// crmain.cc extern TRaceData RaceData[MAX_RACES]; extern int KilledCreatures[MAX_RACES]; extern int KilledPlayers[MAX_RACES]; +extern priority_queue ToDoQueue; -// TODO(fusion): These probably belong elsewhere but we should come back to -// this when we're wrapping up creature files. bool IsCreaturePlayer(uint32 CreatureID); +TCreature *GetCreature(uint32 CreatureID); +TCreature *GetCreature(Object Obj); +void InsertChainCreature(TCreature *Creature, int CoordX, int CoordY); +void DeleteChainCreature(TCreature *Creature); +void MoveChainCreature(TCreature *Creature, int CoordX, int CoordY); +void ProcessCreatures(void); +void ProcessSkills(void); +void MoveCreatures(int Delay); + void AddKillStatistics(int AttackerRace, int DefenderRace); + +bool IsRaceValid(int Race); int GetRaceByName(const char *RaceName); +// crnonpl.cc +// ============================================================================= +void InitNonplayer(); +void ExitNonplayer(); + +// crplayer.cc +// ============================================================================= +void InitPlayer(void); +void ExitPlayer(void); + +// crskill.cc +// ============================================================================= +void InitCrskill(void); +void ExitCrskill(void); + #endif //TIBIA_CREATURE_HH_ diff --git a/src/cract.cc b/src/cract.cc new file mode 100644 index 0000000..cfbbe95 --- /dev/null +++ b/src/cract.cc @@ -0,0 +1,809 @@ +#include "cr.hh" + +#include "stubs.hh" + +// TShortway +// ============================================================================= +struct TShortwayPoint { + TShortwayPoint(void){ + this->x = 0; + this->y = 0; + this->Waypoints = -1; + this->Waylength = -1; + this->Heuristic = -1; + this->Predecessor = NULL; + this->NextToExpand = NULL; + } + + int x; + int y; + int Waypoints; + int Waylength; + int Heuristic; + TShortwayPoint *Predecessor; + TShortwayPoint *NextToExpand; +}; + +struct TShortway{ + TShortway(TCreature *Creature, int VisibleX, int VisibleY); + ~TShortway(void); + void FillMap(void); + void ClearMap(void); + void Expand(TShortwayPoint *Node); + bool Calculate(int DestX, int DestY, bool MustReach, int MaxSteps); + + // DATA + // ================= + matrix *Map; + TShortwayPoint *FirstToExpand; + TCreature *Creature; + int VisibleX; + int VisibleY; + int StartX; + int StartY; + int StartZ; + int MinWaypoints; +}; + +TShortway::TShortway(TCreature *Creature, int VisibleX, int VisibleY){ + if(Creature == NULL){ + error("TShortway::TShortway: Übergebene Kreatur ist NULL.\n"); + return; + } + + if(VisibleX < 1 || VisibleX > 100 || VisibleY < 1 || VisibleY > 100){ + error("TShortway::TShortway: Ungültiger Sichtbarkeitsbereich %d*%d.\n", VisibleX, VisibleY); + return; + } + + this->Creature = Creature; + this->VisibleX = VisibleX; + this->VisibleY = VisibleY; + this->StartX = Creature->posx; + this->StartY = Creature->posy; + this->StartZ = Creature->posz; + this->Map = new matrix( + -(VisibleX + 1), +(VisibleX + 1), + -(VisibleY + 1), +(VisibleY + 1)); + this->FillMap(); +} + +TShortway::~TShortway(void){ + if(this->Map != NULL){ + delete this->Map; + } +} + +void TShortway::FillMap(void){ + this->MinWaypoints = 1000; + + for(int X = -this->VisibleX; X <= this->VisibleX; X += 1) + for(int Y = -this->VisibleY; Y <= this->VisibleY; Y += 1){ + int FieldX = this->StartX + X; + int FieldY = this->StartY + Y; + int FieldZ = this->StartZ; + + int Waypoints = -1; + Object Obj = GetFirstObject(FieldX, FieldY, FieldZ); + if(Obj.exists()){ + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(BANK) && !ObjType.getFlag(UNPASS)){ + Waypoints = (int)ObjType.getAttribute(WAYPOINTS); + if(Waypoints == 0){ + error("TShortway::FillMap: Ungültiger Wegpunkte-Wert %d für Bank %d.\n", + Waypoints, ObjType.TypeID); + Waypoints = -1; + } + + if(!this->Creature->MovePossible(FieldX, FieldY, FieldZ, false, false)){ + Waypoints = -1; + } + + if(Waypoints > 0 && Waypoints < this->MinWaypoints){ + this->MinWaypoints = Waypoints; + } + } + } + + TShortwayPoint *Node = this->Map->at(X, Y); + Node->x = X; + Node->y = Y; + Node->Waypoints = Waypoints; + } +} + +void TShortway::ClearMap(void){ + for(int X = -this->VisibleX; X <= this->VisibleX; X += 1) + for(int Y = -this->VisibleY; Y <= this->VisibleY; Y += 1){ + TShortwayPoint *Node = this->Map->at(X, Y); + Node->Waylength = INT_MAX; + Node->Heuristic = INT_MAX; + Node->Predecessor = NULL; + Node->NextToExpand = NULL; + } +} + +void TShortway::Expand(TShortwayPoint *Node){ + if(Node == NULL){ + error("TShortway::Expand: Übergebener Knoten ist NULL.\n"); + return; + } + + this->FirstToExpand = Node->NextToExpand; + + int MinNeighborWaylength = Node->Waylength + Node->Waypoints; + if(MinNeighborWaylength >= this->Map->at(0, 0)->Waylength){ + return; + } + + for(int OffsetX = -1; OffsetX <= 1; OffsetX += 1) + for(int OffsetY = -1; OffsetY <= 1; OffsetY += 1){ + if(OffsetX == 0 && OffsetY == 0){ + continue; + } + + TShortwayPoint *Neighbor = this->Map->at(Node->x + OffsetX, Node->y + OffsetY); + + // NOTE(fusion): The minimum neighbor waylength already contains the cost + // of a single step. Diagonal steps are three times more expensive so we + // add waypoints two more times. + int NeighborWaylength = MinNeighborWaylength; + if(OffsetX != 0 && OffsetY != 0){ + NeighborWaylength += Node->Waylength * 2; + } + + if(NeighborWaylength < Neighbor->Waylength){ + Neighbor->Waylength = NeighborWaylength; + Neighbor->Predecessor = Node; + if((Neighbor->x != 0 || Neighbor->y != 0) && Neighbor->Waypoints != -1){ + // NOTE(fusion): Remove from expand list if it was already expanded upon. + if(Neighbor->Heuristic != INT_MAX){ + TShortwayPoint *Prev = NULL; + TShortwayPoint *Cur = this->FirstToExpand; + while(Cur != NULL && Cur != Neighbor){ + Prev = Cur; + Cur = Cur->NextToExpand; + } + + if(Cur != Neighbor){ + error("TShortway::Expand: Knoten steht nicht in der ExpandList.\n"); + }else if(Prev == NULL){ + this->FirstToExpand = Neighbor->NextToExpand; + }else{ + Prev->NextToExpand = Neighbor->NextToExpand; + } + } + + // NOTE(fusion): Compute heuristic using the manhattan distance. + int Distance = std::abs(Neighbor->x) + std::abs(Neighbor->y); + Neighbor->Heuristic = Neighbor->Waylength + + Neighbor->Waypoints * 1 + + this->MinWaypoints * (Distance - 1); + + // NOTE(fusion): Insert into expand list. + { + TShortwayPoint *Prev = NULL; + TShortwayPoint *Cur = this->FirstToExpand; + while(Cur != NULL && Cur->Heuristic < Neighbor->Heuristic){ + Prev = Cur; + Cur = Cur->NextToExpand; + } + + if(Prev == NULL){ + this->FirstToExpand = Neighbor; + }else{ + Prev->NextToExpand = Neighbor; + } + Neighbor->NextToExpand = Cur; + } + } + } + } +} + +bool TShortway::Calculate(int DestX, int DestY, bool MustReach, int MaxSteps){ + if(this->Map == NULL){ + error("TShortway::Calculate: Karte existiert nicht.\n"); + return false; + } + + // NOTE(fusion): Transform dest to relative coordinates. + DestX -= this->StartX; + DestY -= this->StartY; + + // NOTE(fusion): Check if already at destination. + if(DestX == 0 && DestY == 0){ + return true; + } + + // NOTE(fusion): Check if out of range. + if(std::abs(DestX) > this->VisibleX || std::abs(DestY) > this->VisibleY){ + return false; + } + + // NOTE(fusion): Find shortest path from the destination to the origin. + this->ClearMap(); + this->FirstToExpand = this->Map->at(DestX, DestY); + this->FirstToExpand->Waylength = 0; + while(this->FirstToExpand != NULL){ + this->Expand(this->FirstToExpand); + } + + // NOTE(fusion): Check if the origin was reached from the destination. + TShortwayPoint *Node = this->Map->at(0, 0); + if(Node->Waylength == INT_MAX){ + return false; + } + + // NOTE(fusion): Walk back from the origin to reconstruct the path. + Node = Node->Predecessor; + while(Node != NULL && MaxSteps > 0){ + int MaxDistance = std::max( + std::abs(Node->x - DestX), + std::abs(Node->y - DestY)); + if(!MustReach && MaxDistance <= 1){ + break; + } + + TToDoEntry TD = {}; + TD.Code = TDGo; + TD.Go.x = this->StartX + Node->x; + TD.Go.y = this->StartY + Node->y; + TD.Go.z = this->StartZ; + Creature->ToDoAdd(TD); + + Node = Node->Predecessor; + MaxSteps -= 1; + } + + return true; +} + +// TCreature +// ============================================================================= +bool TCreature::SetOnMap(void){ + int LoginX = this->posx; + int LoginY = this->posy; + int LoginZ = this->posz; + bool Player = (this->Type == PLAYER); + if(!SearchLoginField(&LoginX, &LoginY, &LoginZ, 1, Player)){ + bool Found = false; + if(IsHouse(LoginX, LoginY, LoginZ)){ + uint16 HouseID = GetHouseID(LoginX, LoginY, LoginZ); + GetExitPosition(HouseID, &LoginX, &LoginY, &LoginZ); + Found = SearchLoginField(&LoginX, &LoginY, &LoginZ, 1, Player); + } + + if(!Found){ + LoginX = this->startx; + LoginY = this->starty; + LoginZ = this->startz; + } + } + + Object Con = GetMapContainer(LoginX, LoginY, LoginZ); + if(Con == NONE){ + error("TCreature::SetOnMap: Kartencontainer für Punkt [%d,%d,%d] existiert nicht.\n", + LoginX, LoginY, LoginZ); + return false; + } + + this->posx = LoginX; + this->posy = LoginY; + this->posz = LoginZ; + + // NOTE(fusion): `Create` automatically sets `this->CrObject` and creates + // its body container slots. + bool Result = true; + try{ + Create(Con, TYPEID_CREATURE_CONTAINER, this->ID); + }catch(RESULT r){ + error("TCreature::SetOnMap: Kann Kreatur nicht setzen ([%d,%d,%d] - Exception %d).\n", + LoginX, LoginY, LoginZ, r); + if(this->Type == PLAYER){ + SendResult(this->Connection, r); + } + Result = false; + } + return Result; +} + +bool TCreature::DelOnMap(void){ + Object Obj = this->CrObject; + if(Obj == NONE){ + return true; + } + + // TODO(fusion): I feel `Delete` should also manage `this->CrObject` automatically. + bool Result = true; + this->CrObject = NONE; + try{ + Delete(Obj, -1); + }catch(RESULT r){ + error("TCreature::DelOnMap: Error Deleting CreatureObject: %d\n", r); + Result = false; + } + return Result; +} + +void TCreature::Attack(void){ + this->Combat.Attack(); +} + +//void TCreature::Execute(void); + +uint32 TCreature::CalculateDelay(void){ + uint32 Delay = 0; + TToDoEntry *TD = this->ToDoList.at(this->ActToDo); + switch(TD->Code){ + case TDWait:{ + // TODO(fusion): I'm not sure about having `EarliestWalkTime` here. + uint32 WaitTime = TD->Wait.Time; + if(WaitTime < this->EarliestWalkTime){ + WaitTime = this->EarliestWalkTime; + } + + if(WaitTime > ServerMilliseconds){ + Delay = WaitTime - ServerMilliseconds; + } + break; + } + + case TDGo:{ + if(this->EarliestWalkTime > ServerMilliseconds){ + Delay = this->EarliestWalkTime - ServerMilliseconds; + } + break; + } + + case TDUse:{ + if(TD->Use.Obj2 != 0){ + if(this->EarliestMultiuseTime > ServerMilliseconds){ + Delay = this->EarliestMultiuseTime - ServerMilliseconds; + } + } + break; + } + + case TDAttack:{ + uint32 EarliestAttackTime = this->Combat.EarliestAttackTime; + if(EarliestAttackTime < this->EarliestSpellTime){ + EarliestAttackTime = this->EarliestSpellTime; + } + + if(EarliestAttackTime > ServerMilliseconds){ + Delay = EarliestAttackTime - ServerMilliseconds; + } + break; + } + + default:{ + break; + } + } + return Delay; +} + +bool TCreature::ToDoClear(void){ + bool SnapbackNecessary = false; + for(int i = 0; i < this->NrToDo; i += 1){ + TToDoEntry *TD = this->ToDoList.at(i); + switch(TD->Code){ + case TDGo:{ + if(this->ActToDo <= i){ + SnapbackNecessary = true; + } + break; + } + + case TDTalk:{ + DeleteDynamicString(TD->Talk.Text); + DeleteDynamicString(TD->Talk.Addressee); + break; + } + + case TDChangeState:{ + if(this->ActToDo <= i && this->Type == NPC){ + ChangeNPCState(this, TD->ChangeState.NewState, false); + } + break; + } + + default:{ + break; + } + } + } + + this->LockToDo = false; + this->ActToDo = 0; + this->NrToDo = 0; + this->Stop = false; + return SnapbackNecessary; +} + +void TCreature::ToDoAdd(TToDoEntry TD){ + if(this->LockToDo){ + if(this->ToDoClear() && this->Type == PLAYER){ + SendSnapback(this->Connection); + } + } + + *this->ToDoList.at(this->NrToDo) = TD; + this->NrToDo += 1; +} + +void TCreature::ToDoStop(void){ + if(this->LockToDo){ + this->Stop = true; + }else if(this->Type == PLAYER){ + SendSnapback(this->Connection); + } +} + +void TCreature::ToDoStart(void){ + if(this->NrToDo != 0){ + this->LockToDo = true; + this->ActToDo = 0; + + uint32 Delay = this->CalculateDelay(); + if(Delay < 1){ + Delay = 1; + } + + uint32 NextWakeup = ServerMilliseconds + Delay; + ToDoQueue.insert(NextWakeup, this->ID); + this->NextWakeup = NextWakeup; + } +} + +void TCreature::ToDoYield(void){ + if(!this->LockToDo){ + this->ToDoWait(0); + this->ToDoStart(); + } +} + +void TCreature::ToDoWait(int Delay){ + TToDoEntry TD = {}; + TD.Code = TDWait; + TD.Wait.Time = ServerMilliseconds + Delay; + this->ToDoAdd(TD); +} + +void TCreature::ToDoGo(int DestX, int DestY, int DestZ, bool MustReach, int MaxSteps){ + if(this->posz < DestZ){ + throw DOWNSTAIRS; + }else if(this->posz > DestZ){ + throw UPSTAIRS; + } + + if(this->LockToDo){ + TToDoEntry *Last = this->ToDoList.at(this->NrToDo - 1); + if(Last->Code == TDGo + && Last->Go.x == DestX + && Last->Go.y == DestY + && Last->Go.z == DestZ){ + // TODO(fusion): Why? Shouldn't we just return here? + throw NOERROR; + } + } + + int DistanceX = std::abs(DestX - this->posx); + int DistanceY = std::abs(DestY - this->posy); + int MaxDistance = std::max(DistanceX, DistanceY); + if(MaxDistance == 0 || (!MustReach && MaxDistance <= 1)){ + return; + } + + // NOTE(fusion): The number of steps between two points is the same as the + // their manhattan distance, if we exclude diagonal movement. We can skip + // the path finder if we know we're step away from the destination. + if(DistanceX + DistanceY == 1){ + TToDoEntry TD = {}; + TD.Code = TDGo; + TD.Go.x = DestX; + TD.Go.y = DestY; + TD.Go.z = DestZ; + this->ToDoAdd(TD); + }else{ + int VisibleX = (this->Type == PLAYER) ? 7 : 10; + int VisibleY = (this->Type == PLAYER) ? 7 : 10; + TShortway Shortway(this, VisibleX, VisibleY); + if(!Shortway.Calculate(DestX, DestY, MustReach, MaxSteps)){ + this->ToDoClear(); + if(this->Type == PLAYER){ + SendSnapback(this->Connection); + } + throw NOWAY; + } + } +} + +void TCreature::ToDoRotate(int Direction){ + if(Direction != DIRECTION_NORTH + && Direction != DIRECTION_EAST + && Direction != DIRECTION_SOUTH + && Direction != DIRECTION_WEST){ + throw ERROR; + } + + TToDoEntry TD = {}; + TD.Code = TDRotate; + TD.Rotate.Direction = Direction; + this->ToDoAdd(TD); +} + +void TCreature::ToDoMove(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum, + int DestX, int DestY, int DestZ, uint8 Count){ + Object Obj = GetObject(this->ID, ObjX, ObjY, ObjZ, RNum, Type); + if(!Obj.exists()){ + throw NOTACCESSIBLE; + } + + // TODO(fusion): This could be an inlined function. + if(ObjX != 0xFFFF){ // SPECIAL_COORDINATE ? + if(this->posz > ObjZ){ + throw UPSTAIRS; + }else if(this->posz < ObjZ){ + throw DOWNSTAIRS; + } + + if(!ObjectInRange(this->ID, Obj, 1)){ + this->ToDoGo(ObjX, ObjY, ObjZ, false, INT_MAX); + } + } + + int Delay = 100; + if(Obj.getObjectType().isCreatureContainer()){ + Object DestBank = GetFirstObject(DestX, DestY, DestZ); + if(DestBank == NONE || !DestBank.getObjectType().getFlag(BANK)){ + throw NOTACCESSIBLE; + } + + TCreature *Creature = GetCreature(Obj); + if(Creature == NULL){ + error("TCreature::ToDoMove: Kreatur existiert nicht.\n"); + throw ERROR; + } + + Delay = 1000; + if(this->EarliestWalkTime > ServerMilliseconds){ + Delay += (int)(this->EarliestWalkTime - ServerMilliseconds); + } + } + + this->ToDoWait(Delay); + + TToDoEntry TD = {}; + TD.Code = TDMove; + TD.Move.Obj = Obj.ObjectID; + TD.Move.x = DestX; + TD.Move.y = DestY; + TD.Move.z = DestZ; + TD.Move.Count = Count; + this->ToDoAdd(TD); +} + +void TCreature::ToDoMove(Object Obj, int DestX, int DestY, int DestZ, uint8 Count){ + if(!Obj.exists()){ + throw NOTACCESSIBLE; + } + + if(!ObjectInRange(this->ID, Obj, 1)){ + this->ToDoGo(DestX, DestY, DestZ, false, INT_MAX); + } + + int Delay = 100; + if(Obj.getObjectType().isCreatureContainer()){ + // TODO(fusion): We don't add the delay until the earliest walk time + // like in the other variant above. + Delay = 1000; + } + + this->ToDoWait(Delay); + + TToDoEntry TD = {}; + TD.Code = TDMove; + TD.Move.Obj = Obj.ObjectID; + TD.Move.x = DestX; + TD.Move.y = DestY; + TD.Move.z = DestZ; + TD.Move.Count = Count; + this->ToDoAdd(TD); +} + +void TCreature::ToDoTrade(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum, + uint32 TradePartner){ + Object Obj = GetObject(this->ID, ObjX, ObjY, ObjZ, RNum, Type); + if(!Obj.exists()){ + throw NOTACCESSIBLE; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.getFlag(UNMOVE)){ + throw NOTMOVABLE; + } + + if(!ObjType.getFlag(TAKE)){ + throw NOTTAKABLE; + } + + if(ObjType.isCreatureContainer()){ + error("TCreature::ToDoTrade: Objekt ist eine Kreatur.\n"); + throw ERROR; + } + + if(TradePartner == 0){ + error("TCreature::ToDoTrade: Handelspartner ist Null.\n"); + throw ERROR; + } + + TCreature *Creature = GetCreature(TradePartner); + if(Creature == NULL){ + throw PLAYERNOTONLINE; + } + + if(Creature->Type != PLAYER){ + error("TCreature::ToDoTrade: Handelspartner von %s ist kein Spieler.\n", this->Name); + throw ERROR; + } + + // TODO(fusion): This could be an inlined function. + if(ObjX != 0xFFFF){ // SPECIAL_COORDINATE ? + if(this->posz > ObjZ){ + throw UPSTAIRS; + }else if(this->posz < ObjZ){ + throw DOWNSTAIRS; + } + + if(!ObjectInRange(this->ID, Obj, 1)){ + this->ToDoGo(ObjX, ObjY, ObjZ, false, INT_MAX); + } + } + + TToDoEntry TD = {}; + TD.Code = TDTrade; + TD.Trade.Obj = Obj.ObjectID; + TD.Trade.Partner = TradePartner; + this->ToDoAdd(TD); +} + +void TCreature::ToDoUse(uint8 Count, int ObjX1, int ObjY1, int ObjZ1, ObjectType Type1, uint8 RNum1, + uint8 Dummy, int ObjX2, int ObjY2, int ObjZ2, ObjectType Type2, uint8 RNum2){ + Object Obj1 = GetObject(this->ID, ObjX1, ObjY1, ObjZ1, RNum1, Type1); + if(!Obj1.exists()){ + throw NOTACCESSIBLE; + } + + Object Obj2 = NONE; + if(Count >= 2){ + Obj2 = GetObject(this->ID, ObjX2, ObjY2, ObjZ2, RNum2, Type2); + if(!Obj2.exists()){ + throw NOTACCESSIBLE; + } + } + + // TODO(fusion): This could be an inlined function. + if(ObjX1 != 0xFFFF){ // SPECIAL_COORDINATE ? + if(this->posz > ObjZ1){ + throw UPSTAIRS; + }else if(this->posz < ObjZ1){ + throw DOWNSTAIRS; + } + + if(!ObjectInRange(this->ID, Obj1, 1)){ + this->ToDoGo(ObjX1, ObjY1, ObjZ1, false, INT_MAX); + } + } + + this->ToDoWait(100); + + TToDoEntry TD = {}; + TD.Code = TDUse; + TD.Use.Obj1 = Obj1.ObjectID; + TD.Use.Obj2 = Obj2.ObjectID; + // TODO(fusion): This is the value sent by the client on single object use + // that contains the next free container index. + TD.Use.Dummy = Dummy; + this->ToDoAdd(TD); +} + +void TCreature::ToDoUse(uint8 Count, Object Obj1, Object Obj2){ + if(!Obj1.exists()){ + throw NOTACCESSIBLE; + } + + if(Count <= 1){ + Obj2 = NONE; + }else if(!Obj2.exists()){ + throw NOTACCESSIBLE; + } + + if(!ObjectInRange(this->ID, Obj1, 1)){ + int ObjX1, ObjY1, ObjZ1; + GetObjectCoordinates(Obj1, &ObjX1, &ObjY1, &ObjZ1); + this->ToDoGo(ObjX1, ObjY1, ObjZ1, false, INT_MAX); + } + + this->ToDoWait(100); + + TToDoEntry TD = {}; + TD.Code = TDUse; + TD.Use.Obj1 = Obj1.ObjectID; + TD.Use.Obj2 = Obj2.ObjectID; + // TODO(fusion): Not sure why we set this value at all. + TD.Use.Dummy = Count; + this->ToDoAdd(TD); +} + +void TCreature::ToDoTurn(int ObjX, int ObjY, int ObjZ, ObjectType Type, uint8 RNum){ + Object Obj = GetObject(this->ID, ObjX, ObjY, ObjZ, RNum, Type); + if(!Obj.exists()){ + throw NOTACCESSIBLE; + } + + // TODO(fusion): This could be an inlined function. + if(ObjX != 0xFFFF){ // SPECIAL_COORDINATE ? + if(this->posz > ObjZ){ + throw UPSTAIRS; + }else if(this->posz < ObjZ){ + throw DOWNSTAIRS; + } + + if(!ObjectInRange(this->ID, Obj, 1)){ + this->ToDoGo(ObjX, ObjY, ObjZ, false, INT_MAX); + } + } + + this->ToDoWait(100); + + TToDoEntry TD = {}; + TD.Code = TDTurn; + TD.Turn.Obj = Obj.ObjectID; + this->ToDoAdd(TD); +} + +void TCreature::ToDoAttack(void){ + this->Combat.CanToDoAttack(); + if(this->Combat.GetDistance() != 1){ + this->ToDoWait(100); + } + + TToDoEntry TD = {}; + TD.Code = TDAttack; + this->ToDoAdd(TD); +} + +void TCreature::ToDoTalk(int Mode, const char *Addressee, const char *Text, bool CheckSpamming){ + TToDoEntry TD = {}; + + if(Text == NULL || Text[0] == 0){ + error("TCreature::ToDoTalk: Text ist NULL bei %s.\n", this->Name); + + // TODO(fusion): The original code would attempt to call `AddDynamicString` + // even after this check but it doesn't check whether `Text` is NULL and + // calls `strlen` immediately on it which could be a problem. + TD.Talk.Text = 0; + }else{ + TD.Talk.Text = AddDynamicString(Text); + } + + if(Addressee == NULL){ + TD.Talk.Addressee = 0; + }else{ + TD.Talk.Addressee = AddDynamicString(Addressee); + } + + TD.Code = TDTalk; + TD.Talk.Mode = Mode; + TD.Talk.CheckSpamming = CheckSpamming; + this->ToDoAdd(TD); +} + +void TCreature::ToDoChangeState(int NewState){ + TToDoEntry TD = {}; + TD.Code = TDChangeState; + TD.ChangeState.NewState = NewState; + this->ToDoAdd(TD); +} diff --git a/src/crcombat.cc b/src/crcombat.cc index 9edfe9b..dd732e3 100644 --- a/src/crcombat.cc +++ b/src/crcombat.cc @@ -307,11 +307,11 @@ int TCombat::GetArmorStrength(void){ int TCombat::GetDistance(void){ int Distance = 0; if(this->Close != NONE || this->Fist){ - Distance = 1; + Distance = 1; // DISTANCE_CLOSE ? }else if(this->Throw != NONE){ - Distance = 2; + Distance = 2; // DISTANCE_THROW ? }else if(this->Missile != NONE || this->Wand != NONE){ - Distance = 3; + Distance = 3; // DISTANCE_RANGE ? } return Distance; } diff --git a/src/crmain.cc b/src/crmain.cc index d962bf9..49348d8 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -1,22 +1,23 @@ #include "cr.hh" +#include "config.hh" #include "enums.hh" +#include "info.hh" #include "stubs.hh" -static uint32 NextCreatureID; -static matrix *FirstChainCreature; -static TCreature *HashList[1000]; - -static int FirstFreeCreature; -static vector CreatureList(0, 10000, 1000); - -static priority_queue ToDoQueue(5000, 1000); -//static priority_queue AttackWaveQueue(100, 100); - TRaceData RaceData[MAX_RACES]; int KilledCreatures[MAX_RACES]; int KilledPlayers[MAX_RACES]; +priority_queue ToDoQueue(5000, 1000); +//priority_queue AttackWaveQueue(100, 100); + +static uint32 NextCreatureID; +static int FirstFreeCreature; +static TCreature *HashList[1000]; +static matrix *FirstChainCreature; +static vector CreatureList(0, 10000, 1000); + // TCreature // ============================================================================= TCreature::TCreature(void) : @@ -67,8 +68,286 @@ TCreature::TCreature(void) : } } -void TCreature::Attack(void){ - this->Combat.Attack(); +TCreature::~TCreature(void){ + // TODO(fusion): Bruuhh... these exceptions... + if(this->IsDead){ + int Race = this->Race; + int PoolLiquid = LIQUID_NONE; + if(RaceData[Race].Blood == BT_BLOOD){ + PoolLiquid = LIQUID_BLOOD; + }else if(RaceData[Race].Blood == BT_SLIME){ + PoolLiquid = LIQUID_SLIME; + } + + if(PoolLiquid != LIQUID_NONE){ + try{ + CreatePool(GetMapContainer(this->CrObject), + GetSpecialObject(BLOOD_POOL), + PoolLiquid); + }catch(RESULT r){ + if(r != NOROOM && r != DESTROYED){ + error("TCreature::~TCreature: Kann Blutlache nicht setzen (Exc %d, Pos [%d,%d,%d]).\n", + r, this->posx, this->posy, this->posz); + } + } + } + + ObjectType CorpseType = (this->Sex == 1) // MALE ? + ? RaceData[Race].MaleCorpse + : RaceData[Race].FemaleCorpse; + + if(CorpseType.getFlag(MAGICFIELD)){ + Object Obj = GetFirstObject(this->posx, this->posy, this->posz); + while(Obj != NONE){ + Object Next = Obj.getNextObject(); + if(Obj.getObjectType().getFlag(MAGICFIELD)){ + try{ + Delete(Obj, -1); + }catch(RESULT r){ + error("TCreature::~TCreature: Exception %d beim Löschen eines Feldes.\n", r); + } + } + Obj = Next; + } + } + + try{ + Object Con = GetMapContainer(this->posx, this->posy, this->posz); + Object Corpse = Create(Con, CorpseType, 0); + Log("game", "Tod von %s: LoseInventory=%d.\n", this->Name, this->LoseInventory); + + if(this->Type == PLAYER){ + char Help[128]; + sprintf(Help, "You recognize %s", this->Name); + if(this->Murderer[0] != 0){ + if(this->Sex == 1){ // MALE ? + strcat(Help, ". He was killed by "); + }else{ + strcat(Help, ". She was killed by "); + } + strcat(Help, this->Murderer); + } + Change(Corpse, TEXTSTRING, AddDynamicString(Help)); + } + + if(this->LoseInventory != 0){ // LOSE_INVENTORY_NONE ? + for(int Position = 1; Position <= 10; Position += 1){ + Object Item = GetBodyObject(this->ID, Position); + if(Item == NONE){ + continue; + } + + if(this->LoseInventory != 2 // LOSE_INVENTORY_ALL ? + && !Item.getObjectType().getFlag(CONTAINER) + && random(0, 9) != 0){ + continue; + } + + Move(0, Item, Corpse, -1, false, NONE); + } + } + + if(this->Type == PLAYER && this->LoseInventory != 2){ // LOSE_INVENTORY_ALL ? + ((TPlayer*)this)->SaveInventory(); + } + }catch(RESULT r){ + error("TCreature::~TCreature: Kann Leiche/Inventory nicht ablegen (Exc %d, Pos [%d,%d,%d], %s).\n", + r, this->posx, this->posy, this->posz, this->Name); + } + } + + if(this->CrObject != NONE && this->CrObject.exists()){ + this->DelOnMap(); + } + + this->ToDoClear(); + + if(this->Type == PLAYER && this->Connection != NULL){ + this->Connection->Logout(30, true); + } + + this->DelInCrList(); + + if(this->ID != 0){ + this->DelID(); + } + + for(TKnownCreature *KnownCreature = this->FirstKnowingConnection; + KnownCreature != NULL; + KnownCreature = KnownCreature->Next){ + if(KnownCreature->CreatureID != this->ID){ + error("TCreature::~TCreature: Verkettungsfehler bei Kreatur %u.\n", this->ID); + } + KnownCreature->State = KNOWNCREATURE_FREE; + } +} + +void TCreature::SetID(uint32 CharacterID){ + if(this->ID != 0){ + error("TCreature::SetID: ID ist schon gesetzt.\n"); + } + + uint32 CreatureID = 0; + if(CharacterID == 0){ + bool Found = false; + for(int Attempts = 0; Attempts < 16; Attempts += 1){ + CreatureID = NextCreatureID++; + if(GetCreature(CreatureID) == NULL){ + Found = true; + break; + } + } + + if(!Found){ + error("TCreature::SetID: 16x hintereinander doppelte ID." + " Verwende nun doppelte ID %d\n", CreatureID); + } + }else{ + CreatureID = CharacterID; + if(GetCreature(CreatureID) != NULL){ + error("TCreature::SetID: Doppelte Character-ID %d gefunden.\n", CharacterID); + } + } + + uint32 ListIndex = CreatureID % NARRAY(HashList); + this->ID = CreatureID; + this->NextHashEntry = HashList[ListIndex]; + HashList[ListIndex] = this; +} + +void TCreature::DelID(void){ + uint32 ListIndex = this->ID % NARRAY(HashList); + TCreature *First = HashList[ListIndex]; + if(First == NULL){ + error("TCreature::DelID: Hasheintrag nicht gefunden id = %d\n", this->ID); + return; + } + + if(First->ID == this->ID){ + HashList[ListIndex] = this->NextHashEntry; + }else{ + TCreature *Prev = First; + TCreature *Current = First->NextHashEntry; + while(true){ + if(Current == NULL){ + error("TCreature::DelID: id=%d nicht gefunden.\n", this->ID); + return; + } + + if(Current->ID == this->ID){ + Prev->NextHashEntry = this->NextHashEntry; + break; + } + + Prev = Current; + Current = Current->NextHashEntry; + } + } +} + +void TCreature::SetInCrList(void){ + *CreatureList.at(FirstFreeCreature) = this; + FirstFreeCreature += 1; +} + +void TCreature::DelInCrList(void){ + // TODO(fusion): See note in `ProcessCreatures`. + for(int Index = 0; Index < FirstFreeCreature; Index += 1){ + TCreature **Current = CreatureList.at(Index); + if(*Current == this){ + TCreature **Last = CreatureList.at(FirstFreeCreature - 1); + *Current = *Last; + *Last = NULL; + FirstFreeCreature -= 1; + + // TODO(fusion): The original function wouldn't break here. Maybe it + // is possible to have duplicates in `CreatureList`? + //break; + } + } +} + +void TCreature::StartLogout(bool Force, bool StopFight){ + this->LoggingOut = true; + if(Force || LagDetected()){ + this->LogoutAllowed = true; + } + + if(this->Type == PLAYER && this->Connection != NULL){ + this->Connection->Logout(0, true); + } + + this->Combat.StopAttack(StopFight ? 0 : 60); +} + +int TCreature::LogoutPossible(void){ + if(!this->LogoutAllowed && !this->IsDead && !GameEnding()){ + if(this->EarliestLogoutRound > RoundNr && !LagDetected()){ + return 1; // LOGOUT_COMBAT ? + } + + if(IsNoLogoutField(this->posx, this->posy, this->posz)){ + return 2; // LOGOUT_FIELD ? + } + + this->LogoutAllowed = true; + } + + return 0; // LOGOUT_OK ? +} + +void TCreature::BlockLogout(int Delay, bool BlockProtectionZone){ + if(WorldType == NON_PVP){ + BlockProtectionZone = false; + } + + if(this->Type == PLAYER && !CheckRight(this->ID, NO_LOGOUT_BLOCK)){ + if(BlockProtectionZone || this->EarliestProtectionZoneRound > RoundNr){ + uint32 EarliestProtectionZoneRound = RoundNr + Delay; + if(this->EarliestProtectionZoneRound < EarliestProtectionZoneRound){ + this->EarliestProtectionZoneRound = EarliestProtectionZoneRound; + } + }else if(this->Connection == NULL){ + // NOTE(fusion): This is a failsafe to avoid extending the earliest + // logout round of a player that got disconnected in combat. + return; + } + + uint32 EarliestLogoutRound = RoundNr + Delay; + if(this->EarliestLogoutRound < EarliestLogoutRound){ + this->EarliestLogoutRound = EarliestLogoutRound; + } + + ((TPlayer*)this)->CheckState(); + } +} + +int TCreature::GetHealth(void){ + int MaxHitPoints = this->Skills[SKILL_HITPOINTS]->Max; + if(MaxHitPoints <= 0){ + if(!this->IsDead){ + error("TCreature::GetHealth: MaxHitpoints von %s ist %d, obwohl sie nicht tot ist.\n", + this->Name, MaxHitPoints); + } + return 0; + } + + int CurrentHitPoints = this->Skills[SKILL_HITPOINTS]->Get(); + int Health = CurrentHitPoints * 100 / MaxHitPoints; + if(Health <= 0){ + Health = (int)(CurrentHitPoints != 0); + } + return Health; +} + +int TCreature::GetSpeed(void){ + TSkill *GoStrength = this->Skills[SKILL_GO_STRENGTH]; + if(GoStrength == NULL){ + error("TCreature::GetSpeed: Kein Skill GOSTRENGTH vorhanden.\n"); + return 0; + } + + return GoStrength->Get() * 2 + 80; } int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){ @@ -462,13 +741,143 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){ return Damage; } +void TCreature::Death(void){ + this->IsDead = true; + this->LoggingOut = true; +} + +bool TCreature::MovePossible(int x, int y, int z, bool Execute, bool Jump){ + bool Result; + + if(Jump){ + Result = JumpPossible(x, y, z, false); + }else{ + Result = CoordinateFlag(x, y, z, BANK) + && !CoordinateFlag(x, y, z, UNPASS); + } + + if(Result && !Execute && CoordinateFlag(x, y, z, AVOID)){ + Result = false; + } + + return Result; +} + +bool TCreature::IsPeaceful(void){ + return true; +} + +uint32 TCreature::GetMaster(void){ + return 0; +} + +void TCreature::TalkStimulus(uint32 SpeakerID, const char *Text){ + // no-op +} + +void TCreature::DamageStimulus(uint32 AttackerID, int Damage, int DamageType){ + // no-op +} + +void TCreature::IdleStimulus(void){ + // no-op +} + +void TCreature::CreatureMoveStimulus(uint32 CreatureID, int Type){ + if(CreatureID == 0 || CreatureID == this->ID + || this->IsDead + || this->Combat.AttackDest != CreatureID + || this->Combat.ChaseMode != CHASE_MODE_CLOSE + || this->Combat.EarliestAttackTime <= (ServerMilliseconds + 200)){ + return; + } + + // TODO(fusion): Find out what `Type` is here. + if(Type != 2 // STIMULUS_TYPE?? + || !this->LockToDo + || this->ActToDo >= this->NrToDo + || this->ToDoList.at(this->ActToDo)->Code != TDAttack){ + return; + } + + TCreature *Target = GetCreature(this->Combat.AttackDest); + if(Target == NULL){ + return; + } + + int Distance = ObjectDistance(this->CrObject, Target->CrObject); + if(Distance <= 1){ + return; + } + + // TODO(fusion): Review this. + try{ + if(this->ToDoClear() && this->Type == PLAYER){ + SendSnapback(this->Connection); + } + this->ToDoWait(200); + this->ToDoAttack(); + this->ToDoStart(); + }catch(RESULT r){ + if(this->Type == PLAYER){ + SendResult(this->Connection, r); + } + this->ToDoClear(); + this->ToDoWait(this->Combat.EarliestAttackTime); + this->ToDoStart(); + } +} + +void TCreature::AttackStimulus(uint32 AttackerID){ + // no-op +} + // Creature Management // ============================================================================= bool IsCreaturePlayer(uint32 CreatureID){ return CreatureID < 0x40000000; } -// +TCreature *GetCreature(uint32 CreatureID){ + if(CreatureID == 0){ + return NULL; + } + + TCreature *Creature = HashList[CreatureID % NARRAY(HashList)]; + while(Creature != NULL && Creature->ID != CreatureID){ + Creature = Creature->NextHashEntry; + } + + return Creature; +} + +TCreature *GetCreature(Object Obj){ + return GetCreature(Obj.getCreatureID()); +} + +void InsertChainCreature(TCreature *Creature, int CoordX, int CoordY){ + if(Creature == NULL){ + // TODO(fusion): Maybe a typo on the name of the function? I thought it + // could be some type of macro because there was no function name mismatch + // until now. + error("DeleteChainCreature: Übegebene Kreatur existiert nicht.\n"); + return; + } + + if(CoordX == 0){ + CoordX = Creature->posx; + } + + if(CoordY == 0){ + CoordY = Creature->posy; + } + + int ChainX = CoordX / 16; + int ChainY = CoordY / 16; + uint32 *FirstID = FirstChainCreature->at(ChainX, ChainY); + Creature->NextChainCreature = *FirstID; + *FirstID = Creature->ID; +} void DeleteChainCreature(TCreature *Creature){ if(Creature == NULL){ @@ -479,9 +888,9 @@ void DeleteChainCreature(TCreature *Creature){ // NOTE(fusion): All creatures in each 16x16 region form a creature linked // list, despite its current floor. Whether that is a good idea is a whole // other matter. - int BlockX = Creature->posx / 16; - int BlockY = Creature->posy / 16; - uint32 *FirstID = FirstChainCreature->at(BlockX, BlockY); + int ChainX = Creature->posx / 16; + int ChainY = Creature->posy / 16; + uint32 *FirstID = FirstChainCreature->at(ChainX, ChainY); if(*FirstID == Creature->ID){ *FirstID = Creature->NextChainCreature; @@ -509,8 +918,112 @@ void DeleteChainCreature(TCreature *Creature){ } } +void MoveChainCreature(TCreature *Creature, int CoordX, int CoordY){ + if(Creature == NULL){ + error("DeleteChainCreature: Übegebene Kreatur existiert nicht.\n"); + return; + } + + int NewChainX = CoordX / 16; + int NewChainY = CoordY / 16; + int OldChainX = Creature->posx / 16; + int OldChainY = Creature->posy / 16; + + if(NewChainX != OldChainX || NewChainY != OldChainY){ + DeleteChainCreature(Creature); + InsertChainCreature(Creature, CoordX, CoordY); + } +} + +void ProcessCreatures(void){ + for(int Index = 0; Index < FirstFreeCreature; Index += 1){ + TCreature *Creature = *CreatureList.at(Index); + if(Creature == NULL){ + error("ProcessCreatures: Kreatur %d existiert nicht.\n", Index); + 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 FoodRegen = Creature->Skills[SKILL_FED]->Get(); + if(FoodRegen > 0 && (RoundNr % FoodRegen) == 0 && !Creature->IsDead + && !IsProtectionZone(Creature->posx, Creature->posy, Creature->posz)){ + Creature->Skills[SKILL_HITPOINTS]->Change(1); + Creature->Skills[SKILL_MANA]->Change(4); + if(Creature->Type == PLAYER){ + SendPlayerData(Creature->Connection); + } + } + + if(Creature->Type == PLAYER){ + if(Creature->Connection != NULL){ + ((TPlayer*)Creature)->CheckState(); + } + + if(Creature->EarliestLogoutRound != 0 && Creature->EarliestLogoutRound <= RoundNr){ + ((TPlayer*)Creature)->ClearPlayerkillingMarks(); + Creature->EarliestLogoutRound = 0; + } + } + + if(!Creature->IsDead && Creature->Skills[SKILL_HITPOINTS]->Get() <= 0){ + error("ProcessCreatures: Kreatur %s ist nicht tot, obwohl sie keine HP mehr hat.\n", Creature->Name); + Creature->Death(); + } + + if(Creature->LoggingOut && Creature->LogoutPossible() == 0){ // LOGOUT_POSSIBLE ? + if(Creature->IsDead && Creature->Skills[SKILL_HITPOINTS]->Get() > 0){ + error("ProcessCreatures: Kreatur %s hat HP, obwohl sie tot ist.\n", Creature->Name); + Creature->Skills[SKILL_HITPOINTS]->Set(0); + } + + // TODO(fusion): Creatures are removed from `CreatureList` with a swap + // and pop. Since we're iterating it RIGHT NOW, we need to process the + // the current index AGAIN because it'll now contain the creature that + // was previously at the end of the list. The annoying part here is that + // this removal occurs implicitly in the creature's destructor. + delete Creature; + Index -= 1; + } + } +} + +void ProcessSkills(void){ + for(int Index = 0; Index < FirstFreeCreature; Index += 1){ + TCreature *Creature = *CreatureList.at(Index); + if(Creature == NULL){ + error("ProcessSkills: Kreatur %d existiert nicht.\n", Index); + continue; + } + + Creature->ProcessSkills(); + } +} + +void MoveCreatures(int Delay){ + ServerMilliseconds += Delay; + while(ToDoQueue.Entries > 0){ + auto Entry = *ToDoQueue.Entry->at(1); + uint32 ExecutionTime = Entry.Key; + uint32 CreatureID = Entry.Data; + if(ExecutionTime > ServerMilliseconds){ + break; + } + + ToDoQueue.deleteMin(); + TCreature *Creature = GetCreature(CreatureID); + if(Creature != NULL){ + Creature->Execute(); + } + } +} + // Kill Statistics // ============================================================================= +void InitKillStatistics(void);//TODO +void ExitKillStatistics(void);//TODO void AddKillStatistics(int AttackerRace, int DefenderRace){ // NOTE(fusion): I think the race name can be "human" only for players, // which means we're probably tracking how many creatures are killed by @@ -572,9 +1085,13 @@ TRaceData::TRaceData(void) : this->Spells = 0; } +bool IsRaceValid(int Race){ + return Race >= 1 && Race < MAX_RACES; +} + int GetRaceByName(const char *RaceName){ int Result = 0; - for(int Race = 1; Race < NARRAY(RaceData); Race += 1){ + for(int Race = 1; Race < MAX_RACES; Race += 1){ if(stricmp(RaceName, RaceData[Race].Name) == 0){ Result = Race; break; @@ -583,7 +1100,35 @@ int GetRaceByName(const char *RaceName){ return Result; } -// Raid +void LoadRaces(void); //TODO + +// Monster Raid // ============================================================================= +void LoadMonsterRaids(void); //TODO +// Initialization +// ============================================================================= +void InitCr(void){ + NextCreatureID = 0x40000000; + FirstFreeCreature = 0; + FirstChainCreature = new matrix( + SectorXMin * 2, SectorXMax * 2 + 1, + SectorYMin * 2, SectorYMax * 2 + 1, + 0); + LoadRaces(); + LoadMonsterRaids(); + InitCrskill(); + InitPlayer(); + InitNonplayer(); + InitKillStatistics(); +} + +void ExitCr(void){ + ExitKillStatistics(); + ExitPlayer(); + ExitNonplayer(); + ExitCrskill(); + + delete FirstChainCreature; +} diff --git a/src/crskill.cc b/src/crskill.cc index d2eb067..8e259a8 100644 --- a/src/crskill.cc +++ b/src/crskill.cc @@ -1159,7 +1159,7 @@ bool TSkillBase::NewSkill(uint16 SkillNo, TCreature *Creature){ } bool TSkillBase::SetSkills(int Race){ - if(Race < 0 || Race >= NARRAY(RaceData)){ + if(!IsRaceValid(Race)){ error("TSkillBase::SetSkills: Ungültige Rassennummer %d.\n", Race); return false; } @@ -1250,3 +1250,13 @@ void TSkillBase::DelTimer(uint16 SkNr){ } } } + +// Initialization +//============================================================================== +void InitCrskill(void){ + // no-op +} + +void ExitCrskill(void){ + // no-op +} diff --git a/src/magic.cc b/src/magic.cc index ea1ba73..53ec1da 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -372,8 +372,7 @@ TSummonImpact::TSummonImpact(TCreature *Actor, int Race, int Maximum){ error("TSummonImpact::TSummonImpact: Actor ist NULL.\n"); } - // TODO(fusion): I think there might be a `IsRaceValid` function that was inlined. - if(Race < 0 || Race >= NARRAY(RaceData)){ + if(!IsRaceValid(Race)){ error("TSummonImpact::TSummonImpact: Ungültige Rassennummer %d.\n", Race); } @@ -387,7 +386,7 @@ void TSummonImpact::handleField(int x, int y, int z){ int Race = this->Race; int Maximum = this->Maximum; if(Actor != NULL - && Race >= 0 && Race < NARRAY(RaceData) + && IsRaceValid(Race) && Actor->SummonedCreatures < Maximum){ int x, y, z; if(SearchSummonField(&x, &y, &z, 2)){ @@ -1870,7 +1869,7 @@ void SummonCreature(TCreature *Actor, int ManaPoints, int Race, bool God){ throw ERROR; } - if(Race < 1 || Race >= NARRAY(RaceData)){ + if(!IsRaceValid(Race)){ error("SummonCreature: Ungültige Rassennummer %d übergeben.\n", Race); throw ERROR; } diff --git a/src/map.cc b/src/map.cc index d3336c3..9ce568d 100644 --- a/src/map.cc +++ b/src/map.cc @@ -8,21 +8,21 @@ #include -static int OBCount; -static int SectorXMin; -static int SectorXMax; -static int SectorYMin; -static int SectorYMax; -static int SectorZMin; -static int SectorZMax; -static int RefreshedCylinders; -static int NewbieStartPositionX; -static int NewbieStartPositionY; -static int NewbieStartPositionZ; -static int VeteranStartPositionX; -static int VeteranStartPositionY; -static int VeteranStartPositionZ; +int SectorXMin; +int SectorXMax; +int SectorYMin; +int SectorYMax; +int SectorZMin; +int SectorZMax; +int RefreshedCylinders; +int NewbieStartPositionX; +int NewbieStartPositionY; +int NewbieStartPositionZ; +int VeteranStartPositionX; +int VeteranStartPositionY; +int VeteranStartPositionZ; +static int OBCount; static matrix3d *Sector; static TObjectBlock **ObjectBlock; static TObject *FirstFreeObject; diff --git a/src/map.hh b/src/map.hh index eafcb1a..e1a9e22 100644 --- a/src/map.hh +++ b/src/map.hh @@ -97,6 +97,21 @@ struct TCronEntry { int Next; }; +// NOTE(fusion): Map config values. +extern int SectorXMin; +extern int SectorXMax; +extern int SectorYMin; +extern int SectorYMax; +extern int SectorZMin; +extern int SectorZMax; +extern int RefreshedCylinders; +extern int NewbieStartPositionX; +extern int NewbieStartPositionY; +extern int NewbieStartPositionZ; +extern int VeteranStartPositionX; +extern int VeteranStartPositionY; +extern int VeteranStartPositionZ; + // NOTE(fusion): Cron management functions. Most for internal use. Object CronCheck(void); void CronExpire(Object Obj, int Delay); diff --git a/src/stubs.hh b/src/stubs.hh index 030f502..fa7f0d2 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -18,6 +18,7 @@ extern void AbortWriter(void); extern void AnnounceChangedCreature(uint32 CreatureID, int Type); extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3); extern void Change(Object Obj, ObjectType NewType, uint32 Value); +extern void ChangeNPCState(TCreature *Npc, int NewState, bool Stimulus); extern void CharacterDeathOrder(TCreature *Creature, int OldLevel, uint32 Offender, const char *Remark, bool Unjustified); extern bool CheckRight(uint32 CreatureID, RIGHT Right); @@ -33,11 +34,11 @@ extern void CreatePool(Object Con, ObjectType Type, uint32 Value); extern void Delete(Object Obj, int Count); extern bool FieldPossible(int x, int y, int z, int FieldType); extern Object GetBodyObject(uint32 CreatureID, int Position); -extern TCreature *GetCreature(uint32 CreatureID); -extern TCreature *GetCreature(Object Obj); +extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z); extern TConnection *GetFirstConnection(void); extern TConnection *GetNextConnection(void); extern const char *GetName(Object Obj); +extern Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type); extern TPlayer *GetPlayer(uint32 CreatureID); extern bool GetRaceNoConvince(int Race); extern bool GetRaceNoIllusion(int Race); @@ -51,25 +52,24 @@ extern void GraphicalEffect(Object Obj, int Type); extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player); extern void InitLog(const char *ProtocolName); extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest); +extern bool LagDetected(void); extern void LoadMonsterRaid(const char *FileName, int Start, bool *Type, int *Date, int *Interval, int *Duration); extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3); extern void LogoutAllPlayers(void); extern void Missile(Object Start, Object Dest, int Type); extern void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Object Ignore); -extern void MoveCreatures(int Delay); extern void NetLoadCheck(void); extern void NetLoadSummary(void); extern void NotifyAllCreatures(Object Obj, int Type, Object OldCon); extern int ObjectDistance(Object Obj1, Object Obj2); +extern bool ObjectInRange(uint32 CreatureID, Object Obj, int Range); extern void ProcessCommunicationControl(void); extern void ProcessConnections(void); -extern void ProcessCreatures(void); extern void ProcessCronSystem(void); extern void ProcessMonsterhomes(void); extern void ProcessMonsterRaids(void); extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails); -extern void ProcessSkills(void); extern void ProcessWriterThreadReplies(void); extern void ReceiveData(void); extern void RefreshCylinders(void); @@ -77,6 +77,7 @@ extern void RefreshMap(void); extern void RefreshSector(int SectorX, int SectorY, int SectorZ, const uint8 *Data, int Size); extern void SavePlayerDataOrder(void); extern bool SearchFlightField(uint32 FugitiveID, uint32 PursuerID, int *x, int *y, int *z); +extern bool SearchLoginField(int *x, int *y, int *z, int Distance, bool Player); extern bool SearchSummonField(int *x, int *y, int *z, int Distance); extern void SendAll(void); extern void SendAmbiente(TConnection *Connection); @@ -89,6 +90,7 @@ extern void SendPlayerData(TConnection *Connection); extern void SendPlayerSkills(TConnection *Connection); extern void SendPlayerState(TConnection *Connection, uint8 State); extern void SendResult(TConnection *Connection, RESULT r); +extern void SendSnapback(TConnection *Connection); extern void 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);