diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-18 18:57:37 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-18 18:57:37 -0300 |
| commit | e5b8aadd493b8b5df4ed661f2491de33d634b001 (patch) | |
| tree | 694e90810ca82d621573f8d26f64481f7001d183 | |
| parent | b912ba995c2175b00393f95388ae2ec1afd0494b (diff) | |
| download | game-e5b8aadd493b8b5df4ed661f2491de33d634b001.tar.gz game-e5b8aadd493b8b5df4ed661f2491de33d634b001.zip | |
finish `crplayer.cc`
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | TODO.md | 1 | ||||
| -rw-r--r-- | reference/game.c | 2460 | ||||
| -rw-r--r-- | src/common.hh | 2 | ||||
| -rw-r--r-- | src/connection.hh | 2 | ||||
| -rw-r--r-- | src/cr.hh | 72 | ||||
| -rw-r--r-- | src/crmain.cc | 4 | ||||
| -rw-r--r-- | src/crplayer.cc | 1477 | ||||
| -rw-r--r-- | src/crskill.cc | 16 | ||||
| -rw-r--r-- | src/enums.hh | 17 | ||||
| -rw-r--r-- | src/stubs.hh | 8 |
11 files changed, 1496 insertions, 2573 deletions
@@ -13,10 +13,10 @@ else CFLAGS += -O2 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)/operate.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/thread.hh +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)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/thread.hh -$(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)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj - echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^ +$(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)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/script.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/thread.obj $(BUILDDIR)/time.obj $(BUILDDIR)/util.obj + @echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^ $(BUILDDIR)/config.obj: $(SRCDIR)/config.cc $(HEADERS) @mkdir -p $(@D) @@ -70,6 +70,10 @@ $(BUILDDIR)/operate.obj: $(SRCDIR)/operate.cc $(HEADERS) @mkdir -p $(@D) $(CC) -c $(CFLAGS) -o $@ $< +$(BUILDDIR)/query.obj: $(SRCDIR)/query.cc $(HEADERS) + @mkdir -p $(@D) + $(CC) -c $(CFLAGS) -o $@ $< + $(BUILDDIR)/script.obj: $(SRCDIR)/script.cc $(HEADERS) @mkdir -p $(@D) $(CC) -c $(CFLAGS) -o $@ $< @@ -1,5 +1,4 @@ ## TODO NEXT -- CRPLAYER.CC - QUERY.CC - COMMUNICATION.CC - HOUSES.CC diff --git a/reference/game.c b/reference/game.c index a3130b1..3711e19 100644 --- a/reference/game.c +++ b/reference/game.c @@ -18382,2466 +18382,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return;
}
-// DWARF original prototype: void ClearConnection(TPlayer * this)
-
-void __thiscall TPlayer::ClearConnection(TPlayer *this)
-
-{
- int GamemasterID;
- TCreature *pTVar1;
- TCreature *pTVar2;
-
- (this->super_TCreature).Connection = (TConnection *)0x0;
- if (this->Request != 0) {
- if (this->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest((this->super_TCreature).Name);
- }
- else {
- pTVar1 = GetCreature(this->RequestProcessingGamemaster);
- pTVar2 = (TCreature *)0x0;
- if ((pTVar1 != (TCreature *)0x0) && (pTVar2 = pTVar1, pTVar1->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar2 = (TCreature *)0x0;
- }
- if (pTVar2 != (TCreature *)0x0) {
- SendFinishRequest(pTVar2->Connection,(this->super_TCreature).Name);
- }
- }
- this->Request = 0;
- }
- return;
-}
-
-
-
-// DWARF original prototype: void LoadData(TPlayer * this)
-
-void __thiscall TPlayer::LoadData(TPlayer *this)
-
-{
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar1;
- uint uVar2;
- int iVar3;
- TPlayerData *pTVar4;
- uchar *puVar5;
- int *piVar6;
- int SkillNr;
- uchar *puVar7;
- int *piVar8;
-
- pTVar4 = this->PlayerData;
- if (pTVar4 != (TPlayerData *)0x0) {
- (this->super_TCreature).Race = pTVar4->Race;
- aVar1 = (pTVar4->OriginalOutfit).field_1;
- (this->super_TCreature).OrgOutfit.OutfitID = (pTVar4->OriginalOutfit).OutfitID;
- (this->super_TCreature).OrgOutfit.field_1 = aVar1;
- GetStartPosition(&(this->super_TCreature).startx,&(this->super_TCreature).starty,
- &(this->super_TCreature).startz,true);
- (this->super_TCreature).posx = (this->super_TCreature).startx;
- (this->super_TCreature).posy = (this->super_TCreature).starty;
- (this->super_TCreature).posz = (this->super_TCreature).startz;
- (this->super_TCreature).Direction = 2;
- TSkillBase::SetSkills
- (&(this->super_TCreature).super_TSkillBase,(this->super_TCreature).Race);
- pTVar4 = this->PlayerData;
- aVar1 = (pTVar4->CurrentOutfit).field_1;
- (this->super_TCreature).Outfit.OutfitID = (pTVar4->CurrentOutfit).OutfitID;
- (this->super_TCreature).Outfit.field_1 = aVar1;
- if (pTVar4->startx != 0) {
- (this->super_TCreature).startx = pTVar4->startx;
- (this->super_TCreature).starty = pTVar4->starty;
- (this->super_TCreature).startz = pTVar4->startz;
- }
- if (pTVar4->posx != 0) {
- (this->super_TCreature).posx = pTVar4->posx;
- (this->super_TCreature).posy = pTVar4->posy;
- (this->super_TCreature).posz = pTVar4->posz;
- }
- uVar2 = 2000;
- (this->super_TCreature).Profession = (uchar)pTVar4->Profession;
- puVar5 = pTVar4->SpellList;
- puVar7 = this->SpellList;
- for (iVar3 = 0x40; iVar3 != 0; iVar3 = iVar3 + -1) {
- *(undefined4 *)puVar7 = *(undefined4 *)puVar5;
- puVar5 = puVar5 + 4;
- puVar7 = puVar7 + 4;
- }
- piVar8 = this->QuestValues;
- pTVar4 = this->PlayerData;
- piVar6 = pTVar4->QuestValues;
- if (((uint)piVar8 & 4) != 0) {
- piVar8 = this->QuestValues + 1;
- piVar6 = pTVar4->QuestValues + 1;
- this->QuestValues[0] = pTVar4->QuestValues[0];
- uVar2 = 0x7cc;
- }
- for (uVar2 = uVar2 >> 2; uVar2 != 0; uVar2 = uVar2 - 1) {
- *piVar8 = *piVar6;
- piVar6 = piVar6 + 1;
- piVar8 = piVar8 + 1;
- }
- pTVar4 = this->PlayerData;
- iVar3 = 0;
- do {
- if (pTVar4->Minimum[iVar3] != -0x80000000) {
- TSkill::Load((this->super_TCreature).super_TSkillBase.Skills[iVar3]);
- pTVar4 = this->PlayerData;
- }
- iVar3 = iVar3 + 1;
- } while (iVar3 < 0x19);
- (this->super_TCreature).EarliestYellRound = pTVar4->EarliestYellRound;
- (this->super_TCreature).EarliestTradeChannelRound = pTVar4->EarliestTradeChannelRound;
- (this->super_TCreature).EarliestSpellTime = pTVar4->EarliestSpellTime;
- (this->super_TCreature).EarliestMultiuseTime = pTVar4->EarliestMultiuseTime;
- this->TalkBufferFullTime = pTVar4->TalkBufferFullTime;
- this->MutingEndRound = pTVar4->MutingEndRound;
- this->NumberOfMutings = pTVar4->NumberOfMutings;
- return;
- }
- error("TPlayer::LoadData: PlayerData ist NULL.\n");
- return;
-}
-
-
-
-// DWARF original prototype: void SaveData(TPlayer * this)
-
-void __thiscall TPlayer::SaveData(TPlayer *this)
-
-{
- TPlayerData *pTVar1;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar2;
- uint uVar3;
- int iVar4;
- int SkillNr;
- uchar *puVar5;
- int *piVar6;
- uchar *puVar7;
- int *piVar8;
-
- pTVar1 = this->PlayerData;
- if (pTVar1 != (TPlayerData *)0x0) {
- aVar2 = (this->super_TCreature).OrgOutfit.field_1;
- (pTVar1->OriginalOutfit).OutfitID = (this->super_TCreature).OrgOutfit.OutfitID;
- (pTVar1->OriginalOutfit).field_1 = aVar2;
- pTVar1 = this->PlayerData;
- aVar2 = (this->super_TCreature).Outfit.field_1;
- (pTVar1->CurrentOutfit).OutfitID = (this->super_TCreature).Outfit.OutfitID;
- (pTVar1->CurrentOutfit).field_1 = aVar2;
- this->PlayerData->startx = (this->super_TCreature).startx;
- this->PlayerData->starty = (this->super_TCreature).starty;
- this->PlayerData->startz = (this->super_TCreature).startz;
- this->PlayerData->posx = (this->super_TCreature).posx;
- this->PlayerData->posy = (this->super_TCreature).posy;
- this->PlayerData->posz = (this->super_TCreature).posz;
- uVar3 = 2000;
- this->PlayerData->Profession = (uint)(this->super_TCreature).Profession;
- puVar5 = this->SpellList;
- puVar7 = this->PlayerData->SpellList;
- for (iVar4 = 0x40; iVar4 != 0; iVar4 = iVar4 + -1) {
- *(undefined4 *)puVar7 = *(undefined4 *)puVar5;
- puVar5 = puVar5 + 4;
- puVar7 = puVar7 + 4;
- }
- piVar6 = this->QuestValues;
- pTVar1 = this->PlayerData;
- piVar8 = pTVar1->QuestValues;
- if (((uint)piVar8 & 4) != 0) {
- piVar8 = pTVar1->QuestValues + 1;
- piVar6 = this->QuestValues + 1;
- pTVar1->QuestValues[0] = this->QuestValues[0];
- uVar3 = 0x7cc;
- }
- for (uVar3 = uVar3 >> 2; uVar3 != 0; uVar3 = uVar3 - 1) {
- *piVar8 = *piVar6;
- piVar6 = piVar6 + 1;
- piVar8 = piVar8 + 1;
- }
- iVar4 = 0;
- do {
- if ((this->super_TCreature).super_TSkillBase.Skills[iVar4] == (TSkill *)0x0) {
- this->PlayerData->Minimum[iVar4] = -0x80000000;
- }
- else {
- TSkill::Save((this->super_TCreature).super_TSkillBase.Skills[iVar4]);
- }
- iVar4 = iVar4 + 1;
- } while (iVar4 < 0x19);
- this->PlayerData->EarliestYellRound = (this->super_TCreature).EarliestYellRound;
- this->PlayerData->EarliestTradeChannelRound =
- (this->super_TCreature).EarliestTradeChannelRound;
- this->PlayerData->EarliestSpellTime = (this->super_TCreature).EarliestSpellTime;
- this->PlayerData->EarliestMultiuseTime = (this->super_TCreature).EarliestMultiuseTime;
- this->PlayerData->TalkBufferFullTime = this->TalkBufferFullTime;
- this->PlayerData->MutingEndRound = this->MutingEndRound;
- this->PlayerData->NumberOfMutings = this->NumberOfMutings;
- return;
- }
- error("TPlayer::SaveData: PlayerData ist NULL.\n");
- return;
-}
-
-
-
-// DWARF original prototype: void LoadInventory(TPlayer * this, bool SetStandardInventory)
-
-void __thiscall TPlayer::LoadInventory(TPlayer *this,bool SetStandardInventory)
-
-{
- TPlayerData *pTVar1;
- bool bVar2;
- byte bVar3;
- RESULT r;
- int Position;
- undefined1 local_5c [4];
- TReadBuffer Buffer;
- Object Con;
- Object local_3c [4];
- Object local_2c [7];
-
- pTVar1 = this->PlayerData;
- if (pTVar1 == (TPlayerData *)0x0) {
- error("TPlayer::LoadInventory: PlayerData ist NULL.\n");
- }
- else if (pTVar1->Inventory == (uchar *)0x0) {
- if ((this->super_TCreature).Profession == '\0') {
- bVar2 = CheckRight((this->super_TCreature).ID,ZERO_CAPACITY);
- if ((!bVar2) && (SetStandardInventory)) {
- // try { // try from 080abb37 to 080abca5 has its CatchHandler @ 080abd71
- GetSpecialObject((SPECIALMEANING)local_3c);
- GetBodyContainer((ulong)&Buffer.Position,(this->super_TCreature).ID);
- Create(local_2c,(ObjectType *)&Buffer.Position,(ulong)local_3c);
- GetSpecialObject((SPECIALMEANING)local_3c);
- GetBodyContainer((ulong)local_2c,(this->super_TCreature).ID);
- Create((Object *)&Buffer.Position,(ObjectType *)local_2c,(ulong)local_3c);
- GetSpecialObject((SPECIALMEANING)local_3c);
- GetBodyContainer((ulong)local_2c,(this->super_TCreature).ID);
- Create((Object *)&Buffer.Position,(ObjectType *)local_2c,(ulong)local_3c);
- GetSpecialObject((SPECIALMEANING)local_3c);
- GetBodyContainer((ulong)local_2c,(this->super_TCreature).ID);
- Create((Object *)&Buffer.Position,(ObjectType *)local_2c,(ulong)local_3c);
- GetSpecialObject((SPECIALMEANING)local_2c);
- local_5c = (undefined1 [4])Buffer.Position;
- Create(local_3c,(ObjectType *)local_5c,(ulong)local_2c);
- }
- }
- }
- else {
- // try { // try from 080abcca to 080abd5a has its CatchHandler @ 080abdb0
- TReadBuffer::TReadBuffer((TReadBuffer *)local_5c,pTVar1->Inventory,pTVar1->InventorySize);
- while( true ) {
- bVar3 = TReadBuffer::readByte((TReadBuffer *)local_5c);
- if (bVar3 == 0xff) break;
- GetBodyContainer((ulong)&Buffer.Position,(this->super_TCreature).ID);
- LoadObjects((TReadStream *)local_5c,(Object *)&Buffer.Position);
- GetBodyObject((ulong)&Buffer.Position,(this->super_TCreature).ID);
- local_3c[0] = (Object)::NONE.ObjectID;
- local_2c[0].ObjectID = local_3c[0].ObjectID;
- if (Buffer.Position != ::NONE.ObjectID) {
- local_2c[0].ObjectID = Buffer.Position;
- SendSetInventory((this->super_TCreature).Connection,(uint)bVar3,local_2c);
- }
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void SaveInventory(TPlayer * this)
-
-void __thiscall TPlayer::SaveInventory(TPlayer *this)
-
-{
- bool bVar1;
- TPlayerData *pTVar2;
- uchar *puVar3;
- int con;
- int iVar4;
- TDynamicWriteBuffer *Position;
- Object local_4c [4];
- undefined1 local_3c [4];
- TDynamicWriteBuffer HelpBuffer;
- Object Obj;
-
- pTVar2 = this->PlayerData;
- if (pTVar2 == (TPlayerData *)0x0) {
- error("TPlayer::SaveInventory: PlayerData ist NULL.\n");
- }
- else {
- if (pTVar2->Inventory != (uchar *)0x0) {
- operator_delete__(pTVar2->Inventory);
- this->PlayerData->Inventory = (uchar *)0x0;
- pTVar2 = this->PlayerData;
- }
- pTVar2->InventorySize = 0;
- HelpBuffer.super_TWriteBuffer.Position = (this->super_TCreature).CrObject.ObjectID;
- local_3c = (undefined1 [4])::NONE.ObjectID;
- if (HelpBuffer.super_TWriteBuffer.Position != ::NONE.ObjectID) {
- // try { // try from 080abe5b to 080abe5f has its CatchHandler @ 080abfb1
- TDynamicWriteBuffer::TDynamicWriteBuffer((TDynamicWriteBuffer *)local_3c,0x4000);
- iVar4 = 1;
- do {
- Position = (TDynamicWriteBuffer *)(this->super_TCreature).ID;
- // try { // try from 080abe79 to 080abecf has its CatchHandler @ 080abf72
- GetBodyObject((ulong)&HelpBuffer.super_TWriteBuffer.Position,(int)Position);
- bVar1 = Object::exists((Object *)&HelpBuffer.super_TWriteBuffer.Position);
- if (bVar1) {
- // try { // try from 080abf14 to 080abf35 has its CatchHandler @ 080abf72
- TDynamicWriteBuffer::writeByte((TDynamicWriteBuffer *)local_3c,(uchar)iVar4);
- local_4c[0].ObjectID = HelpBuffer.super_TWriteBuffer.Position;
- Position = (TDynamicWriteBuffer *)local_3c;
- SaveObjects(local_4c,(TWriteStream *)local_3c,false);
- }
- iVar4 = iVar4 + 1;
- } while (iVar4 < 0xb);
- if (HelpBuffer.super_TWriteBuffer.Size != 0) {
- TDynamicWriteBuffer::writeByte((TDynamicWriteBuffer *)local_3c,0xff);
- this->PlayerData->InventorySize = HelpBuffer.super_TWriteBuffer.Size;
- pTVar2 = this->PlayerData;
- puVar3 = (uchar *)operator_new__(pTVar2->InventorySize);
- pTVar2->Inventory = puVar3;
- memcpy(this->PlayerData->Inventory,
- HelpBuffer.super_TWriteBuffer.super_TWriteStream._vptr_TWriteStream,
- this->PlayerData->InventorySize);
- Position = (TDynamicWriteBuffer *)
- HelpBuffer.super_TWriteBuffer.super_TWriteStream._vptr_TWriteStream;
- }
- // try { // try from 080abefe to 080abf02 has its CatchHandler @ 080abfb1
- TDynamicWriteBuffer::~TDynamicWriteBuffer((TDynamicWriteBuffer *)local_3c,(int)Position)
- ;
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void StartCoordinates(TPlayer * this)
-
-void __thiscall TPlayer::StartCoordinates(TPlayer *this)
-
-{
- GetStartPosition(&(this->super_TCreature).startx,&(this->super_TCreature).starty,
- &(this->super_TCreature).startz,true);
- return;
-}
-
-
-
-// DWARF original prototype: void TakeOver(TPlayer * this, TConnection * Connection)
-
-void __thiscall TPlayer::TakeOver(TPlayer *this,TConnection *Connection)
-
-{
- char *__dest;
- Object OVar1;
- bool bVar2;
- TCreature *cr;
- TPlayerData *pTVar3;
- __pid_t _Var4;
- char *__src;
- TCreature *pTVar5;
- TPlayer *pTVar6;
- TCreature *pTVar7;
- ulong extraout_EDX;
- ulong id;
- ulong extraout_EDX_00;
- TPlayerData *PlayerData;
- Object *pOVar8;
- uint Window;
- Object local_4c [4];
- ulong local_3c;
- ulong local_2c;
-
- __dest = (this->super_TCreature).Name;
- Log("game",&DAT_08103d40,__dest);
- (this->super_TCreature).LoggingOut = false;
- (this->super_TCreature).LogoutAllowed = false;
- (this->super_TCreature).Connection = Connection;
- TConnection::EnterGame(Connection);
- pTVar3 = GetPlayerPoolSlot((this->super_TCreature).ID);
- if (pTVar3 == (TPlayerData *)0x0) {
- error("TPlayer::TakeOver: PlayerData-Slot nicht gefunden.\n");
- }
- else {
- _Var4 = getpid();
- if (pTVar3->Locked != _Var4) {
- error("TPlayer::TakeOver: PlayerData-Slot ist nicht korrekt gesperrt (%d).\n",
- pTVar3->Locked);
- }
- if (pTVar3->Sticky < 2) {
- error("TPlayer::TakeOver: Falscher Sticky-Wert %d.\n",pTVar3->Sticky);
- }
- else {
- Semaphore::down(&PlayerDataPoolMutex);
- pTVar3->Sticky = pTVar3->Sticky + -1;
- Semaphore::up(&PlayerDataPoolMutex);
- }
- strcpy(__dest,pTVar3->Name);
- InsertPlayerIndex(&PlayerIndexHead,0,__dest,(this->super_TCreature).ID);
- __src = TConnection::GetIPAddress(Connection);
- strcpy(this->IPAddress,__src);
- *(undefined4 *)this->Rights = *(undefined4 *)pTVar3->Rights;
- *(undefined4 *)(this->Rights + 4) = *(undefined4 *)(pTVar3->Rights + 4);
- *(undefined4 *)(this->Rights + 8) = *(undefined4 *)(pTVar3->Rights + 8);
- (this->super_TCreature).Sex = pTVar3->Sex;
- strcpy(this->Guild,pTVar3->Guild);
- strcpy(this->Rank,pTVar3->Rank);
- pOVar8 = this->OpenContainer;
- strcpy(this->Title,pTVar3->Title);
- CheckOutfit(this);
- Window = 0;
- do {
- if (Window < 0x10) {
- local_2c = pOVar8->ObjectID;
- }
- else {
- error(&DAT_08103de0);
- local_2c = ::NONE.ObjectID;
- }
- local_3c = ::NONE.ObjectID;
- local_4c[0].ObjectID = ::NONE.ObjectID;
- if (local_2c != ::NONE.ObjectID) {
- SetOpenContainer(this,Window,local_4c);
- SendCloseContainer((this->super_TCreature).Connection,Window);
- }
- Window = Window + 1;
- pOVar8 = pOVar8 + 1;
- } while ((int)Window < 0x10);
- TCombat::StopAttack(&(this->super_TCreature).Combat,0);
- LeaveAllChannels((this->super_TCreature).ID);
- if (this->Request != 0) {
- if (this->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest(__dest);
- }
- else {
- pTVar5 = GetCreature(this->RequestProcessingGamemaster);
- pTVar7 = (TCreature *)0x0;
- if ((pTVar5 != (TCreature *)0x0) && (pTVar7 = pTVar5, pTVar5->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar7 = (TCreature *)0x0;
- }
- if (pTVar7 != (TCreature *)0x0) {
- SendFinishRequest(pTVar7->Connection,__dest);
- }
- }
- this->Request = 0;
- }
- this->RequestTimestamp = 0;
- this->RequestProcessingGamemaster = 0;
- local_4c[0] = ::NONE;
- if ((this->TradeObject).ObjectID != ::NONE.ObjectID) {
- local_3c = ::NONE.ObjectID;
- (this->TradeObject).ObjectID = ::NONE.ObjectID;
- pTVar6 = GetPlayer(this->TradePartner);
- OVar1 = ::NONE;
- if (pTVar6 != (TPlayer *)0x0) {
- local_4c[0] = (Object)::NONE.ObjectID;
- bVar2 = false;
- if (((pTVar6->TradeObject).ObjectID != ::NONE.ObjectID) &&
- (pTVar6->TradePartner == (this->super_TCreature).ID)) {
- bVar2 = true;
- }
- local_3c = local_4c[0].ObjectID;
- if (bVar2) {
- local_2c = ::NONE.ObjectID;
- (pTVar6->TradeObject).ObjectID = ::NONE.ObjectID;
- local_3c = OVar1.ObjectID;
- SendCloseTrade((pTVar6->super_TCreature).Connection);
- SendMessage((pTVar6->super_TCreature).Connection,0x17,"Trade cancelled.");
- }
- }
- }
- bVar2 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- id = extraout_EDX;
- if (bVar2) {
- CloseProcessedRequests((this->super_TCreature).ID);
- id = extraout_EDX_00;
- }
- SendInitGame((TConnection *)(this->super_TCreature).ID,id);
- SendRights((this->super_TCreature).Connection);
- SendFullScreen((this->super_TCreature).Connection);
- SendBodyInventory((this->super_TCreature).Connection,(this->super_TCreature).ID);
- SendAmbiente((this->super_TCreature).Connection);
- SendPlayerData((this->super_TCreature).Connection);
- SendPlayerSkills((this->super_TCreature).Connection);
- this->OldState = 0;
- CheckState(this);
- SendBuddies(this);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void Death(TPlayer * this)
-
-void __thiscall TPlayer::Death(TPlayer *this)
-
-{
- TConnection *Connection;
- TSkill *pTVar1;
- bool bVar2;
- int iVar3;
- undefined4 uVar4;
- TSkill *sk;
- uint uVar5;
- int Percent;
- int iVar6;
-
- bVar2 = CheckRight((this->super_TCreature).ID,INVULNERABLE);
- if (bVar2) {
- error("TPlayer::Death: Aha, so geht das aber nicht!! Goetter kann man nicht toeten!!\n");
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[2];
- (*pTVar1->_vptr_TSkill[2])((this->super_TCreature).super_TSkillBase.Skills[2],pTVar1->Max);
- }
- else {
- Connection = (this->super_TCreature).Connection;
- if (Connection != (TConnection *)0x0) {
- SendPlayerData(Connection);
- SendMessage((this->super_TCreature).Connection,0x13,"You are dead.\n");
- TConnection::Die((this->super_TCreature).Connection);
- }
- TCreature::Death(&this->super_TCreature);
- if (WorldType == PVP_ENFORCED) {
- TCombat::DistributeExperiencePoints
- (&(this->super_TCreature).Combat,
- (this->super_TCreature).super_TSkillBase.Skills[0]->Exp / 0x14);
- }
- bVar2 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar2) {
- bVar2 = 9 < (this->super_TCreature).Profession;
- }
- else {
- bVar2 = false;
- }
- uVar5 = 0x65;
- iVar6 = (uint)!bVar2 * 3 + 7;
- do {
- if (uVar5 < 500) {
- print();
- iVar3 = this->QuestValues[uVar5];
- }
- else {
- error(&DAT_08103ea0);
- iVar3 = 0;
- }
- if (iVar3 != 0) {
- iVar6 = iVar6 + -1;
- if (uVar5 < 500) {
- print();
- this->QuestValues[uVar5] = 0;
- }
- else {
- error(&DAT_08103ee0);
- }
- }
- uVar5 = uVar5 + 1;
- } while ((int)uVar5 < 0x6a);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[8];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[10];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[9];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[7];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0xb];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[6];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[1];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0xd];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0];
- uVar4 = __divdi3((longlong)pTVar1->Exp * (longlong)iVar6,100,0);
- (*pTVar1->_vptr_TSkill[4])(pTVar1,uVar4);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void AttackStimulus(TPlayer * this, ulong param_1)
-
-void __thiscall TPlayer::AttackStimulus(TPlayer *this,ulong param_1)
-
-{
- if ((this->super_TCreature).IsDead == false) {
- TCreature::BlockLogout(&this->super_TCreature,0x3c,false);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void DamageStimulus(TPlayer * this, ulong param_1, int param_2, int
-// param_3)
-
-void __thiscall TPlayer::DamageStimulus(TPlayer *this,ulong param_1,int param_2,int param_3)
-
-{
- if ((this->super_TCreature).IsDead != false) {
- return;
- }
- TCreature::BlockLogout(&this->super_TCreature,0x3c,false);
- return;
-}
-
-
-
-// DWARF original prototype: void IdleStimulus(TPlayer * this)
-
-void __thiscall TPlayer::IdleStimulus(TPlayer *this)
-
-{
- RESULT r;
-
- if ((this->super_TCreature).Combat.AttackDest != 0) {
- // try { // try from 080ac866 to 080ac872 has its CatchHandler @ 080ac875
- TCreature::ToDoAttack(&this->super_TCreature);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void SetOpenContainer(TPlayer * this, int Window, Object * Con)
-
-void __thiscall TPlayer::SetOpenContainer(TPlayer *this,int Window,Object *Con)
-
-{
- bool bVar1;
- bool bVar2;
- char *Text;
- Object local_3c [4];
- ulong local_2c;
-
- if (0xf < (uint)Window) {
- Text = &DAT_08104040;
- goto LAB_080ac947;
- }
- bVar1 = false;
- local_2c = ::NONE.ObjectID;
- local_3c[0].ObjectID = ::NONE.ObjectID;
- if (Con->ObjectID != ::NONE.ObjectID) {
- bVar2 = Object::exists(Con);
- if (bVar2) {
- Object::getObjectType(local_3c);
- bVar2 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER);
- if (bVar2) goto LAB_080ac914;
- }
- bVar1 = true;
- }
-LAB_080ac914:
- if (!bVar1) {
- this->OpenContainer[Window].ObjectID = Con->ObjectID;
- return;
- }
- Text = "TPlayer::SetOpenContainer: Container existiert nicht.\n";
-LAB_080ac947:
- error(Text);
- return;
-}
-
-
-
-// DWARF original prototype: Object GetOpenContainer(TPlayer * this, int Window)
-
-Object __thiscall TPlayer::GetOpenContainer(TPlayer *this,int Window)
-
-{
- Object OVar1;
- uint in_stack_0000000c;
-
- if (in_stack_0000000c < 0x10) {
- OVar1.ObjectID = (ulong)*(_func_int_varargs ***)(Window + 0xca0 + in_stack_0000000c * 4);
- }
- else {
- error(&DAT_08103de0);
- OVar1 = ::NONE;
- }
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)OVar1.ObjectID;
- return (Object)(ulong)this;
-}
-
-
-
-// DWARF original prototype: void CloseAllContainers(TPlayer * this)
-
-void __thiscall TPlayer::CloseAllContainers(TPlayer *this)
-
-{
- Object *pOVar1;
- int i;
- uint Window;
- Object local_4c [4];
- ulong local_3c;
- ulong local_2c;
-
- pOVar1 = this->OpenContainer;
- Window = 0;
- do {
- if (Window < 0x10) {
- local_2c = pOVar1->ObjectID;
- }
- else {
- error(&DAT_08103de0);
- local_2c = ::NONE.ObjectID;
- }
- local_3c = ::NONE.ObjectID;
- local_4c[0].ObjectID = ::NONE.ObjectID;
- if (local_2c != ::NONE.ObjectID) {
- SetOpenContainer(this,Window,local_4c);
- SendCloseContainer((this->super_TCreature).Connection,Window);
- }
- Window = Window + 1;
- pOVar1 = pOVar1 + 1;
- } while ((int)Window < 0x10);
- return;
-}
-
-
-
-// DWARF original prototype: Object InspectTrade(TPlayer * this, bool OwnOffer, int Position)
-
-Object __thiscall TPlayer::InspectTrade(TPlayer *this,bool OwnOffer,int Position)
-
-{
- TSkill *pTVar1;
- bool bVar2;
- TCreature *cr;
- TCreature *pTVar3;
- int iVar4;
- TCreature *pTVar5;
- undefined3 in_stack_00000009;
- int in_stack_00000010;
- Object local_4c [4];
- Object local_3c [4];
- TSkill *local_2c;
- Object Obj;
-
- if (*(TSkill **)(_OwnOffer + 0x3b0) == (TSkill *)::NONE.ObjectID) {
-LAB_080acaaf:
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)::NONE.ObjectID;
- return (Object)(ulong)this;
- }
- local_2c = (TSkill *)0x0;
- pTVar1 = *(TSkill **)(_OwnOffer + 0x3b0);
- if ((char)Position == '\0') {
- if (*(ulong *)(_OwnOffer + 0x3b4) == 0) goto LAB_080acaaf;
- pTVar3 = GetCreature(*(ulong *)(_OwnOffer + 0x3b4));
- pTVar5 = (TCreature *)0x0;
- if ((pTVar3 != (TCreature *)0x0) && (pTVar5 = pTVar3, pTVar3->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar5 = (TCreature *)0x0;
- }
- local_2c = (TSkill *)::NONE.ObjectID;
- if (pTVar5 == (TCreature *)0x0) goto LAB_080acb9b;
- bVar2 = false;
- pTVar1 = pTVar5[1].super_TSkillBase.TimerList[0xb];
- if ((pTVar1 == (TSkill *)::NONE.ObjectID) ||
- (pTVar5[1].super_TSkillBase.TimerList[0xc] != *(TSkill **)(_OwnOffer + 0x208))) {
- bVar2 = true;
- }
- if (bVar2) goto LAB_080acaaf;
- }
- while( true ) {
- local_2c = pTVar1;
- bVar2 = false;
- if ((local_2c != (TSkill *)::NONE.ObjectID) && (0 < in_stack_00000010)) {
- bVar2 = true;
- }
- if (!bVar2) break;
- local_4c[0].ObjectID = (ulong)local_2c;
- local_3c[0].ObjectID = ::NONE.ObjectID;
- iVar4 = CountObjects(local_4c);
- if (in_stack_00000010 < iVar4) {
- in_stack_00000010 = in_stack_00000010 + -1;
- GetFirstContainerObject(local_3c);
- }
- else {
- in_stack_00000010 = in_stack_00000010 - iVar4;
- Object::getNextObject(local_3c);
- }
- pTVar1 = (TSkill *)local_3c[0].ObjectID;
- }
-LAB_080acb9b:
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)local_2c;
- return (Object)(ulong)this;
-}
-
-
-
-// WARNING: Type propagation algorithm not settling
-// DWARF original prototype: void AcceptTrade(TPlayer * this)
-
-void __thiscall TPlayer::AcceptTrade(TPlayer *this)
-
-{
- Object *Obj_00;
- TPlayer *pTVar1;
- TSkill *this_00;
- bool bVar2;
- bool bVar3;
- TCreature *cr;
- TCreature *pTVar4;
- int iVar5;
- int iVar6;
- ulong uVar7;
- int iVar8;
- undefined4 *puVar9;
- ulong uVar10;
- RESULT r;
- int NewWeight;
- bool bVar11;
- int Step;
- bool local_bd;
- bool invert;
- int iStack_bc;
- bool first;
- int pos;
- TSkill *sk;
- int p;
- TPlayer *Player [2];
- Object local_8c;
- ObjectType Type0;
- Object local_7c;
- ObjectType Type1;
- Object local_6c [4];
- Object local_5c;
- Object Help;
- Object local_4c [4];
- ulong local_3c;
- Object Con [2];
- Object Obj [2];
-
- if ((this->TradeObject).ObjectID != ::NONE.ObjectID) {
- pTVar4 = GetCreature(this->TradePartner);
- p = 0;
- if ((pTVar4 != (TCreature *)0x0) && (p = (int)pTVar4, pTVar4->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- p = 0;
- }
- if (p != 0) {
- bVar2 = false;
- if ((*(ulong *)(p + 0x3b0) == ::NONE.ObjectID) ||
- (*(ulong *)(p + 0x3b4) != (this->super_TCreature).ID)) {
- bVar2 = true;
- }
- if ((!bVar2) && (this->TradeAccepted = true, *(char *)(p + 0x3b8) != '\0')) {
- pTVar1 = (TPlayer *)(this->TradeObject).ObjectID;
- sk = (TSkill *)0x0;
- Player[0] = (TPlayer *)p;
- Obj[0].ObjectID = *(ulong *)(p + 0x3b0);
- local_3c = ::NONE.ObjectID;
- local_4c[0].ObjectID = ::NONE.ObjectID;
- Con[0] = ::NONE;
- local_5c.ObjectID = ::NONE.ObjectID;
- do {
- local_5c.ObjectID = Obj[(int)((int)&sk[-1].AddLevel + 3)].ObjectID;
- // try { // try from 080acd0a to 080ace9d has its CatchHandler @ 080ad450
- bVar2 = ObjectAccessible((Player[(int)((int)&sk[-1].AddLevel + 3)]->
- super_TCreature).ID,&local_5c,1);
- if (!bVar2) {
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 1;
- goto LAB_080acf89;
- }
- Object::getObjectType(&local_5c);
- bVar2 = ObjectType::getFlag((ObjectType *)&local_5c,UNMOVE);
- if (bVar2) {
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 2;
- goto LAB_080acf89;
- }
- Object::getObjectType(&local_5c);
- bVar2 = ObjectType::getFlag((ObjectType *)&local_5c,TAKE);
- if (!bVar2) {
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 3;
- goto LAB_080acf89;
- }
- iVar8 = -(int)sk;
- bVar2 = CheckRight((Player[iVar8]->super_TCreature).ID,ZERO_CAPACITY);
- if (bVar2) {
-LAB_080ad379:
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 8;
-LAB_080acf89:
- // WARNING: Subroutine does not return
- // try { // try from 080acf9c to 080acfa0 has its CatchHandler @ 080ad450
- __cxa_throw(puVar9,&RESULT::typeinfo,0);
- }
- bVar2 = CheckRight((Player[iVar8]->super_TCreature).ID,UNLIMITED_CAPACITY);
- if (!bVar2) {
- this_00 = (Player[iVar8]->super_TCreature).super_TSkillBase.Skills[5];
- if (this_00 == (TSkill *)0x0) {
- error("TPlayer::AcceptTrade: Skill CARRYSTRENGTH existiert nicht.\n");
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 0xffffffff;
- goto LAB_080acf89;
- }
- iVar5 = GetInventoryWeight((Player[iVar8]->super_TCreature).ID);
- local_5c.ObjectID = Obj[(int)((int)&sk[-1].AddLevel + 3)].ObjectID;
- iVar6 = GetCompleteWeight(&local_5c);
- iVar5 = iVar5 + iVar6;
- local_5c.ObjectID = Obj[iVar8].ObjectID;
- uVar7 = GetObjectCreatureID(&local_5c);
- if (uVar7 == (Player[iVar8]->super_TCreature).ID) {
- local_4c[0].ObjectID = Obj[iVar8].ObjectID;
- // try { // try from 080ad3a1 to 080ad3b8 has its CatchHandler @ 080ad450
- iVar8 = GetCompleteWeight(local_4c);
- iVar5 = iVar5 - iVar8;
- }
- iVar8 = TSkill::Get(this_00);
- if (iVar8 * 100 < iVar5) goto LAB_080ad379;
- }
- local_bd = true;
- iStack_bc = 0;
- Object::getObjectType(&local_5c);
- bVar2 = ObjectType::getFlag((ObjectType *)&local_5c,MOVEMENTEVENT);
- while( true ) {
- iStack_bc = iStack_bc + 1;
- iVar8 = -(int)sk;
- uVar7 = (Player[iVar8]->super_TCreature).ID;
- iVar5 = iStack_bc;
- // try { // try from 080acedf to 080acee3 has its CatchHandler @ 080ad430
- GetBodyObject((ulong)&local_5c,uVar7);
- if ((local_bd != bVar2) &&
- (local_4c[0].ObjectID = ::NONE.ObjectID,
- local_5c.ObjectID == ::NONE.ObjectID)) {
- local_6c[0].ObjectID = Obj[iVar8].ObjectID;
- GetBodyContainer((ulong)&local_7c,(Player[iVar8]->super_TCreature).ID);
- Object::getObjectType(&local_8c);
- CheckInventoryPlace((ObjectType *)&local_8c,&local_7c,local_6c);
- uVar7 = (Player[iVar8]->super_TCreature).ID;
- iVar5 = iStack_bc;
- GetBodyContainer((ulong)&local_7c,uVar7);
- local_8c.ObjectID = local_7c.ObjectID;
- Con[iVar8].ObjectID = local_7c.ObjectID;
- }
- bVar11 = false;
- if (local_bd == bVar2) {
- local_8c = (Object)::NONE.ObjectID;
- local_7c.ObjectID = ::NONE.ObjectID;
- if (local_5c.ObjectID != ::NONE.ObjectID) {
- Object::getObjectType(&local_7c);
- uVar7 = 4;
- bVar3 = ObjectType::getFlag((ObjectType *)&local_7c,CONTAINER);
- if (bVar3) {
- local_7c.ObjectID = Obj[-(int)sk].ObjectID;
- local_6c[0].ObjectID = local_7c.ObjectID;
- if (local_5c.ObjectID != local_7c.ObjectID) {
- bVar11 = true;
- }
- }
- }
- }
- if (bVar11) {
- // try { // try from 080ad1d2 to 080ad365 has its CatchHandler @ 080ad430
- Object::getContainer(local_6c);
- bVar11 = local_6c[0].ObjectID == local_5c.ObjectID;
- local_4c[0].ObjectID = local_5c.ObjectID;
- local_6c[0].ObjectID = local_5c.ObjectID;
- iVar8 = CountObjectsInContainer(local_6c);
- Object::getObjectType(local_4c);
- uVar7 = 1;
- uVar10 = ObjectType::getAttribute((ObjectType *)local_4c,CAPACITY);
- if ((int)uVar10 <= (int)(iVar8 - (uint)bVar11)) {
- puVar9 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar9 = 10;
- // WARNING: Subroutine does not return
- __cxa_throw(puVar9,&RESULT::typeinfo,0);
- }
- local_4c[0].ObjectID = local_5c.ObjectID;
- Con[-(int)sk].ObjectID = local_5c.ObjectID;
- local_6c[0].ObjectID = local_5c.ObjectID;
- }
- local_8c.ObjectID = ::NONE.ObjectID;
- if (Con[-(int)sk].ObjectID != ::NONE.ObjectID) break;
- if (9 < iStack_bc) {
- if (local_bd == false) {
- puVar9 = (undefined4 *)__cxa_allocate_exception(4,uVar7,iVar5);
- *puVar9 = 4;
- goto LAB_080acf89;
- }
- local_bd = false;
- iStack_bc = 0;
- }
- }
- sk = (TSkill *)((int)&sk->_vptr_TSkill + 1);
- } while ((int)sk < 2);
- (this->TradeObject).ObjectID = ::NONE.ObjectID;
- local_8c = ::NONE;
- local_7c.ObjectID = ::NONE.ObjectID;
- *(ulong *)(p + 0x3b0) = ::NONE.ObjectID;
- SendCloseTrade((this->super_TCreature).Connection);
- SendCloseTrade(*(TConnection **)(p + 0x318));
- Object::getObjectType(&local_8c);
- Object::getObjectType(&local_7c);
- local_6c[0].ObjectID = ::NONE.ObjectID;
- local_4c[0].ObjectID = (Player[0]->super_TCreature).CrObject.ObjectID;
- // try { // try from 080ad052 to 080ad1a1 has its CatchHandler @ 080ad501
- GetMapContainer(&local_5c);
- Obj_00 = (Object *)(Player + 1);
- Player[1] = pTVar1;
- Move(0,Obj_00,&local_5c,-1,true,local_6c);
- Player[1] = (TPlayer *)::NONE.ObjectID;
- local_5c.ObjectID = (this->super_TCreature).CrObject.ObjectID;
- GetMapContainer(local_6c);
- local_4c[0].ObjectID = Obj[0].ObjectID;
- Move(0,local_4c,local_6c,-1,true,Obj_00);
- Player[1] = (TPlayer *)::NONE.ObjectID;
- local_6c[0].ObjectID = Con[0].ObjectID;
- local_5c.ObjectID = (ulong)pTVar1;
- Move(0,&local_5c,local_6c,-1,true,Obj_00);
- Player[1] = (TPlayer *)::NONE.ObjectID;
- local_6c[0].ObjectID = local_3c;
- local_5c.ObjectID = Obj[0].ObjectID;
- Move(0,&local_5c,local_6c,-1,true,Obj_00);
- }
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void RejectTrade(TPlayer * this)
-
-void __thiscall TPlayer::RejectTrade(TPlayer *this)
-
-{
- bool bVar1;
- TCreature *cr;
- TCreature *pTVar2;
- TCreature *pTVar3;
-
- if ((this->TradeObject).ObjectID != ::NONE.ObjectID) {
- (this->TradeObject).ObjectID = ::NONE.ObjectID;
- pTVar2 = GetCreature(this->TradePartner);
- pTVar3 = (TCreature *)0x0;
- if ((pTVar2 != (TCreature *)0x0) && (pTVar3 = pTVar2, pTVar2->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar3 = (TCreature *)0x0;
- }
- if (pTVar3 != (TCreature *)0x0) {
- bVar1 = false;
- if ((pTVar3[1].super_TSkillBase.TimerList[0xb] != (TSkill *)::NONE.ObjectID) &&
- (pTVar3[1].super_TSkillBase.TimerList[0xc] == (TSkill *)(this->super_TCreature).ID))
- {
- bVar1 = true;
- }
- if (bVar1) {
- pTVar3[1].super_TSkillBase.TimerList[0xb] = (TSkill *)::NONE.ObjectID;
- SendCloseTrade(pTVar3->Connection);
- SendMessage(pTVar3->Connection,0x17,"Trade cancelled.");
- }
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: void ClearProfession(TPlayer * this)
-
-void __thiscall TPlayer::ClearProfession(TPlayer *this)
-
-{
- if ((this->super_TCreature).Profession == '\0') {
- return;
- }
- (this->super_TCreature).Profession = '\0';
- TCombat::CheckCombatValues(&(this->super_TCreature).Combat);
- IncrementNewbiesOnline();
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: prof_local
-// DWARF original prototype: void SetProfession(TPlayer * this, uchar prof)
-
-void __thiscall TPlayer::SetProfession(TPlayer *this,uchar prof)
-
-{
- byte bVar1;
- int Rest;
- TSkill *pTVar2;
- int iVar3;
- _func_int_varargs **pp_Var4;
- undefined4 uVar5;
- uchar prof_local;
-
- if (prof == '\n') {
- bVar1 = (this->super_TCreature).Profession;
- if (bVar1 == 0) {
- this = (TPlayer *)&DAT_08104220;
- }
- else {
- if (bVar1 < 10) {
- (this->super_TCreature).Profession = bVar1 + 10;
- TCombat::CheckCombatValues(&(this->super_TCreature).Combat);
- (this->super_TCreature).super_TSkillBase.Skills[0x16]->Max = 200;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0x16];
- iVar3 = (*pTVar2->_vptr_TSkill[0xd])(pTVar2);
- if (0xe < iVar3) {
- TSkillBase::SetTimer(&(this->super_TCreature).super_TSkillBase);
- }
- return;
- }
- this = (TPlayer *)s_TPlayer__SetProfession__Spieler_h_081041c0;
- }
- error((char *)this);
- return;
- }
- if ((this->super_TCreature).Profession != '\0') {
- this = (TPlayer *)s_TPlayer__SetProfession__Player___08104180;
- goto LAB_080ad750;
- }
- if (prof == '\x02') {
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[8];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x4b0,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[10];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x4b0,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[9];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x4b0,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0xb];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x4b0,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[7];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,0x1e);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[6];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,100);
- (this->super_TCreature).super_TSkillBase.Skills[2]->AddLevel = 10;
- (this->super_TCreature).super_TSkillBase.Skills[5]->AddLevel = 0x14;
- (this->super_TCreature).super_TSkillBase.Skills[3]->AddLevel = 0xf;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[1];
- pp_Var4 = pTVar2->_vptr_TSkill;
- uVar5 = 0x578;
- goto LAB_080ad830;
- }
- if (prof < 3) {
- if (prof == '\x01') {
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[8];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[10];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[9];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0xb];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[7];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x578,0x1e);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[6];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x44c,100);
- (this->super_TCreature).super_TSkillBase.Skills[2]->AddLevel = 0xf;
- (this->super_TCreature).super_TSkillBase.Skills[5]->AddLevel = 0x19;
- (this->super_TCreature).super_TSkillBase.Skills[3]->AddLevel = 5;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[1];
- pp_Var4 = pTVar2->_vptr_TSkill;
- uVar5 = 3000;
- goto LAB_080ad830;
- }
-LAB_080ad742:
- this = (TPlayer *)s_TPlayer__SetProfession__Beruf__d_08104140;
-LAB_080ad750:
- error((char *)this);
- return;
- }
- if (prof == '\x03') {
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[8];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,2000,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[10];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,2000,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[9];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,2000,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0xb];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x5dc,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[7];
- pp_Var4 = pTVar2->_vptr_TSkill;
- uVar5 = 2000;
- }
- else {
- if (prof != '\x04') goto LAB_080ad742;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[8];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x708,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[10];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x708,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[9];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x708,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0xb];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x5dc,0x32);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[7];
- pp_Var4 = pTVar2->_vptr_TSkill;
- uVar5 = 0x708;
- }
- (*pp_Var4[7])(pTVar2,uVar5,0x1e);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[6];
- (*pTVar2->_vptr_TSkill[7])(pTVar2,0x5dc,100);
- (this->super_TCreature).super_TSkillBase.Skills[2]->AddLevel = 5;
- (this->super_TCreature).super_TSkillBase.Skills[5]->AddLevel = 10;
- (this->super_TCreature).super_TSkillBase.Skills[3]->AddLevel = 0x1e;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[1];
- pp_Var4 = pTVar2->_vptr_TSkill;
- uVar5 = 0x44c;
-LAB_080ad830:
- (*pp_Var4[7])(pTVar2,uVar5,0x640);
- (this->super_TCreature).Profession = prof;
- TCombat::CheckCombatValues(&(this->super_TCreature).Combat);
- DecrementNewbiesOnline();
- return;
-}
-
-
-// DWARF original prototype: bool SpellKnown(TPlayer * this, int SpellNumber)
-
-bool __thiscall TPlayer::SpellKnown(TPlayer *this,int SpellNumber)
-
-{
- bool bVar1;
-
- if ((uint)SpellNumber < 0x100) {
- bVar1 = this->SpellList[SpellNumber] != '\0';
- }
- else {
- error(&DAT_08104280,SpellNumber);
- bVar1 = false;
- }
- return bVar1;
-}
-
-
-
-// DWARF original prototype: void LearnSpell(TPlayer * this, int SpellNumber)
-
-void __thiscall TPlayer::LearnSpell(TPlayer *this,int SpellNumber)
-
-{
- if (0xff < (uint)SpellNumber) {
- error(&DAT_08104300);
- return;
- }
- if (this->SpellList[SpellNumber] == '\0') {
- this->SpellList[SpellNumber] = '\x01';
- return;
- }
- error("TPlayer::LearnSpell: Der Spieler kennt den Spruch schon.\n");
- return;
-}
-
-
-
-// DWARF original prototype: int GetQuestValue(TPlayer * this, int Number)
-
-int __thiscall TPlayer::GetQuestValue(TPlayer *this,int Number)
-
-{
- int iVar1;
-
- if ((uint)Number < 500) {
- print();
- iVar1 = this->QuestValues[Number];
- }
- else {
- error(&DAT_08103ea0,Number);
- iVar1 = 0;
- }
- return iVar1;
-}
-
-
-
-// DWARF original prototype: void SetQuestValue(TPlayer * this, int Number, int Value)
-
-void __thiscall TPlayer::SetQuestValue(TPlayer *this,int Number,int Value)
-
-{
- if (499 < (uint)Number) {
- error(&DAT_08103ee0);
- return;
- }
- print();
- this->QuestValues[Number] = Value;
- return;
-}
-
-
-
-// DWARF original prototype: void CheckOutfit(TPlayer * this)
-
-void __thiscall TPlayer::CheckOutfit(TPlayer *this)
-
-{
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar1;
- int iVar2;
- bool bVar3;
-
- bVar3 = CheckRight((this->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (bVar3) {
- if ((this->super_TCreature).OrgOutfit.OutfitID == 0x4b) {
- return;
- }
- (this->super_TCreature).OrgOutfit.field_1.Colors[0] = '\0';
- (this->super_TCreature).OrgOutfit.OutfitID = 0x4b;
- (this->super_TCreature).OrgOutfit.field_1.Colors[1] = '\0';
- (this->super_TCreature).OrgOutfit.field_1.Colors[2] = '\0';
- (this->super_TCreature).OrgOutfit.field_1.Colors[3] = '\0';
- }
- else {
- if ((this->super_TCreature).Sex == 1) {
- iVar2 = (this->super_TCreature).OrgOutfit.OutfitID;
- bVar3 = false;
- if ((0x7f < iVar2) && (iVar2 < 0x87)) {
- bVar3 = true;
- }
- if (bVar3) {
- return;
- }
- (this->super_TCreature).OrgOutfit.OutfitID = 0x80;
- }
- else {
- iVar2 = (this->super_TCreature).OrgOutfit.OutfitID;
- bVar3 = false;
- if ((0x87 < iVar2) && (iVar2 < 0x8f)) {
- bVar3 = true;
- }
- if (bVar3) {
- return;
- }
- (this->super_TCreature).OrgOutfit.OutfitID = 0x88;
- }
- builtin_memcpy(&(this->super_TCreature).OrgOutfit.field_1,"NE:L",4);
- }
- aVar1 = (this->super_TCreature).OrgOutfit.field_1;
- (this->super_TCreature).Outfit.OutfitID = (this->super_TCreature).OrgOutfit.OutfitID;
- (this->super_TCreature).Outfit.field_1 = aVar1;
- return;
-}
-
-// WARNING: Variable defined which should be unmapped: Execute_local
-// DWARF original prototype: bool MovePossible(TPlayer * this, int x, int y, int z, bool Execute,
-// bool Jump)
-
-bool __thiscall TPlayer::MovePossible(TPlayer *this,int x,int y,int z,bool Execute,bool Jump)
-
-{
- bool bVar1;
- bool bVar2;
- ushort HouseID;
- ushort HouseID_00;
- undefined4 *puVar3;
- int iVar4;
- int iVar5;
- bool Execute_local;
-
- if (Jump) {
- bVar2 = JumpPossible(x,y,z,false);
- }
- else {
- bVar2 = false;
- // try { // try from 080adffe to 080ae18e has its CatchHandler @ 080ae196
- bVar1 = CoordinateFlag();
- if (bVar1) {
- bVar2 = CoordinateFlag();
- bVar2 = !bVar2;
- }
- }
- bVar1 = false;
- if (bVar2 != false) {
- if (Execute) {
- if ((RoundNr < (this->super_TCreature).EarliestProtectionZoneRound) &&
- (bVar2 = IsProtectionZone(), bVar2)) {
- iVar5 = (this->super_TCreature).posz;
- iVar4 = (this->super_TCreature).posy;
- bVar2 = IsProtectionZone();
- if (!bVar2) {
- puVar3 = (undefined4 *)__cxa_allocate_exception(4,iVar4,iVar5);
- *puVar3 = 0x30;
- goto LAB_080ae0ab;
- }
- }
- HouseID_00 = GetHouseID(x,y,z);
- if (((HouseID_00 != 0) && (bVar2 = IsInvited(HouseID_00,this,0x7fffffff), !bVar2)) &&
- (bVar2 = CheckRight((this->super_TCreature).ID,ENTER_HOUSES), !bVar2)) {
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = 0x32;
-LAB_080ae0ab:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,&RESULT::typeinfo,0);
- }
- }
- else {
- bVar2 = CoordinateFlag();
- if (bVar2) {
- return false;
- }
- }
- bVar1 = true;
- }
- return bVar1;
-}
-
-
-
-// DWARF original prototype: void AddBuddy(TPlayer * this, char * Name)
-
-void __thiscall TPlayer::AddBuddy(TPlayer *this,char *Name)
-
-{
- int *piVar1;
- bool bVar2;
- TPlayerIndexEntry *Entry;
- TConnection *pTVar3;
- int iVar4;
- TPlayerIndexEntry *pTVar5;
- ulong CharacterID_00;
- ulong CharacterID_01;
- ulong extraout_EDX;
- ulong extraout_EDX_00;
- ulong CharacterID;
- char *pcVar6;
- TPlayer *pTStack_40;
- bool Online;
- TPlayer *pl;
- char RealName [30];
-
- if (Name == (char *)0x0) {
- pcVar6 = "TPlayer::AddBuddy: Name ist NULL.\n";
- }
- else {
- if (this->PlayerData != (TPlayerData *)0x0) {
- if (((this->PlayerData->Buddies < 100) &&
- ((bVar2 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL), bVar2 ||
- (this->PlayerData->Buddies < 100)))) &&
- ((bVar2 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT), bVar2 ||
- (this->PlayerData->Buddies < 0x14)))) {
- iVar4 = IdentifyPlayer(Name,true,true,&stack0xffffffc0);
- if (iVar4 == 0) {
- CharacterID_00 = (pTStack_40->super_TCreature).ID;
- strcpy((char *)&pl,(pTStack_40->super_TCreature).Name);
- bVar2 = true;
- }
- else {
- if (Name == (char *)0x0) {
- error("GetCharacterID: Name ist NULL.\n");
- CharacterID_00 = 0;
- }
- else {
- pTVar5 = SearchPlayerIndex(Name);
- CharacterID_00 = 0;
- if (pTVar5 != (TPlayerIndexEntry *)0x0) {
- CharacterID_00 = pTVar5->CharacterID;
- }
- }
- if (CharacterID_00 == 0) {
- SendResult((this->super_TCreature).Connection,PLAYERNOTEXISTING);
- return;
- }
- if (Name == (char *)0x0) {
- error("GetCharacterName: Name ist NULL.\n");
- pTVar5 = (TPlayerIndexEntry *)0x0;
- }
- else {
- pTVar5 = SearchPlayerIndex(Name);
- if (pTVar5 == (TPlayerIndexEntry *)0x0) {
- error("GetCharacterName: Spieler existiert nicht.\n");
- pTVar5 = (TPlayerIndexEntry *)0x8107675;
- }
- }
- strcpy((char *)&pl,pTVar5->Name);
- bVar2 = false;
- }
- iVar4 = 0;
- CharacterID_01 = this->PlayerData->Buddies;
- if (0 < (int)CharacterID_01) {
- do {
- if (this->PlayerData->Buddy[iVar4] == CharacterID_00) {
- pTVar3 = (this->super_TCreature).Connection;
- pcVar6 = "This player is already in your list.";
- goto LAB_080ae24e;
- }
- iVar4 = iVar4 + 1;
- } while (iVar4 < (int)CharacterID_01);
- }
- if ((bVar2) &&
- (bVar2 = CheckRight(CharacterID_00,NO_STATISTICS), CharacterID_01 = extraout_EDX,
- bVar2)) {
- CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- CharacterID_01 = extraout_EDX_00;
- }
- pTVar3 = (this->super_TCreature).Connection;
- SendBuddyData(pTVar3,CharacterID_01,(char *)pTVar3,SUB41(CharacterID_00,0));
- AddBuddyOrder(&this->super_TCreature,CharacterID_00);
- this->PlayerData->Buddy[this->PlayerData->Buddies] = CharacterID_00;
- strcpy(this->PlayerData->BuddyName[this->PlayerData->Buddies],(char *)&pl);
- piVar1 = &this->PlayerData->Buddies;
- *piVar1 = *piVar1 + 1;
- return;
- }
- pTVar3 = (this->super_TCreature).Connection;
- pcVar6 = "You cannot add more buddies.";
-LAB_080ae24e:
- SendMessage(pTVar3,0x17,pcVar6);
- return;
- }
- pcVar6 = "TPlayer::AddBuddy: PlayerData ist NULL.\n";
- }
- error(pcVar6);
- return;
-}
-
-
-
-// DWARF original prototype: void RemoveBuddy(TPlayer * this, ulong CharacterID)
-
-void __thiscall TPlayer::RemoveBuddy(TPlayer *this,ulong CharacterID)
-
-{
- int *piVar1;
- TPlayerData *pTVar2;
- int i;
- int iVar3;
- int Position;
- int iVar4;
-
- pTVar2 = this->PlayerData;
- if (pTVar2 == (TPlayerData *)0x0) {
- error("TPlayer::RemoveBuddy: PlayerData ist NULL.\n");
- return;
- }
- iVar3 = 0;
- iVar4 = -1;
- if (0 < pTVar2->Buddies) {
- do {
- iVar4 = iVar3;
- if (pTVar2->Buddy[iVar3] == CharacterID) break;
- iVar3 = iVar3 + 1;
- iVar4 = -1;
- } while (iVar3 < pTVar2->Buddies);
- }
- if (iVar4 == -1) {
- return;
- }
- pTVar2->Buddy[iVar4] = pTVar2->Buddy[pTVar2->Buddies + -1];
- pTVar2 = this->PlayerData;
- strcpy(pTVar2->BuddyName[iVar4],pTVar2->BuddyName[pTVar2->Buddies + -1]);
- piVar1 = &this->PlayerData->Buddies;
- *piVar1 = *piVar1 + -1;
- RemoveBuddyOrder(&this->super_TCreature,CharacterID);
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: ViewAll
-// DWARF original prototype: void SendBuddies(TPlayer * this)
-
-void __thiscall TPlayer::SendBuddies(TPlayer *this)
-
-{
- bool bVar1;
- TCreature *cr;
- TPlayerData *pTVar2;
- TCreature *pTVar3;
- TConnection *Connection;
- TPlayerData *extraout_EDX;
- TPlayerData *extraout_EDX_00;
- TPlayerData *extraout_EDX_01;
- int i;
- int iVar4;
- TConnection *Name;
- TCreature *local_18;
- bool ViewAll;
-
- if (this->PlayerData != (TPlayerData *)0x0) {
- bVar1 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- pTVar2 = this->PlayerData;
- if (0 < pTVar2->Buddies) {
- iVar4 = 0;
- do {
- pTVar3 = GetCreature(pTVar2->Buddy[iVar4]);
- local_18 = (TCreature *)0x0;
- pTVar2 = extraout_EDX;
- if ((pTVar3 != (TCreature *)0x0) && (local_18 = pTVar3, pTVar3->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- local_18 = (TCreature *)0x0;
- pTVar2 = extraout_EDX_01;
- }
- if (local_18 == (TCreature *)0x0) {
- Name = (this->super_TCreature).Connection;
- pTVar2 = this->PlayerData;
- Connection = (TConnection *)pTVar2->Buddy[iVar4];
- }
- else {
- if (!bVar1) {
- CheckRight(local_18->ID,NO_STATISTICS);
- pTVar2 = extraout_EDX_00;
- }
- Name = (this->super_TCreature).Connection;
- Connection = (TConnection *)this->PlayerData->Buddy[iVar4];
- }
- SendBuddyData(Connection,(ulong)pTVar2,(char *)Name,SUB41(Connection,0));
- iVar4 = iVar4 + 1;
- pTVar2 = this->PlayerData;
- } while (iVar4 < pTVar2->Buddies);
- }
- return;
- }
- error("TPlayer::SendBuddies: PlayerData ist NULL.\n");
- return;
-}
-
-
-
-// DWARF original prototype: void Regenerate(TPlayer * this)
-
-void __thiscall TPlayer::Regenerate(TPlayer *this)
-
-{
- TSkill *pTVar1;
- bool bVar2;
- RESULT r;
- ulong uVar3;
- int iVar4;
- int iVar5;
- time_t tVar6;
- int Fed;
- int Regeneration;
- int iVar7;
- time_t OfflineTime;
- char *pcVar8;
- Object *pOVar9;
- Object local_4c [4];
- Object local_3c [4];
- Object local_2c;
- Object Bed;
-
- iVar4 = (this->super_TCreature).posz;
- iVar7 = (this->super_TCreature).posy;
- pOVar9 = (Object *)(this->super_TCreature).posx;
- GetFirstObject();
- local_3c[0].ObjectID = ::NONE.ObjectID;
- if (local_2c.ObjectID != ::NONE.ObjectID) {
- do {
- local_4c[0].ObjectID = ::NONE.ObjectID;
- local_3c[0].ObjectID = ::NONE.ObjectID;
- Object::getObjectType(local_4c);
- pOVar9 = (Object *)0x14;
- bVar2 = ObjectType::getFlag((ObjectType *)local_4c,BED);
- if (bVar2) break;
- pOVar9 = &local_2c;
- Object::getNextObject(local_3c);
- local_2c.ObjectID = local_3c[0].ObjectID;
- local_3c[0].ObjectID = ::NONE.ObjectID;
- } while (local_2c.ObjectID != ::NONE.ObjectID);
- }
- local_4c[0].ObjectID = ::NONE.ObjectID;
- if (local_2c.ObjectID == ::NONE.ObjectID) {
- pcVar8 = "TPlayer::Regenerate: Bett nicht gefunden.\n";
- }
- else {
- Object::getObjectType(local_4c);
- pOVar9 = (Object *)0x18;
- bVar2 = ObjectType::getFlag((ObjectType *)local_4c,TEXT);
- if (bVar2) {
- uVar3 = Object::getAttribute(&local_2c,TEXTSTRING);
- if (uVar3 == 0) {
- return;
- }
- uVar3 = Object::getAttribute(&local_2c,TEXTSTRING);
- pcVar8 = GetDynamicString(uVar3);
- iVar4 = stricmp(pcVar8,(this->super_TCreature).Name,-1);
- if (iVar4 != 0) {
- return;
- }
- if ((this->PlayerData == (TPlayerData *)0x0) || (this->PlayerData->LastLogoutTime == 0))
- {
- iVar4 = 0;
- }
- else {
- tVar6 = time((time_t *)0x0);
- iVar4 = tVar6 - this->PlayerData->LastLogoutTime;
- }
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0xe];
- iVar5 = (*pTVar1->_vptr_TSkill[0xd])(pTVar1);
- iVar7 = iVar4 / 0xf;
- if (iVar5 / 3 < iVar4 / 0xf) {
- iVar7 = iVar5 / 3;
- }
- if (0 < iVar7) {
- iVar5 = iVar7 + 3;
- if (-1 < iVar7) {
- iVar5 = iVar7;
- }
- TSkill::Change((this->super_TCreature).super_TSkillBase.Skills[2],iVar5 >> 2);
- TSkill::Change((this->super_TCreature).super_TSkillBase.Skills[3],iVar7);
- pTVar1 = (this->super_TCreature).super_TSkillBase.Skills[0xe];
- (*pTVar1->_vptr_TSkill[0xd])(pTVar1);
- TSkillBase::SetTimer(&(this->super_TCreature).super_TSkillBase);
- }
- if (899 < iVar4) {
- TSkill::Change((this->super_TCreature).super_TSkillBase.Skills[0x16],iVar4 / 900);
- }
- local_4c[0].ObjectID = local_2c.ObjectID;
- local_3c[0].ObjectID = local_2c.ObjectID;
- // try { // try from 080ae8eb to 080ae8ef has its CatchHandler @ 080ae94d
- UseObjects(0,local_3c,local_4c);
- return;
- }
- pcVar8 = &DAT_081044c0;
- }
- error(pcVar8,pOVar9,iVar7,iVar4);
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: CheckFormer_local
-// DWARF original prototype: bool IsAttacker(TPlayer * this, ulong Victim, bool CheckFormer)
-
-bool __thiscall TPlayer::IsAttacker(TPlayer *this,ulong Victim,bool CheckFormer)
-
-{
- ulong *puVar1;
- int i;
- int iVar2;
- bool CheckFormer_local;
-
- iVar2 = 0;
- if (0 < this->NumberOfAttackedPlayers) {
- do {
- puVar1 = vector<>::operator()(&this->AttackedPlayers,iVar2);
- if (*puVar1 == Victim) {
- return true;
- }
- iVar2 = iVar2 + 1;
- } while (iVar2 < this->NumberOfAttackedPlayers);
- }
- if (((CheckFormer) && (RoundNr <= this->FormerLogoutRound + 5)) &&
- (iVar2 = 0, 0 < this->NumberOfFormerAttackedPlayers)) {
- do {
- puVar1 = vector<>::operator()(&this->FormerAttackedPlayers,iVar2);
- if (*puVar1 == Victim) {
- return true;
- }
- iVar2 = iVar2 + 1;
- } while (iVar2 < this->NumberOfFormerAttackedPlayers);
- }
- return false;
-}
-
-
-
-// DWARF original prototype: bool IsAggressor(TPlayer * this, bool CheckFormer)
-
-bool __thiscall TPlayer::IsAggressor(TPlayer *this,bool CheckFormer)
-
-{
- bool bVar1;
-
- if ((this->Aggressor != false) ||
- (((CheckFormer && (RoundNr <= this->FormerLogoutRound + 5)) &&
- (this->FormerAggressor != false)))) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- return bVar1;
-}
-
-
-
-// DWARF original prototype: bool IsAttackJustified(TPlayer * this, ulong Victim)
-
-bool __thiscall TPlayer::IsAttackJustified(TPlayer *this,ulong Victim)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- TPlayer *this_00;
- ulong uVar3;
- ulong uVar4;
-
- pTVar2 = (TPlayer *)GetCreature(Victim);
- this_00 = (TPlayer *)0x0;
- if ((pTVar2 != (TPlayer *)0x0) && (this_00 = pTVar2, (pTVar2->super_TCreature).Type != PLAYER))
- {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- this_00 = (TPlayer *)0x0;
- }
- if (this_00 == (TPlayer *)0x0) {
- error("TPlayer::IsAttackJustified: Opfer existiert nicht.\n");
- }
- else if ((WorldType != PVP_ENFORCED) && (this_00->PlayerData->PlayerkillerEnd == 0)) {
- if ((this_00->Aggressor == false) &&
- ((this_00->FormerLogoutRound + 5 < RoundNr || (this_00->FormerAggressor == false)))) {
- bVar1 = false;
- }
- else {
- bVar1 = true;
- }
- if (!bVar1) {
- uVar4 = this->PartyLeavingRound;
- if ((uVar4 == 0) || (RoundNr <= uVar4 + 5)) {
- uVar3 = this->PartyLeader;
- }
- else {
- uVar3 = 0;
- }
- if (uVar3 != 0) {
- if ((uVar4 == 0) || (RoundNr <= uVar4 + 5)) {
- uVar4 = this->PartyLeader;
- }
- else {
- uVar4 = 0;
- }
- if ((this_00->PartyLeavingRound == 0) || (RoundNr <= this_00->PartyLeavingRound + 5)
- ) {
- uVar3 = this_00->PartyLeader;
- }
- else {
- uVar3 = 0;
- }
- if (uVar4 == uVar3) {
- return true;
- }
- }
- bVar1 = IsAttacker(this_00,(this->super_TCreature).ID,true);
- return bVar1;
- }
- }
- return true;
-}
-
-
-
-// DWARF original prototype: void RecordAttack(TPlayer * this, ulong Victim)
-
-void __thiscall TPlayer::RecordAttack(TPlayer *this,ulong Victim)
-
-{
- TConnection *this_00;
- bool bVar1;
- TCreature *cr;
- TPlayer *pTVar2;
- ulong *puVar3;
- KNOWNCREATURESTATE KVar4;
- ulong uVar5;
- ulong uVar6;
- TPlayer *this_01;
-
- if (WorldType != NORMAL) {
- return;
- }
- if (Victim == (this->super_TCreature).ID) {
- return;
- }
- pTVar2 = (TPlayer *)GetCreature(Victim);
- this_01 = (TPlayer *)0x0;
- if ((pTVar2 != (TPlayer *)0x0) && (this_01 = pTVar2, (pTVar2->super_TCreature).Type != PLAYER))
- {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- this_01 = (TPlayer *)0x0;
- }
- if (this_01 == (TPlayer *)0x0) {
- error("TPlayer::RecordAttack: Opfer existiert nicht.\n");
- return;
- }
- bVar1 = IsAttacker(this_01,(this->super_TCreature).ID,true);
- if ((!bVar1) && (bVar1 = IsAttacker(this,Victim,false), !bVar1)) {
- uVar6 = this->PartyLeavingRound;
- if ((uVar6 == 0) || (RoundNr <= uVar6 + 5)) {
- uVar5 = this->PartyLeader;
- }
- else {
- uVar5 = 0;
- }
- if (uVar5 != 0) {
- if ((uVar6 == 0) || (RoundNr <= uVar6 + 5)) {
- uVar6 = this->PartyLeader;
- }
- else {
- uVar6 = 0;
- }
- if ((this_01->PartyLeavingRound == 0) || (RoundNr <= this_01->PartyLeavingRound + 5)) {
- uVar5 = this_01->PartyLeader;
- }
- else {
- uVar5 = 0;
- }
- if (uVar6 == uVar5) goto LAB_080aec5e;
- }
- puVar3 = vector<>::operator()(&this->AttackedPlayers,this->NumberOfAttackedPlayers);
- *puVar3 = Victim;
- this->NumberOfAttackedPlayers = this->NumberOfAttackedPlayers + 1;
- print();
- this_00 = (this_01->super_TCreature).Connection;
- if ((this_00 != (TConnection *)0x0) &&
- (KVar4 = TConnection::KnownCreature(this_00,(this->super_TCreature).ID,false),
- KVar4 == KNOWNCREATURE_UPTODATE)) {
- SendCreatureSkull((this_01->super_TCreature).Connection,(this->super_TCreature).ID);
- }
- }
-LAB_080aec5e:
- bVar1 = IsAttackJustified(this,Victim);
- if ((!bVar1) && (this->Aggressor == false)) {
- this->Aggressor = true;
- print();
- AnnounceChangedCreature((this->super_TCreature).ID,5);
- return;
- }
- return;
-}
-
-
-
-// DWARF original prototype: void RecordMurder(TPlayer * this, ulong Victim)
-
-void __thiscall TPlayer::RecordMurder(TPlayer *this,ulong Victim)
-
-{
- TPlayerData *pTVar1;
- int iVar2;
- bool bVar3;
- TCreature *cr;
- TCreature *pTVar4;
- time_t tVar5;
- int i;
- int iVar6;
- TCreature *pTVar7;
- int Playerkilling;
-
- if (((WorldType == NORMAL) && (Victim != (this->super_TCreature).ID)) &&
- (bVar3 = IsAttackJustified(this,Victim), !bVar3)) {
- pTVar4 = GetCreature(Victim);
- pTVar7 = (TCreature *)0x0;
- if ((pTVar4 != (TCreature *)0x0) && (pTVar7 = pTVar4, pTVar4->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar7 = (TCreature *)0x0;
- }
- if (pTVar7 == (TCreature *)0x0) {
- error("TPlayer::RecordMurder: Opfer existiert nicht.\n");
- return;
- }
- print();
- iVar6 = 1;
- do {
- this->PlayerData->MurderTimestamps[iVar6 + -1] =
- this->PlayerData->MurderTimestamps[iVar6];
- iVar6 = iVar6 + 1;
- } while (iVar6 < 0x14);
- pTVar1 = this->PlayerData;
- tVar5 = time((time_t *)0x0);
- pTVar1->MurderTimestamps[0x13] = tVar5;
- SendMessage((this->super_TCreature).Connection,0x12,
- "Warning! The murder of %s was not justified.",pTVar7->Name);
- iVar6 = CheckPlayerkilling(this);
- if (iVar6 != 0) {
- pTVar1 = this->PlayerData;
- iVar2 = pTVar1->PlayerkillerEnd;
- tVar5 = time((time_t *)0x0);
- pTVar1->PlayerkillerEnd = tVar5 + 0x278d00;
- if (iVar2 == 0) {
- print();
- AnnounceChangedCreature((this->super_TCreature).ID,5);
- }
- if (iVar6 == 2) {
- PunishmentOrder((TCreature *)0x0,(this->super_TCreature).Name,this->IPAddress,0x1c,2
- ,"Exceeding the limit of unjustified kills by 100%.",0,
- (vector<> *)0x0,0,false);
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: LastMonth
-// DWARF original prototype: int CheckPlayerkilling(TPlayer * this)
-
-int __thiscall TPlayer::CheckPlayerkilling(TPlayer *this)
-
-{
- int iVar1;
- int iVar2;
- int Now;
- time_t tVar3;
- int i;
- int iVar4;
- int LastDay;
- int iVar5;
- int LastWeek;
- int iVar6;
- int local_14;
- int LastMonth;
-
- local_14 = 0;
- tVar3 = time((time_t *)0x0);
- iVar4 = 0;
- iVar5 = 0;
- iVar6 = 0;
- do {
- iVar1 = this->PlayerData->MurderTimestamps[iVar4];
- iVar2 = local_14;
- if (iVar1 != 0) {
- if (tVar3 + -0x15180 < iVar1) {
- iVar5 = iVar5 + 1;
- }
- if (tVar3 + -0x93a80 < iVar1) {
- iVar6 = iVar6 + 1;
- }
- iVar2 = local_14 + 1;
- if (iVar1 <= tVar3 + -0x278d00) {
- iVar2 = local_14;
- }
- }
- local_14 = iVar2;
- iVar4 = iVar4 + 1;
- } while (iVar4 < 0x14);
- if (((iVar5 < 6) && (iVar6 < 10)) && (local_14 < 0x14)) {
- if (((2 < iVar5) || (4 < iVar6)) || (iVar5 = 0, 9 < local_14)) {
- iVar5 = 1;
- }
- }
- else {
- iVar5 = 2;
- }
- return iVar5;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Victim_local
-// DWARF original prototype: void ClearAttacker(TPlayer * this, ulong Victim)
-
-void __thiscall TPlayer::ClearAttacker(TPlayer *this,ulong Victim)
-
-{
- vector<> *this_00;
- TCreature *cr;
- ulong *puVar1;
- ulong *puVar2;
- TCreature *pTVar3;
- KNOWNCREATURESTATE KVar4;
- int i;
- int i_00;
- TCreature *pTVar5;
- ulong Victim_local;
-
- i_00 = 0;
- if (0 < this->NumberOfAttackedPlayers) {
- this_00 = &this->AttackedPlayers;
- do {
- puVar1 = vector<>::operator()(this_00,i_00);
- if (*puVar1 == Victim) {
- puVar1 = vector<>::operator()(this_00,i_00);
- puVar2 = vector<>::operator()(this_00,this->NumberOfAttackedPlayers + -1);
- *puVar1 = *puVar2;
- this->NumberOfAttackedPlayers = this->NumberOfAttackedPlayers + -1;
- pTVar3 = GetCreature(Victim);
- pTVar5 = (TCreature *)0x0;
- if ((pTVar3 != (TCreature *)0x0) && (pTVar5 = pTVar3, pTVar3->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar5 = (TCreature *)0x0;
- }
- if (pTVar5 == (TCreature *)0x0) {
- return;
- }
- print();
- if (pTVar5->Connection == (TConnection *)0x0) {
- return;
- }
- KVar4 = TConnection::KnownCreature
- (pTVar5->Connection,(this->super_TCreature).ID,false);
- if (KVar4 != KNOWNCREATURE_UPTODATE) {
- return;
- }
- SendCreatureSkull(pTVar5->Connection,(this->super_TCreature).ID);
- return;
- }
- i_00 = i_00 + 1;
- } while (i_00 < this->NumberOfAttackedPlayers);
- }
- return;
-}
-
-
-
-// DWARF original prototype: void ClearPlayerkillingMarks(TPlayer * this)
-
-void __thiscall TPlayer::ClearPlayerkillingMarks(TPlayer *this)
-
-{
- char cVar1;
- TCreature *cr;
- ulong *puVar2;
- ulong *puVar3;
- TCreature *pTVar4;
- KNOWNCREATURESTATE KVar5;
- TPlayer **ppTVar6;
- TPlayer *pl;
- int i_2;
- int iVar7;
- int i;
- int iVar8;
- int iVar9;
- TCreature *pTVar10;
-
- print();
- iVar7 = this->NumberOfAttackedPlayers;
- this->FormerLogoutRound = RoundNr;
- cVar1 = this->Aggressor;
- this->NumberOfFormerAttackedPlayers = iVar7;
- this->FormerAggressor = (bool)cVar1;
- if (0 < iVar7) {
- iVar9 = 0;
- do {
- puVar2 = vector<>::operator()(&this->FormerAttackedPlayers,iVar9);
- iVar8 = iVar9 + 1;
- puVar3 = vector<>::operator()(&this->AttackedPlayers,iVar9);
- *puVar2 = *puVar3;
- iVar7 = this->NumberOfAttackedPlayers;
- iVar9 = iVar8;
- } while (iVar8 < iVar7);
- cVar1 = this->Aggressor;
- }
- if (cVar1 != '\0') {
- this->Aggressor = false;
- this->NumberOfAttackedPlayers = 0;
- print();
- AnnounceChangedCreature((this->super_TCreature).ID,5);
- iVar7 = this->NumberOfAttackedPlayers;
- }
- if ((0 < iVar7) && (this->NumberOfAttackedPlayers = 0, 0 < iVar7)) {
- iVar9 = 0;
- do {
- puVar2 = vector<>::operator()(&this->AttackedPlayers,iVar9);
- pTVar4 = GetCreature(*puVar2);
- pTVar10 = (TCreature *)0x0;
- if ((pTVar4 != (TCreature *)0x0) && (pTVar10 = pTVar4, pTVar4->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar10 = (TCreature *)0x0;
- }
- if (pTVar10 != (TCreature *)0x0) {
- print();
- if ((pTVar10->Connection != (TConnection *)0x0) &&
- (KVar5 = TConnection::KnownCreature
- (pTVar10->Connection,(this->super_TCreature).ID,false),
- KVar5 == KNOWNCREATURE_UPTODATE)) {
- SendCreatureSkull(pTVar10->Connection,(this->super_TCreature).ID);
- }
- }
- iVar9 = iVar9 + 1;
- } while (iVar9 < iVar7);
- }
- iVar7 = 0;
- if (0 < FirstFreePlayer) {
- do {
- ppTVar6 = vector<TPlayer*>::operator()(&PlayerList,iVar7);
- if (*ppTVar6 == (TPlayer *)0x0) {
- error("TPlayer::ClearPlayerkillingMarks: Spieler %d existiert nicht.\n",iVar7);
- }
- else {
- ClearAttacker(*ppTVar6,(this->super_TCreature).ID);
- }
- iVar7 = iVar7 + 1;
- } while (iVar7 < FirstFreePlayer);
- }
- return;
-}
-
-
-
-// DWARF original prototype: int GetPlayerkillingMark(TPlayer * this, TPlayer * Observer)
-
-int __thiscall TPlayer::GetPlayerkillingMark(TPlayer *this,TPlayer *Observer)
-
-{
- bool bVar1;
- ulong uVar2;
- ulong uVar3;
-
- if (WorldType == NORMAL) {
- if (Observer != (TPlayer *)0x0) {
- if (this->PlayerData->PlayerkillerEnd != 0) {
- return 4;
- }
- if (this->Aggressor != false) {
- return 3;
- }
- uVar2 = 0;
- if (this->PartyLeavingRound == 0) {
- uVar2 = this->PartyLeader;
- }
- if (uVar2 != 0) {
- uVar2 = 0;
- if (this->PartyLeavingRound == 0) {
- uVar2 = this->PartyLeader;
- }
- if (Observer->PartyLeavingRound == 0) {
- uVar3 = Observer->PartyLeader;
- }
- else {
- uVar3 = 0;
- }
- if (uVar2 == uVar3) {
- return 2;
- }
- }
- bVar1 = IsAttacker(this,(Observer->super_TCreature).ID,false);
- return (uint)bVar1;
- }
- error("TPlayer::GetPlayerkillingMark: Beobachter existiert nicht.\n");
- }
- return 0;
-}
-
-
-
-// DWARF original prototype: ulong GetPartyLeader(TPlayer * this, bool CheckFormer)
-
-ulong __thiscall TPlayer::GetPartyLeader(TPlayer *this,bool CheckFormer)
-
-{
- if (this->PartyLeavingRound != 0) {
- if (!CheckFormer) {
- return 0;
- }
- if (this->PartyLeavingRound + 5 < RoundNr) {
- return 0;
- }
- }
- return this->PartyLeader;
-}
-
-
-
-// DWARF original prototype: void JoinParty(TPlayer * this, ulong Leader)
-
-void __thiscall TPlayer::JoinParty(TPlayer *this,ulong Leader)
-
-{
- this->PartyLeavingRound = 0;
- this->PartyLeader = Leader;
- return;
-}
-
-
-
-// DWARF original prototype: void LeaveParty(TPlayer * this)
-
-void __thiscall TPlayer::LeaveParty(TPlayer *this)
-
-{
- this->PartyLeavingRound = RoundNr;
- return;
-}
-
-
-
-// DWARF original prototype: int GetPartyMark(TPlayer * this, TPlayer * Observer)
-
-int __thiscall TPlayer::GetPartyMark(TPlayer *this,TPlayer *Observer)
-
-{
- bool bVar1;
- ulong uVar2;
- ulong uVar3;
- ulong uVar4;
- ulong Guest;
- ulong local_18;
-
- if (Observer == (TPlayer *)0x0) {
- error("TPlayer::GetPartyMark: Beobachter existiert nicht.\n");
- }
- else {
- uVar2 = Observer->PartyLeavingRound;
- uVar3 = 0;
- if (uVar2 == 0) {
- uVar3 = Observer->PartyLeader;
- }
- Guest = (this->super_TCreature).ID;
- if (Guest == uVar3) {
- return 4;
- }
- uVar4 = 0;
- uVar3 = this->PartyLeavingRound;
- if (uVar3 == 0) {
- uVar4 = this->PartyLeader;
- }
- if (uVar4 != 0) {
- local_18 = 0;
- if (uVar3 == 0) {
- local_18 = this->PartyLeader;
- }
- uVar4 = 0;
- if (uVar2 == 0) {
- uVar4 = Observer->PartyLeader;
- }
- if (local_18 == uVar4) {
- return 3;
- }
- }
- uVar4 = 0;
- if (uVar2 == 0) {
- uVar4 = Observer->PartyLeader;
- }
- uVar2 = (Observer->super_TCreature).ID;
- if (uVar2 == uVar4) {
- bVar1 = IsInvitedToParty(Guest,uVar2);
- if (bVar1) {
- return 2;
- }
- Guest = (this->super_TCreature).ID;
- uVar3 = this->PartyLeavingRound;
- }
- uVar2 = 0;
- if (uVar3 == 0) {
- uVar2 = this->PartyLeader;
- }
- if ((Guest == uVar2) &&
- (bVar1 = IsInvitedToParty((Observer->super_TCreature).ID,Guest), bVar1)) {
- return 1;
- }
- }
- return 0;
-}
-
-
-
-// DWARF original prototype: int RecordTalk(TPlayer * this)
-
-int __thiscall TPlayer::RecordTalk(TPlayer *this)
-
-{
- uint uVar1;
- uint uVar2;
- ulong uVar3;
- int iVar4;
-
- uVar3 = RoundNr;
- uVar1 = this->TalkBufferFullTime;
- uVar2 = ServerMilliseconds;
- if ((ServerMilliseconds < uVar1) && (uVar2 = uVar1, ServerMilliseconds < uVar1 - 0x1d4c)) {
- iVar4 = this->NumberOfMutings + 1;
- this->NumberOfMutings = iVar4;
- iVar4 = iVar4 * iVar4 * 5;
- this->MutingEndRound = uVar3 + iVar4;
- }
- else {
- this->TalkBufferFullTime = uVar2 + 0x9c4;
- iVar4 = 0;
- }
- return iVar4;
-}
-
-
-
-// DWARF original prototype: int RecordMessage(TPlayer * this, ulong Addressee)
-
-int __thiscall TPlayer::RecordMessage(TPlayer *this,ulong Addressee)
-
-{
- ulong uVar1;
- int i;
- int iVar2;
- int FreeSlot;
- int iVar3;
-
- uVar1 = RoundNr;
- iVar2 = 0;
- iVar3 = -1;
- do {
- if (this->Addressees[iVar2] == Addressee) {
- this->AddresseesTimes[iVar2] = RoundNr;
- goto LAB_080af797;
- }
- if ((this->Addressees[iVar2] == 0) || (this->AddresseesTimes[iVar2] < RoundNr - 600)) {
- iVar3 = iVar2;
- }
- iVar2 = iVar2 + 1;
- } while (iVar2 < 0x14);
- if (iVar3 < 0) {
- iVar3 = this->NumberOfMutings + 1;
- this->NumberOfMutings = iVar3;
- iVar3 = iVar3 * iVar3 * 5;
- this->MutingEndRound = uVar1 + iVar3;
- }
- else {
- this->Addressees[iVar3] = Addressee;
- this->AddresseesTimes[iVar3] = RoundNr;
-LAB_080af797:
- iVar3 = 0;
- }
- return iVar3;
-}
-
-
-
-// DWARF original prototype: int CheckForMuting(TPlayer * this)
-
-int __thiscall TPlayer::CheckForMuting(TPlayer *this)
-
-{
- int iVar1;
-
- iVar1 = 0;
- if (RoundNr < this->MutingEndRound) {
- iVar1 = this->MutingEndRound - RoundNr;
- }
- return iVar1;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void InitPlayer(void)
-
-{
- TPlayerData *pTVar1;
-
- FirstFreePlayer = 0;
- pTVar1 = PlayerDataPool;
- do {
- pTVar1->CharacterID = 0;
- pTVar1 = pTVar1 + 1;
- } while ((int)pTVar1 < 0x907a435);
- // try { // try from 080af836 to 080af83f has its CatchHandler @ 080af842
- CreatePlayerList(true);
- InitPlayerIndex();
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ExitPlayer(void)
-
-{
- ExitPlayerPool();
- CreatePlayerList(false);
- return;
-}
-
-
-
void __tcf_0(void *param_1)
{
diff --git a/src/common.hh b/src/common.hh index 4737c54..384d76e 100644 --- a/src/common.hh +++ b/src/common.hh @@ -16,6 +16,8 @@ typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; typedef uintptr_t uintptr; typedef size_t usize; diff --git a/src/connection.hh b/src/connection.hh index 4a5e544..5e2b1ba 100644 --- a/src/connection.hh +++ b/src/connection.hh @@ -20,6 +20,8 @@ struct TConnection { bool IsVisible(int x, int y, int z); void EnterGame(void); const char *GetIPAddress(void); + void Die(void); + KNOWNCREATURESTATE KnownCreature(uint32 CreatureID, bool UpdateFollows); // DATA // ================= @@ -184,6 +184,8 @@ struct TSkill{ int GetProgress(void); void Check(void); void Change(int Amount); + void SetMax(void); + void DecreasePercent(int Percent); void SetMDAct(int MDAct); void Load(int Act, int Max, int Min, int DAct, int MDAct, int Cycle, int MaxCycle, int Count, int MaxCount, int AddLevel, @@ -716,45 +718,61 @@ struct TPlayer: TCreature { TPlayer(TConnection *Connection, uint32 CharacterID); void SetInList(void); void DelInList(void); - -//== - - // TODO(fusion): Eventually sort these out when we implement player functions. + void ClearRequest(void); + void ClearConnection(void); + void LoadData(void); + void SaveData(void); + void LoadInventory(bool SetStandardInventory); + void SaveInventory(void); + void StartCoordinates(void); + void TakeOver(TConnection *Connection); + void SetOpenContainer(int ContainerNr, Object Con); + Object GetOpenContainer(int ContainerNr); + void CloseAllContainers(void); + Object InspectTrade(bool OwnOffer, int Position); + void AcceptTrade(void); + void RejectTrade(void); + void ClearProfession(void); + void SetProfession(uint8 Profession); uint8 GetRealProfession(void); uint8 GetEffectiveProfession(void); uint8 GetActiveProfession(void); bool GetActivePromotion(void); - void ClearProfession(void); - void SetProfession(uint8 Profession); - int GetQuestValue(int Number); - void SetQuestValue(int Number, int Value); - void JoinParty(uint32 Leader); - void LeaveParty(void); - uint32 GetPartyLeader(bool CheckFormer); bool SpellKnown(int SpellNr); - bool IsAttackJustified(uint32 Victim); - void RecordAttack(uint32 Victim); - void RecordMurder(uint32 Victim); + void LearnSpell(int SpellNr); + int GetQuestValue(int QuestNr); + void SetQuestValue(int QuestNr, int Value); + void CheckOutfit(void); void CheckState(void); + void AddBuddy(const char *Name); + void RemoveBuddy(uint32 CharacterID); + void SendBuddies(void); + void Regenerate(void); + bool IsAttacker(uint32 VictimID, bool CheckFormer); + bool IsAggressor(bool CheckFormer); + bool IsAttackJustified(uint32 VictimID); + void RecordAttack(uint32 VictimID); + void RecordMurder(uint32 VictimID); + int CheckPlayerkilling(int Now); + void ClearAttacker(uint32 VictimID); void ClearPlayerkillingMarks(void); - void SaveInventory(void); - Object GetOpenContainer(int ContainerNr); - void SetOpenContainer(int ContainerNr, Object Con); - void RejectTrade(void); - Object InspectTrade(bool OwnOffer, int Position); - int CheckForMuting(void); + int GetPlayerkillingMark(TPlayer *Observer); + uint32 GetPartyLeader(bool CheckFormer); + void JoinParty(uint32 LeaderID); + void LeaveParty(void); + int GetPartyMark(TPlayer *Observer); int RecordTalk(void); - int RecordMessage(uint32 Addressee); - void LoadData(void); - void SaveData(void); - void CheckOutfit(void); - void Regenerate(void); - void LoadInventory(bool SetDefaultInventory); - void SendBuddies(void); + int RecordMessage(uint32 AddresseeID); + int CheckForMuting(void); // VIRTUAL FUNCTIONS // ================= ~TPlayer(void) override; + void Death(void) override; + bool MovePossible(int x, int y, int z, bool Execute, bool Jump) override; + void DamageStimulus(uint32 AttackerID, int Damage, int DamageType) override; + void IdleStimulus(void) override; + void AttackStimulus(uint32 AttackerID) override; // DATA // ================= diff --git a/src/crmain.cc b/src/crmain.cc index ddf5393..a98f33e 100644 --- a/src/crmain.cc +++ b/src/crmain.cc @@ -1050,8 +1050,8 @@ void ProcessCreatures(void){ // 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 + int FoodInterval = Creature->Skills[SKILL_FED]->Get(); + if(FoodInterval > 0 && (RoundNr % FoodInterval) == 0 && !Creature->IsDead && !IsProtectionZone(Creature->posx, Creature->posy, Creature->posz)){ Creature->Skills[SKILL_HITPOINTS]->Change(1); Creature->Skills[SKILL_MANA]->Change(4); diff --git a/src/crplayer.cc b/src/crplayer.cc index 67ff996..24fcd56 100644 --- a/src/crplayer.cc +++ b/src/crplayer.cc @@ -1,4 +1,5 @@ #include "cr.hh" +#include "config.hh" #include "info.hh" #include "operate.hh" #include "query.hh" @@ -84,35 +85,39 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): this->AddresseesTimes[AddresseeNr] = 0; } - TPlayerData *Slot = AttachPlayerPoolSlot(CharacterID, false); - if(Slot == NULL){ + TPlayerData *PlayerData = AttachPlayerPoolSlot(CharacterID, false); + if(PlayerData == NULL){ error("TPlayer::TPlayer: PlayerData-Slot nicht gefunden.\n"); this->ConstructError = ERROR; return; } - SendMails(Slot); - - this->PlayerData = Slot; + SendMails(PlayerData); + this->PlayerData = PlayerData; this->Connection = Connection; - strcpy(this->Name, Slot->Name); - this->SetID(CharacterID); + strcpy(this->Name, PlayerData->Name); + // TODO(fusion): There is a try..catch block somewhere in here that also sets + // `this->ConstructorError` but I couldn't figure its scope. It could be the + // whole function from this point. + // I couldn't find any functions here with unhandled exceptions so we might + // want to keep an eye out. + this->SetID(CharacterID); InsertPlayerIndex(&PlayerIndexHead, 0, this->Name, CharacterID); this->LoadData(); - this->AccountID = Slot->AccountID; + this->AccountID = PlayerData->AccountID; strcpy(this->IPAddress, Connection->GetIPAddress()); - STATIC_ASSERT(sizeof(this->Rights) == sizeof(Slot->Rights)); - memcpy(this->Rights, Slot->Rights, sizeof(this->Rights)); + STATIC_ASSERT(sizeof(this->Rights) == sizeof(PlayerData->Rights)); + memcpy(this->Rights, PlayerData->Rights, sizeof(this->Rights)); - this->Sex = Slot->Sex; - strcpy(this->Guild, Slot->Guild); - strcpy(this->Rank, Slot->Rank); - strcpy(this->Title, Slot->Title); + this->Sex = PlayerData->Sex; + strcpy(this->Guild, PlayerData->Guild); + strcpy(this->Rank, PlayerData->Rank); + strcpy(this->Title, PlayerData->Title); - if(Slot->PlayerkillerEnd < (int)time(NULL)){ - Slot->PlayerkillerEnd = 0; + if(PlayerData->PlayerkillerEnd < (int)time(NULL)){ + PlayerData->PlayerkillerEnd = 0; } this->CheckOutfit(); @@ -145,15 +150,15 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): this->Skills[SkillNr]->DAct = 0; } - this->Skills[SKILL_HITPOINTS]->Set(this->Skills[SKILL_HITPOINTS]->Max); - this->Skills[SKILL_MANA ]->Set(this->Skills[SKILL_MANA ]->Max); + this->Skills[SKILL_HITPOINTS]->SetMax(); + this->Skills[SKILL_MANA ]->SetMax(); this->Outfit = this->OrgOutfit; this->posx = this->startx; this->posy = this->starty; this->posz = this->startz; } - if(Slot->LastLoginTime == 0 && CheckRight(CharacterID, GAMEMASTER_OUTFIT)){ + if(PlayerData->LastLoginTime == 0 && CheckRight(CharacterID, GAMEMASTER_OUTFIT)){ Log("game", "Gamemaster-Charakter %s loggt zum ersten Mal ein -> Level 2 setzen.\n", this->Name); this->Skills[SKILL_LEVEL]->Act = 2; this->Skills[SKILL_LEVEL]->Exp = 100; @@ -167,7 +172,7 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): uint16 HouseID = GetHouseID(this->posx, this->posy, this->posz); if(HouseID != 0 - && !IsInvited(HouseID, this, Slot->LastLogoutTime) + && !IsInvited(HouseID, this, PlayerData->LastLogoutTime) && !CheckRight(CharacterID, ENTER_HOUSES)){ GetExitPosition(HouseID, &this->posx, &this->posy, &this->posz); } @@ -194,7 +199,7 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): SendRights(Connection); SendFullScreen(Connection); GraphicalEffect(this->CrObject, EFFECT_ENERGY); - this->LoadInventory(Slot->LastLoginTime == 0); + this->LoadInventory(PlayerData->LastLoginTime == 0); this->NotifyChangeInventory(); SendAmbiente(Connection); AnnounceChangedCreature(CharacterID, CREATURE_LIGHT_CHANGED); @@ -202,9 +207,9 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): this->CheckState(); this->SendBuddies(); - if(Slot->LastLoginTime != 0){ + if(PlayerData->LastLoginTime != 0){ char TimeString[100]; - struct tm LastLogin = GetLocalTimeTM(Slot->LastLoginTime); + struct tm LastLogin = GetLocalTimeTM(PlayerData->LastLoginTime); strftime(TimeString, sizeof(TimeString), "%d. %b %Y %X %Z", &LastLogin); SendMessage(Connection, TALK_LOGIN_MESSAGE, "Your last visit in Tibia: %s.", TimeString); @@ -215,7 +220,7 @@ TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID): SendOutfit(Connection); } - Slot->LastLoginTime = time(NULL); + PlayerData->LastLoginTime = time(NULL); } TPlayer::~TPlayer(void){ @@ -226,8 +231,8 @@ TPlayer::~TPlayer(void){ } ASSERT(this->PlayerData); - TPlayerData *Slot = this->PlayerData; - Slot->LastLogoutTime = time(NULL); + TPlayerData *PlayerData = this->PlayerData; + PlayerData->LastLogoutTime = time(NULL); this->SaveData(); if(!this->IsDead){ @@ -237,12 +242,12 @@ TPlayer::~TPlayer(void){ }else{ Log("game", "Spieler %s ist gestorben.\n", this->Name); - // NOTE(fusion): This is a disaster. We're deleting the slot's inventory - // here so `~TCreature` can handle dropping loot and then re-generate it - // with `SaveInventory` if `LoseInventory` is not `LOSE_INVENTORY_ALL`, - // which makes sense but is poorly executed. - delete[] Slot->Inventory; - Slot->Inventory = NULL; + // NOTE(fusion): This is a disaster. We're deleting inventory data here + // so `~TCreature` can handle dropping loot and then re-generate it with + // `SaveInventory` if `LoseInventory` is not `LOSE_INVENTORY_ALL`, which + // makes sense but is poorly executed. + delete[] PlayerData->Inventory; + PlayerData->Inventory = NULL; bool ResetCharacter = false; if(this->Profession != PROFESSION_NONE && this->Skills[SKILL_LEVEL]->Get() <= 5){ @@ -254,38 +259,39 @@ TPlayer::~TPlayer(void){ } if(ResetCharacter){ - Slot->CurrentOutfit = Slot->OriginalOutfit; - Slot->startx = 0; - Slot->starty = 0; - Slot->startz = 0; - Slot->posx = 0; - Slot->posy = 0; - Slot->posz = 0; - Slot->Profession = PROFESSION_NONE; + PlayerData->CurrentOutfit = PlayerData->OriginalOutfit; + PlayerData->startx = 0; + PlayerData->starty = 0; + PlayerData->startz = 0; + PlayerData->posx = 0; + PlayerData->posy = 0; + PlayerData->posz = 0; + PlayerData->Profession = PROFESSION_NONE; for(int SpellNr = 0; - SpellNr < NARRAY(Slot->SpellList); + SpellNr < NARRAY(PlayerData->SpellList); SpellNr += 1){ - Slot->SpellList[SpellNr] = 0; + PlayerData->SpellList[SpellNr] = 0; } for(int QuestNr = 0; - QuestNr < NARRAY(Slot->QuestValues); + QuestNr < NARRAY(PlayerData->QuestValues); QuestNr += 1){ - Slot->QuestValues[QuestNr] = 0; + PlayerData->QuestValues[QuestNr] = 0; } - // TODO(fusion): This one looks sketchy. + // NOTE(fusion): This is used to reset skills back to default. See + // `LoadData`. for(int SkillNr = 0; - SkillNr < NARRAY(Slot->Minimum); + SkillNr < NARRAY(PlayerData->Minimum); SkillNr += 1){ - Slot->Minimum[SkillNr] = INT_MIN; + PlayerData->Minimum[SkillNr] = INT_MIN; } this->LoseInventory = LOSE_INVENTORY_ALL; } - if(Slot->PlayerkillerEnd != 0){ + if(PlayerData->PlayerkillerEnd != 0){ this->LoseInventory = LOSE_INVENTORY_ALL; } @@ -298,22 +304,7 @@ TPlayer::~TPlayer(void){ CloseProcessedRequests(this->ID); } - if(this->Request != 0){ - if(this->RequestProcessingGamemaster == 0){ - DeleteGamemasterRequest(this->Name); - }else{ - TCreature *Gamemaster = GetCreature(this->RequestProcessingGamemaster); - if(Gamemaster != NULL){ - if(Gamemaster->Type == PLAYER){ - SendFinishRequest(Gamemaster->Connection, this->Name); - }else{ - error("GetPlayer: Kreatur ist kein Spieler.\n"); - } - } - } - this->Request = 0; - } - + this->ClearRequest(); LeaveAllChannels(this->ID); if(this->GetPartyLeader(false) != 0){ @@ -323,10 +314,99 @@ TPlayer::~TPlayer(void){ this->ClearPlayerkillingMarks(); this->DelInList(); - Slot->Dirty = true; - // TODO(fusion): Something is telling me that `Slot->Sticky` is also poorly managed. - DecreasePlayerPoolSlotSticky(Slot); - ReleasePlayerPoolSlot(Slot); + PlayerData->Dirty = true; + // TODO(fusion): Something is telling me that `PlayerData->Sticky` is also poorly managed. + DecreasePlayerPoolSlotSticky(PlayerData); + ReleasePlayerPoolSlot(PlayerData); +} + +void TPlayer::Death(void){ + if(CheckRight(this->ID, INVULNERABLE)){ + error("TPlayer::Death: Aha, so geht das aber nicht!! Goetter kann man nicht toeten!!\n"); + this->Skills[SKILL_HITPOINTS]->SetMax(); + return; + } + + if(this->Connection != NULL){ + SendPlayerData(this->Connection); + SendMessage(this->Connection, TALK_EVENT_MESSAGE, "You are dead.\n"); + this->Connection->Die(); + } + + TCreature::Death(); + + if(WorldType == PVP_ENFORCED){ + this->Combat.DistributeExperiencePoints(this->Skills[SKILL_LEVEL]->Exp / 20); + } + + // TODO(fusion): Probably related to blessings? + int LossPercent = (this->GetActivePromotion() ? 7 : 10); + for(int QuestNr = 101; QuestNr <= 105; QuestNr += 1){ + if(this->GetQuestValue(QuestNr) != 0){ + this->SetQuestValue(QuestNr, 0); + LossPercent -= 1; + } + } + + this->Skills[SKILL_LEVEL ]->DecreasePercent(LossPercent); + this->Skills[SKILL_MAGIC_LEVEL]->DecreasePercent(LossPercent); + this->Skills[SKILL_SHIELDING ]->DecreasePercent(LossPercent); + this->Skills[SKILL_DISTANCE ]->DecreasePercent(LossPercent); + this->Skills[SKILL_SWORD ]->DecreasePercent(LossPercent); + this->Skills[SKILL_CLUB ]->DecreasePercent(LossPercent); + this->Skills[SKILL_AXE ]->DecreasePercent(LossPercent); + this->Skills[SKILL_FIST ]->DecreasePercent(LossPercent); + this->Skills[SKILL_FISHING ]->DecreasePercent(LossPercent); +} + +bool TPlayer::MovePossible(int x, int y, int z, bool Execute, bool Jump){ + bool Result = TCreature::MovePossible(x, y, z, Execute, Jump); + if(Result && Execute){ + if(this->EarliestProtectionZoneRound > RoundNr + && IsProtectionZone(x, y, z) + && !IsProtectionZone(this->posx, this->posy, this->posz)){ + throw ENTERPROTECTIONZONE; + } + + uint16 HouseID = GetHouseID(x, y, z); + if(HouseID != 0 + && !IsInvited(HouseID, this, INT_MAX) + && !CheckRight(this->ID, ENTER_HOUSES)){ + throw NOTINVITED; + } + } + return Result; +} + +void TPlayer::DamageStimulus(uint32 AttackerID, int Damage, int DamageType){ + if(!this->IsDead){ + this->BlockLogout(60, false); + } +} + +void TPlayer::IdleStimulus(void){ + if(this->Combat.AttackDest != 0){ + try{ + this->ToDoAttack(); + this->ToDoStart(); + }catch(RESULT r){ + this->ToDoClear(); + if(r != NOERROR){ + if(r != NOWAY){ + SendResult(this->Connection, r); + } + + this->ToDoWait(1000); + this->ToDoStart(); + } + } + } +} + +void TPlayer::AttackStimulus(uint32 AttackerID){ + if(!this->IsDead){ + this->BlockLogout(60, false); + } } void TPlayer::SetInList(void){ @@ -368,14 +448,666 @@ void TPlayer::DelInList(void){ } } +void TPlayer::ClearRequest(void){ + if(this->Request != 0){ + if(this->RequestProcessingGamemaster != 0){ + TCreature *Gamemaster = GetPlayer(this->RequestProcessingGamemaster); + if(Gamemaster != NULL){ + SendFinishRequest(Gamemaster->Connection, this->Name); + } + }else{ + DeleteGamemasterRequest(this->Name); + } + + this->Request = 0; + this->RequestTimestamp = 0; + this->RequestProcessingGamemaster = 0; + } +} + +void TPlayer::ClearConnection(void){ + this->Connection = NULL; + this->ClearRequest(); +} + +void TPlayer::LoadData(void){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::LoadData: PlayerData ist NULL.\n"); + return; + } + + this->Race = PlayerData->Race; + this->OrgOutfit = PlayerData->OriginalOutfit; + this->Outfit = PlayerData->CurrentOutfit; + + GetStartPosition(&this->startx, &this->starty, &this->startz, true); + this->posx = this->startx; + this->posy = this->starty; + this->posz = this->startz; + this->Direction = DIRECTION_SOUTH; + + if(PlayerData->startx != 0){ + this->startx = PlayerData->startx; + this->starty = PlayerData->starty; + this->startz = PlayerData->startz; + } + + if(PlayerData->posx != 0){ + this->posx = PlayerData->posx; + this->posy = PlayerData->posy; + this->posz = PlayerData->posz; + } + + this->Profession = PlayerData->Profession; + this->EarliestYellRound = PlayerData->EarliestYellRound; + this->EarliestTradeChannelRound = PlayerData->EarliestTradeChannelRound; + this->EarliestSpellTime = PlayerData->EarliestSpellTime; + this->EarliestMultiuseTime = PlayerData->EarliestMultiuseTime; + this->TalkBufferFullTime = PlayerData->TalkBufferFullTime; + this->MutingEndRound = PlayerData->MutingEndRound; + this->NumberOfMutings = PlayerData->NumberOfMutings; + + + STATIC_ASSERT(NARRAY(this->SpellList) == NARRAY(PlayerData->SpellList)); + for(int SpellNr = 0; + SpellNr < NARRAY(this->SpellList); + SpellNr += 1){ + this->SpellList[SpellNr] = PlayerData->SpellList[SpellNr]; + } + + STATIC_ASSERT(NARRAY(this->QuestValues) == NARRAY(PlayerData->QuestValues)); + for(int QuestNr = 0; + QuestNr < NARRAY(this->QuestValues); + QuestNr += 1){ + this->QuestValues[QuestNr] = PlayerData->QuestValues[QuestNr]; + } + + // NOTE(fusion): `Minimum` is set to `INT_MIN` to skip loading a skill, and + // stick with the race's default. + this->SetSkills(PlayerData->Race); + STATIC_ASSERT(NARRAY(this->Skills) == NARRAY(PlayerData->Actual)); + for(int SkillNr = 0; + SkillNr < NARRAY(this->Skills); + SkillNr += 1){ + if(PlayerData->Minimum[SkillNr] == INT_MIN){ + continue; + } + + this->Skills[SkillNr]->Load( + PlayerData->Actual[SkillNr], + PlayerData->Maximum[SkillNr], + PlayerData->Minimum[SkillNr], + PlayerData->DeltaAct[SkillNr], + PlayerData->MagicDeltaAct[SkillNr], + PlayerData->Cycle[SkillNr], + PlayerData->MaxCycle[SkillNr], + PlayerData->Count[SkillNr], + PlayerData->MaxCount[SkillNr], + PlayerData->AddLevel[SkillNr], + PlayerData->Experience[SkillNr], + PlayerData->FactorPercent[SkillNr], + PlayerData->NextLevel[SkillNr], + PlayerData->Delta[SkillNr]); + } +} + +void TPlayer::SaveData(void){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::SaveData: PlayerData ist NULL.\n"); + return; + } + + PlayerData->OriginalOutfit = this->OrgOutfit; + PlayerData->CurrentOutfit = this->Outfit; + + PlayerData->startx = this->startx; + PlayerData->starty = this->starty; + PlayerData->startz = this->startz; + PlayerData->posx = this->posx; + PlayerData->posy = this->posy; + PlayerData->posz = this->posz; + + PlayerData->Profession = this->Profession; + PlayerData->EarliestYellRound = this->EarliestYellRound; + PlayerData->EarliestTradeChannelRound = this->EarliestTradeChannelRound; + PlayerData->EarliestSpellTime = this->EarliestSpellTime; + PlayerData->EarliestMultiuseTime = this->EarliestMultiuseTime; + PlayerData->TalkBufferFullTime = this->TalkBufferFullTime; + PlayerData->MutingEndRound = this->MutingEndRound; + PlayerData->NumberOfMutings = this->NumberOfMutings; + + STATIC_ASSERT(NARRAY(this->SpellList) == NARRAY(PlayerData->SpellList)); + for(int SpellNr = 0; + SpellNr < NARRAY(this->SpellList); + SpellNr += 1){ + PlayerData->SpellList[SpellNr] = this->SpellList[SpellNr]; + } + + STATIC_ASSERT(NARRAY(this->QuestValues) == NARRAY(PlayerData->QuestValues)); + for(int QuestNr = 0; + QuestNr < NARRAY(this->QuestValues); + QuestNr += 1){ + PlayerData->QuestValues[QuestNr] = this->QuestValues[QuestNr]; + } + + STATIC_ASSERT(NARRAY(this->Skills) == NARRAY(PlayerData->Actual)); + for(int SkillNr = 0; + SkillNr < NARRAY(this->Skills); + SkillNr += 1){ + // TODO(fusion): Is this even possible? I've seen a few checks here and + // here but it seems all skills are created in TCreature's constructor. + if(this->Skills[SkillNr] == NULL){ + PlayerData->Minimum[SkillNr] = INT_MIN; + continue; + } + + this->Skills[SkillNr]->Save( + &PlayerData->Actual[SkillNr], + &PlayerData->Maximum[SkillNr], + &PlayerData->Minimum[SkillNr], + &PlayerData->DeltaAct[SkillNr], + &PlayerData->MagicDeltaAct[SkillNr], + &PlayerData->Cycle[SkillNr], + &PlayerData->MaxCycle[SkillNr], + &PlayerData->Count[SkillNr], + &PlayerData->MaxCount[SkillNr], + &PlayerData->AddLevel[SkillNr], + &PlayerData->Experience[SkillNr], + &PlayerData->FactorPercent[SkillNr], + &PlayerData->NextLevel[SkillNr], + &PlayerData->Delta[SkillNr]); + } +} + +void TPlayer::LoadInventory(bool SetStandardInventory){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::LoadInventory: PlayerData ist NULL.\n"); + return; + } + + if(PlayerData->Inventory != NULL){ + try{ + TReadBuffer ReadBuffer(PlayerData->Inventory, PlayerData->InventorySize); + while(true){ + int Position = (int)ReadBuffer.readByte(); + if(Position == 0xFF){ + break; + } + + LoadObjects(&ReadBuffer, GetBodyContainer(this->ID, Position)); + Object BodyObj = GetBodyObject(this->ID, Position); + if(BodyObj != NONE){ + SendSetInventory(this->Connection, Position, BodyObj); + } + } + }catch(const char *str){ + error("TPlayer::LoadInventory: Kann Inventory von Spieler %s nicht lesen.\n", this->Name); + error("# Fehler: %s\n", str); + } + }else if(SetStandardInventory + && this->Profession == PROFESSION_NONE + && !CheckRight(this->ID, ZERO_CAPACITY)){ + try{ + Create(GetBodyContainer(this->ID, INVENTORY_RIGHTHAND), + GetSpecialObject(DEFAULT_RIGHTHAND), 0); + Create(GetBodyContainer(this->ID, INVENTORY_LEFTHAND), + GetSpecialObject(DEFAULT_LEFTHAND), 0); + if(this->Sex == 1){ + Create(GetBodyContainer(this->ID, INVENTORY_LEFTHAND), + GetSpecialObject(DEFAULT_BODY_MALE), 0); + }else{ + Create(GetBodyContainer(this->ID, INVENTORY_LEFTHAND), + GetSpecialObject(DEFAULT_BODY_FEMALE), 0); + } + + Object Bag = Create(GetBodyContainer(this->ID, INVENTORY_BAG), + GetSpecialObject(DEFAULT_CONTAINER), 0); + Create(Bag, GetSpecialObject(DEFAULT_FOOD), 1); + }catch(RESULT r){ + error("TPlayer::LoadInventory: Exception %d beim Erstellen des Standard-Inventorys.\n", r); + } + } +} + +void TPlayer::SaveInventory(void){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::SaveInventory: PlayerData ist NULL.\n"); + return; + } + + // TODO(fusion): Set `PlayerData->Dirty`? + delete[] PlayerData->Inventory; + PlayerData->Inventory = NULL; + PlayerData->InventorySize = 0; + if(this->CrObject == NONE){ + return; + } + + try{ + TDynamicWriteBuffer HelpBuffer(KB(16)); + for(int Position = INVENTORY_FIRST; + Position <= INVENTORY_LAST; + Position += 1){ + Object Obj = GetBodyObject(this->ID, Position); + if(Obj.exists()){ + HelpBuffer.writeByte((uint8)Position); + SaveObjects(Obj, &HelpBuffer, false); + } + } + + if(HelpBuffer.Position > 0){ + HelpBuffer.writeByte(0xFF); + + int InventorySize = HelpBuffer.Position; + PlayerData->Inventory = new uint8[InventorySize]; + PlayerData->InventorySize = InventorySize; + memcpy(PlayerData->Inventory, HelpBuffer.Data, InventorySize); + } + }catch(const char *str){ + error("TPlayer::SaveInventory: Kann Inventory von Spieler %s nicht schreiben.\n", this->Name); + error("# Fehler: %s\n", str); + } +} + +void TPlayer::StartCoordinates(void){ + GetStartPosition(&this->startx, &this->starty, &this->startz, true); +} + +void TPlayer::TakeOver(TConnection *Connection){ + Log("game", "Spieler %s übernimmt Verbindung.\n", this->Name); + + this->LoggingOut = false; + this->LogoutAllowed = false; + this->Connection = Connection; + Connection->EnterGame(); + + TPlayerData *PlayerData = GetPlayerPoolSlot(this->ID); + if(PlayerData == NULL){ + error("TPlayer::TakeOver: PlayerData-Slot nicht gefunden.\n"); + return; + } + + if(PlayerData->Locked != getpid()){ + error("TPlayer::TakeOver: PlayerData-Slot ist nicht korrekt gesperrt (%d).\n", PlayerData->Locked); + } + + if(PlayerData->Sticky > 1){ + DecreasePlayerPoolSlotSticky(PlayerData); + }else{ + error("TPlayer::TakeOver: Falscher Sticky-Wert %d.\n", PlayerData->Sticky); + } + + strcpy(this->Name, PlayerData->Name); + InsertPlayerIndex(&PlayerIndexHead, 0, this->Name, this->ID); + strcpy(this->IPAddress, Connection->GetIPAddress()); + memcpy(this->Rights, PlayerData->Rights, sizeof(this->Rights)); + this->Sex = PlayerData->Sex; + strcpy(this->Guild, PlayerData->Guild); + strcpy(this->Rank, PlayerData->Rank); + strcpy(this->Title, PlayerData->Title); + this->OldState = 0; + + this->CheckOutfit(); + this->ClearRequest(); + this->Combat.StopAttack(0); + LeaveAllChannels(this->ID); + this->CloseAllContainers(); + this->RejectTrade(); + + if(CheckRight(this->ID, READ_GAMEMASTER_CHANNEL)){ + CloseProcessedRequests(this->ID); + } + + SendInitGame(Connection, this->ID); + SendRights(Connection); + SendFullScreen(Connection); + SendBodyInventory(Connection, this->ID); + SendAmbiente(Connection); + SendPlayerData(Connection); + SendPlayerSkills(Connection); + this->CheckState(); + this->SendBuddies(); +} + +void TPlayer::SetOpenContainer(int ContainerNr, Object Con){ + if(ContainerNr < 0 || ContainerNr >= NARRAY(this->OpenContainer)){ + error("TPlayer::SetOpenContainer: Ungültige Fensternummer %d.\n", ContainerNr); + return; + } + + if(Con != NONE && (!Con.exists() || !Con.getObjectType().getFlag(CONTAINER))){ + error("TPlayer::SetOpenContainer: Container existiert nicht.\n"); + return; + } + + this->OpenContainer[ContainerNr] = Con; +} + +Object TPlayer::GetOpenContainer(int ContainerNr){ + if(ContainerNr < 0 || ContainerNr >= NARRAY(this->OpenContainer)){ + error("TPlayer::GetOpenContainer: Ungültige Fensternummer %d.\n", ContainerNr); + return NONE; + } + + return this->OpenContainer[ContainerNr]; +} + +void TPlayer::CloseAllContainers(void){ + for(int ContainerNr = 0; + ContainerNr < NARRAY(this->OpenContainer); + ContainerNr += 1){ + Object Con = this->GetOpenContainer(ContainerNr); + if(Con != NONE){ + this->SetOpenContainer(ContainerNr, NONE); + SendCloseContainer(this->Connection, ContainerNr); + } + } +} + +Object TPlayer::InspectTrade(bool OwnOffer, int Position){ + Object Obj = this->TradeObject; + if(Obj == NONE){ + return NONE; + } + + if(!OwnOffer){ + if(this->TradePartner == 0){ + return NONE; + } + + TPlayer *Partner = GetPlayer(this->TradePartner); + if(Partner == NULL + || Partner->TradeObject == NONE + || Partner->TradePartner != this->ID){ + return NONE; + } + + Obj = Partner->TradeObject; + } + + while(Obj != NONE && Position > 0){ + int ObjCount = CountObjects(Obj); + if(Position < ObjCount){ + Obj = GetFirstContainerObject(Obj); + Position -= 1; + }else{ + Obj = Obj.getNextObject(); + Position -= ObjCount; + } + } + + return Obj; +} + +void TPlayer::AcceptTrade(void){ + if(this->TradeObject == NONE){ + return; + } + + TPlayer *Partner = GetPlayer(this->TradePartner); + if(Partner == NULL + || Partner->TradeObject == NONE + || Partner->TradePartner != this->ID){ + return; + } + + this->TradeAccepted = true; + if(!Partner->TradeAccepted){ + return; + } + + TPlayer *Player[2] = { this, Partner }; + Object Dest[2] = { NONE, NONE }; + Object Obj[2] = { this->TradeObject, Partner->TradeObject }; + ObjectType ObjType[2] = { Obj[0].getObjectType(), Obj[1].getObjectType() }; + for(int i = 0; i < 2; i += 1){ + int Cur = i; + int Other = 1 - i; + + try{ + if(!ObjectAccessible(Player[Cur]->ID, Obj[Cur], 1)){ + throw NOTACCESSIBLE; + } + + if(ObjType[Cur].getFlag(UNMOVE)){ + throw NOTMOVABLE; + } + + if(!ObjType[Cur].getFlag(TAKE)){ + throw NOTTAKABLE; + } + + if(CheckRight(Player[Other]->ID, ZERO_CAPACITY)){ + throw TOOHEAVY; + } + + if(!CheckRight(Player[Other]->ID, UNLIMITED_CAPACITY)){ + TSkill *CarryStrength = Player[Other]->Skills[SKILL_CARRY_STRENGTH]; + if(CarryStrength == NULL){ + error("TPlayer::AcceptTrade: Skill CARRYSTRENGTH existiert nicht.\n"); + throw ERROR; + } + + // NOTE(fusion): Check if the other player has enough carry strength, + // considering the object that will be added and the object that may + // be removed. + int MaxWeight = CarryStrength->Get() * 100; + int FinalWeight = GetInventoryWeight(Player[Other]->ID) + + GetCompleteWeight(Obj[Cur]); + if(GetObjectCreatureID(Obj[Other]) == Player[Other]->ID){ + FinalWeight -= GetCompleteWeight(Obj[Other]); + } + + if(FinalWeight > MaxWeight){ + throw TOOHEAVY; + } + } + + // NOTE(fusion): We're looking for the object's destination on the + // other player's inventory. It is similar to `CreateAtCreature` but + // not quite. This should probably be its own function. + bool CheckContainers = ObjType[Cur].getFlag(MOVEMENTEVENT); + for(int j = 0; j < 2; j += 1){ + for(int Position = INVENTORY_FIRST; + Position <= INVENTORY_LAST; + Position += 1){ + // TODO(fusion): It was only a matter of time until one of these showed up. + try{ + Object BodyObj = GetBodyObject(Player[Other]->ID, Position); + if(CheckContainers){ + if(BodyObj != NONE && BodyObj != Obj[Other] + && BodyObj.getObjectType().getFlag(CONTAINER)){ + // NOTE(fusion): Check if the container has enough capacity, + // considering the object that will be added and the object + // that may be removed. + int MaxCount = BodyObj.getObjectType().getAttribute(CAPACITY); + int FinalCount = CountObjectsInContainer(BodyObj) + 1; + if(Obj[Other].getContainer() == BodyObj){ + FinalCount -= 1; + } + + if(FinalCount > MaxCount){ + throw CONTAINERFULL; + } + + Dest[Other] = BodyObj; + break; + } + }else{ + if(BodyObj == NONE){ + Object BodyCon = GetBodyContainer(Player[Other]->ID, Position); + CheckInventoryPlace(ObjType[Cur], BodyCon, Obj[Other]); + Dest[Other] = BodyCon; + break; + } + } + }catch(RESULT r){ + // no-op + } + } + + if(Dest[Other] != NONE){ + break; + } + + CheckContainers = !CheckContainers; + } + + if(Dest[Other] == NONE){ + throw NOROOM; + } + }catch(RESULT r){ + if(r == TOOHEAVY || r == NOROOM){ + SendResult(Player[Other]->Connection, r); + }else{ + SendResult(Player[Cur]->Connection, r); + } + + Player[Cur]->TradeObject = NONE; + Player[Other]->TradeObject = NONE; + SendCloseTrade(Player[Cur]->Connection); + SendCloseTrade(Player[Other]->Connection); + return; + } + } + + this->TradeObject = NONE; + Partner->TradeObject = NONE; + SendCloseTrade(this->Connection); + SendCloseTrade(Partner->Connection); + + // TODO(fusion): I feel this could be problematic. + ::Move(0, Obj[0], GetMapContainer(Player[1]->CrObject), -1, true, NONE); + ::Move(0, Obj[1], GetMapContainer(Player[0]->CrObject), -1, true, NONE); + ::Move(0, Obj[0], Dest[1], -1, true, NONE); + ::Move(0, Obj[1], Dest[0], -1, true, NONE); +} + +void TPlayer::RejectTrade(void){ + if(this->TradeObject != NONE){ + this->TradeObject = NONE; + TPlayer *Partner = GetPlayer(this->TradePartner); + if(Partner != NULL + && Partner->TradeObject != NONE + && Partner->TradePartner == this->ID){ + Partner->TradeObject = NONE; + SendCloseTrade(Partner->Connection); + SendMessage(Partner->Connection, TALK_FAILURE_MESSAGE, "Trade cancelled."); + } + } +} + +void TPlayer::ClearProfession(void){ + if(this->Profession != PROFESSION_NONE){ + this->Profession = PROFESSION_NONE; + this->Combat.CheckCombatValues(); + IncrementNewbiesOnline(); + } +} + +void TPlayer::SetProfession(uint8 Profession){ + if(Profession == PROFESSION_PROMOTED){ + if(this->Profession == PROFESSION_NONE){ + error("TPlayer::SetProfession: Spieler hat noch keinen Beruf für Veredelung.\n"); + return; + } + + if(this->Profession >= PROFESSION_PROMOTED){ + error("TPlayer::SetProfession: Spieler hat seinen Beruf schon veredelt.\n"); + return; + } + + this->Profession += PROFESSION_PROMOTED; + this->Combat.CheckCombatValues(); + + // TODO(fusion): This is similar to the TPlayer's constructor. It is + // problably some `CheckSoul` inlined function? + { + TSkill *Soul = this->Skills[SKILL_SOUL]; + Soul->Max = 200; + + int Timer = Soul->TimerValue(); + if(Timer >= 15){ + int Cycle = (Timer + 14) / 15; + int Count = (Timer + 14) % 15; + this->SetTimer(SKILL_SOUL, Cycle, Count, 15, -1); + } + } + + return; + } + + if(this->Profession != PROFESSION_NONE){ + error("TPlayer::SetProfession: Player '%s' hat bereits einen Beruf!\n", this->Name); + return; + } + + if(Profession == PROFESSION_KNIGHT){ + this->Skills[SKILL_HITPOINTS ]->AddLevel = 15; + this->Skills[SKILL_MANA ]->AddLevel = 5; + this->Skills[SKILL_CARRY_STRENGTH]->AddLevel = 25; + this->Skills[SKILL_MAGIC_LEVEL ]->ChangeSkill(3000, 1600); + this->Skills[SKILL_SHIELDING ]->ChangeSkill(1100, 100); + this->Skills[SKILL_DISTANCE ]->ChangeSkill(1400, 30); + this->Skills[SKILL_SWORD ]->ChangeSkill(1100, 50); + this->Skills[SKILL_CLUB ]->ChangeSkill(1100, 50); + this->Skills[SKILL_AXE ]->ChangeSkill(1100, 50); + this->Skills[SKILL_FIST ]->ChangeSkill(1100, 50); + }else if(Profession == PROFESSION_PALADIN){ + this->Skills[SKILL_HITPOINTS ]->AddLevel = 10; + this->Skills[SKILL_MANA ]->AddLevel = 15; + this->Skills[SKILL_CARRY_STRENGTH]->AddLevel = 20; + this->Skills[SKILL_MAGIC_LEVEL ]->ChangeSkill(1400, 1600); + this->Skills[SKILL_SHIELDING ]->ChangeSkill(1100, 100); + this->Skills[SKILL_DISTANCE ]->ChangeSkill(1100, 30); + this->Skills[SKILL_SWORD ]->ChangeSkill(1200, 50); + this->Skills[SKILL_CLUB ]->ChangeSkill(1200, 50); + this->Skills[SKILL_AXE ]->ChangeSkill(1200, 50); + this->Skills[SKILL_FIST ]->ChangeSkill(1200, 50); + }else if(Profession == PROFESSION_SORCERER){ + this->Skills[SKILL_HITPOINTS ]->AddLevel = 5; + this->Skills[SKILL_MANA ]->AddLevel = 30; + this->Skills[SKILL_CARRY_STRENGTH]->AddLevel = 10; + this->Skills[SKILL_MAGIC_LEVEL ]->ChangeSkill(1100, 1600); + this->Skills[SKILL_SHIELDING ]->ChangeSkill(1500, 100); + this->Skills[SKILL_DISTANCE ]->ChangeSkill(2000, 30); + this->Skills[SKILL_SWORD ]->ChangeSkill(2000, 50); + this->Skills[SKILL_CLUB ]->ChangeSkill(2000, 50); + this->Skills[SKILL_AXE ]->ChangeSkill(2000, 50); + this->Skills[SKILL_FIST ]->ChangeSkill(1500, 50); + }else if(Profession == PROFESSION_DRUID){ + this->Skills[SKILL_HITPOINTS ]->AddLevel = 5; + this->Skills[SKILL_MANA ]->AddLevel = 30; + this->Skills[SKILL_CARRY_STRENGTH]->AddLevel = 10; + this->Skills[SKILL_MAGIC_LEVEL ]->ChangeSkill(1100, 1600); + this->Skills[SKILL_SHIELDING ]->ChangeSkill(1500, 100); + this->Skills[SKILL_DISTANCE ]->ChangeSkill(1800, 30); + this->Skills[SKILL_SWORD ]->ChangeSkill(1800, 50); + this->Skills[SKILL_CLUB ]->ChangeSkill(1800, 50); + this->Skills[SKILL_AXE ]->ChangeSkill(1800, 50); + this->Skills[SKILL_FIST ]->ChangeSkill(1500, 50); + }else{ + error("TPlayer::SetProfession: Beruf %d existiert nicht!\n", Profession); + return; + } + + this->Profession = Profession; + this->Combat.CheckCombatValues(); + DecrementNewbiesOnline(); +} + uint8 TPlayer::GetRealProfession(void){ return this->Profession; } uint8 TPlayer::GetEffectiveProfession(void){ uint8 Profession = this->Profession; - if(Profession >= 10){ - Profession -= 10; + if(Profession >= PROFESSION_PROMOTED){ + Profession -= PROFESSION_PROMOTED; } return Profession; } @@ -383,7 +1115,7 @@ uint8 TPlayer::GetEffectiveProfession(void){ uint8 TPlayer::GetActiveProfession(void){ uint8 Profession; if(CheckRight(this->ID, PREMIUM_ACCOUNT)){ - Profession = this->Profession; + Profession = this->GetRealProfession(); }else{ Profession = this->GetEffectiveProfession(); } @@ -392,7 +1124,88 @@ uint8 TPlayer::GetActiveProfession(void){ bool TPlayer::GetActivePromotion(void){ return CheckRight(this->ID, PREMIUM_ACCOUNT) - && this->Profession >= 10; + && this->Profession >= PROFESSION_PROMOTED; +} + +bool TPlayer::SpellKnown(int SpellNr){ + if(SpellNr < 0 || SpellNr >= NARRAY(this->SpellList)){ + error("TPlayer::SpellKnown: Ungültige Spruchnummer %d.\n", SpellNr); + return false; + } + + return this->SpellList[SpellNr] != 0; +} + +void TPlayer::LearnSpell(int SpellNr){ + if(SpellNr < 0 || SpellNr >= NARRAY(this->SpellList)){ + error("TPlayer::LearnSpell: Ungültige Spruchnummer %d.\n", SpellNr); + return; + } + + if(this->SpellList[SpellNr] != 0){ + error("TPlayer::LearnSpell: Der Spieler kennt den Spruch schon.\n"); + return; + } + + this->SpellList[SpellNr] = 1; +} + +int TPlayer::GetQuestValue(int QuestNr){ + if(QuestNr < 0 || QuestNr >= NARRAY(this->QuestValues)){ + error("TPlayer::GetQuestValue: Ungültige Nummer %d.\n", QuestNr); + return 0; + } + + print(3, "Wert der Questvariablen %d von %s: %d.\n", + QuestNr, this->Name, this->QuestValues[QuestNr]); + return this->QuestValues[QuestNr]; +} + +void TPlayer::SetQuestValue(int QuestNr, int Value){ + if(QuestNr < 0 || QuestNr >= NARRAY(this->QuestValues)){ + error("TPlayer::SetQuestValue: Ungültige Nummer %d.\n", QuestNr); + return; + } + + print(3, "Neuer Wert für Questvariable %d von %s: %d.\n", + QuestNr, this->Name, Value); + this->QuestValues[QuestNr] = Value; +} + +void TPlayer::CheckOutfit(void){ + if(CheckRight(this->ID, GAMEMASTER_OUTFIT)){ + if(this->OrgOutfit.OutfitID == 75){ + return; + } + + this->OrgOutfit.OutfitID = 75; + this->OrgOutfit.Colors[0] = 0; + this->OrgOutfit.Colors[1] = 0; + this->OrgOutfit.Colors[2] = 0; + this->OrgOutfit.Colors[3] = 0; + }else if(this->Sex == 1){ + if(this->OrgOutfit.OutfitID >= 128 && this->OrgOutfit.OutfitID <= 134){ + return; + } + + this->OrgOutfit.OutfitID = 128; + this->OrgOutfit.Colors[0] = 78; + this->OrgOutfit.Colors[1] = 69; + this->OrgOutfit.Colors[2] = 58; + this->OrgOutfit.Colors[3] = 76; + }else{ + if(this->OrgOutfit.OutfitID >= 136 && this->OrgOutfit.OutfitID <= 142){ + return; + } + + this->OrgOutfit.OutfitID = 136; + this->OrgOutfit.Colors[0] = 78; + this->OrgOutfit.Colors[1] = 69; + this->OrgOutfit.Colors[2] = 58; + this->OrgOutfit.Colors[3] = 76; + } + + this->Outfit = this->OrgOutfit; } void TPlayer::CheckState(void){ @@ -440,6 +1253,510 @@ void TPlayer::CheckState(void){ } } +void TPlayer::AddBuddy(const char *Name){ + if(Name == NULL){ + error("TPlayer::AddBuddy: Name ist NULL.\n"); + return; + } + + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::AddBuddy: PlayerData ist NULL.\n"); + return; + } + + if(PlayerData->Buddies >= 100){ + SendMessage(this->Connection, TALK_FAILURE_MESSAGE, + "You cannot add more buddies."); + return; + } + + if(PlayerData->Buddies >= 20 + && !CheckRight(this->ID, PREMIUM_ACCOUNT) + && !CheckRight(this->ID, READ_GAMEMASTER_CHANNEL)){ + SendMessage(this->Connection, TALK_FAILURE_MESSAGE, + "You cannot add more buddies."); + return; + } + + TPlayer *Buddy = NULL; + uint32 BuddyID = 0; + char BuddyName[30] = {}; + bool Online = false; + if(IdentifyPlayer(Name, true, true, &Buddy) == 0){ + BuddyID = Buddy->ID; + strcpy(BuddyName, Buddy->Name); + Online = true; + }else{ + BuddyID = GetCharacterID(Name); + if(BuddyID == 0){ + SendResult(this->Connection, PLAYERNOTEXISTING); + return; + } + strcpy(BuddyName, GetCharacterName(Name)); + Online = false; + } + + for(int i = 0; i < PlayerData->Buddies; i += 1){ + if(PlayerData->Buddy[i] == BuddyID){ + SendMessage(this->Connection, TALK_FAILURE_MESSAGE, + "This player is already in your list."); + return; + } + } + + PlayerData->Buddy[PlayerData->Buddies] = BuddyID; + strcpy(PlayerData->BuddyName[PlayerData->Buddies], BuddyName); + PlayerData->Buddies += 1; + + Online = Online && (!CheckRight(BuddyID, NO_STATISTICS) + || CheckRight(this->ID, READ_GAMEMASTER_CHANNEL)); + SendBuddyData(this->Connection, BuddyID, BuddyName, Online); + AddBuddyOrder(this, BuddyID); +} + +void TPlayer::RemoveBuddy(uint32 CharacterID){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::RemoveBuddy: PlayerData ist NULL.\n"); + return; + } + + int BuddyIndex = 0; + while(BuddyIndex < PlayerData->Buddies){ + if(PlayerData->Buddy[BuddyIndex] == CharacterID){ + break; + } + BuddyIndex += 1; + } + + if(BuddyIndex < PlayerData->Buddies){ + // NOTE(fusion): A little swap and pop action. + PlayerData->Buddies -= 1; + PlayerData->Buddy[BuddyIndex] = PlayerData->Buddy[PlayerData->Buddies]; + strcpy(PlayerData->BuddyName[BuddyIndex], PlayerData->BuddyName[PlayerData->Buddies]); + RemoveBuddyOrder(this, CharacterID); + } +} + +void TPlayer::SendBuddies(void){ + TPlayerData *PlayerData = this->PlayerData; + if(PlayerData == NULL){ + error("TPlayer::SendBuddies: PlayerData ist NULL.\n"); + return; + } + + bool ReadGamemasterChannel = CheckRight(this->ID, READ_GAMEMASTER_CHANNEL); + for(int i = 0; i < PlayerData->Buddies; i += 1){ + bool Online = false; + uint32 BuddyID = PlayerData->Buddy[i]; + const char *BuddyName = PlayerData->BuddyName[i]; + TPlayer *Buddy = GetPlayer(BuddyID); + if(Buddy != NULL){ + Online = ReadGamemasterChannel || !CheckRight(BuddyID, NO_STATISTICS); + BuddyName = Buddy->Name; + } + SendBuddyData(this->Connection, BuddyID, BuddyName, Online); + } +} + +void TPlayer::Regenerate(void){ + // TODO(fusion): This is probably some inlined function that searches for an + // object with an specific flag on a field. + Object Bed = GetFirstObject(this->posx, this->posy, this->posz); + while(Bed != NONE){ + if(Bed.getObjectType().getFlag(BED)){ + break; + } + Bed = Bed.getNextObject(); + } + + if(Bed == NONE){ + error("TPlayer::Regenerate: Bett nicht gefunden.\n"); + return; + } + + if(!Bed.getObjectType().getFlag(TEXT)){ + error("TPlayer::Regenerate: Bett trägt keinen Text.\n"); + return; + } + + uint32 Text = Bed.getAttribute(TEXTSTRING); + if(Text == 0 || stricmp(GetDynamicString(Text), this->Name) != 0){ + return; + } + + int OfflineTime = 0; + if(this->PlayerData != NULL && this->PlayerData->LastLogoutTime != 0){ + OfflineTime = (int)(time(NULL) - this->PlayerData->LastLogoutTime); + } + + int FoodTime = this->Skills[SKILL_FED]->TimerValue(); + int Regen = std::min<int>(FoodTime / 3, OfflineTime / 15); + if(Regen > 0){ + this->Skills[SKILL_HITPOINTS]->Change(Regen / 4); + this->Skills[SKILL_MANA ]->Change(Regen); + this->SetTimer(SKILL_FED, (FoodTime - Regen * 3), 0, 0, -1); + } + + if(OfflineTime > 900){ + this->Skills[SKILL_SOUL]->Change(OfflineTime / 900); + } + + try{ + UseObjects(0, Bed, Bed); + }catch(RESULT r){ + error("TPlayer::Regenerate: Exception %d beim Aufräumen des Bettes.\n", r); + } +} + +bool TPlayer::IsAttacker(uint32 VictimID, bool CheckFormer){ + for(int i = 0; i < this->NumberOfAttackedPlayers; i += 1){ + if(*this->AttackedPlayers.at(i) == VictimID){ + return true; + } + } + + if(CheckFormer && (this->FormerLogoutRound + 5) >= RoundNr){ + for(int i = 0; i < this->NumberOfFormerAttackedPlayers; i += 1){ + if(*this->FormerAttackedPlayers.at(i) == VictimID){ + return true; + } + } + } + + return false; +} + +bool TPlayer::IsAggressor(bool CheckFormer){ + return this->Aggressor + || (CheckFormer && this->FormerAggressor + && (this->FormerLogoutRound + 5) >= RoundNr); +} + +bool TPlayer::IsAttackJustified(uint32 VictimID){ + TPlayer *Victim = GetPlayer(VictimID); + if(Victim == NULL){ + error("TPlayer::IsAttackJustified: Opfer existiert nicht.\n"); + return true; + } + + if(WorldType != PVP_ENFORCED // TODO(fusion): Probably `WorldType == NORMAL` ? + && Victim->PlayerData != NULL + && Victim->PlayerData->PlayerkillerEnd == 0){ + if(Victim->IsAggressor(true)){ + return true; + } + + if(Victim->GetPartyLeader(true) != 0 + && Victim->GetPartyLeader(true) == this->GetPartyLeader(true)){ + return true; + } + + return Victim->IsAttacker(this->ID, true); + } + + return true; +} + +void TPlayer::RecordAttack(uint32 VictimID){ + if(WorldType != NORMAL || VictimID == this->ID){ + return; + } + + TPlayer *Victim = GetPlayer(VictimID); + if(Victim == NULL){ + error("TPlayer::RecordAttack: Opfer existiert nicht.\n"); + return; + } + + if(!Victim->IsAttacker(this->ID, true) && !this->IsAttacker(VictimID, false) + && (Victim->GetPartyLeader(true) == 0 + || Victim->GetPartyLeader(true) != this->GetPartyLeader(true))){ + *this->AttackedPlayers.at(this->NumberOfAttackedPlayers) = VictimID; + this->NumberOfAttackedPlayers += 1; + print(3, "Spieler %s ist Angreifer für Spieler %s.\n", this->Name, Victim->Name); + if(Victim->Connection != NULL + && Victim->Connection->KnownCreature(this->ID, false) == KNOWNCREATURE_UPTODATE){ + SendCreatureSkull(Victim->Connection, this->ID); + } + } + + if(!this->IsAttackJustified(VictimID) && !this->Aggressor){ + this->Aggressor = true; + print(3, "Spieler %s ist Aggressor.\n", this->Name); + AnnounceChangedCreature(this->ID, CREATURE_SKULL_CHANGED); + } +} + +void TPlayer::RecordMurder(uint32 VictimID){ + if(WorldType != NORMAL || VictimID == this->ID + || this->IsAttackJustified(VictimID)){ + return; + } + + TPlayer *Victim = GetPlayer(VictimID); + if(Victim == NULL){ + error("TPlayer::RecordMurder: Opfer existiert nicht.\n"); + return; + } + + print(3, "Ungerechtfertigter Mord von %s an %s.\n", this->Name, Victim->Name); + + int Now = (int)time(NULL); + + // TODO(fusion): It's just annoying that we check `PlayerData` in some places + // but not others. + ASSERT(this->PlayerData != NULL); + TPlayerData *PlayerData = this->PlayerData; + for(int i = 1; i < NARRAY(PlayerData->MurderTimestamps); i += 1){ + PlayerData->MurderTimestamps[i - 1] = PlayerData->MurderTimestamps[i]; + } + PlayerData->MurderTimestamps[NARRAY(PlayerData->MurderTimestamps) - 1] = Now; + SendMessage(this->Connection, TALK_ADMIN_MESSAGE, + "Warning! The murder of %s was not justified.", Victim->Name); + + int Playerkilling = this->CheckPlayerkilling(Now); + if(Playerkilling != 0){ + int OldPlayerkillerEnd = PlayerData->PlayerkillerEnd; + PlayerData->PlayerkillerEnd = Now + 2592000; // 30 days + if(OldPlayerkillerEnd == 0){ + print(3, "Spieler %s ist Playerkiller.\n", this->Name); + AnnounceChangedCreature(this->ID, CREATURE_SKULL_CHANGED); + } + + if(Playerkilling == 2){ + // TODO(fusion): This might be an inlined function that calls `PunishmentOrder`? + PunishmentOrder(NULL, this->Name, this->IPAddress, 28, 2, + "Exceeding the limit of unjustified kills by 100%.", + 0, NULL, 0, false); + } + } +} + +int TPlayer::CheckPlayerkilling(int Now){ + int LastDay = 0; + int LastWeek = 0; + int LastMonth = 0; + + ASSERT(this->PlayerData != NULL); + TPlayerData *PlayerData = this->PlayerData; + for(int i = 0; i < NARRAY(PlayerData->MurderTimestamps); i += 1){ + int Timestamp = PlayerData->MurderTimestamps[i]; + if(Timestamp == 0){ + continue; + } + + if((Now - Timestamp) < 86000){ + LastDay += 1; + } + + if((Now - Timestamp) < 604800){ + LastWeek += 1; + } + + if((Now - Timestamp) < 2592000){ + LastMonth += 1; + } + } + + if(LastDay >= 6 || LastWeek >= 10 || LastMonth >= 20){ + return 2; // EXCESSIVE_KILLING ? + }else if(LastDay >= 3 || LastWeek >= 5 || LastMonth >= 10){ + return 1; // PLAYERKILLER ? + }else{ + return 0; + } +} + +void TPlayer::ClearAttacker(uint32 VictimID){ + int AttackedIndex = 0; + while(AttackedIndex < this->NumberOfAttackedPlayers){ + if(*this->AttackedPlayers.at(AttackedIndex) == VictimID){ + break; + } + AttackedIndex += 1; + } + + if(AttackedIndex >= this->NumberOfAttackedPlayers){ + return; + } + + // NOTE(fusion): A little swap and pop action. + this->NumberOfAttackedPlayers -= 1; + *this->AttackedPlayers.at(AttackedIndex) = *this->AttackedPlayers.at(this->NumberOfAttackedPlayers); + + TPlayer *Victim = GetPlayer(VictimID); + if(Victim != NULL + && Victim->Connection != NULL + && Victim->Connection->KnownCreature(this->ID, false) == KNOWNCREATURE_UPTODATE){ + SendCreatureSkull(Victim->Connection, this->ID); + } +} + +void TPlayer::ClearPlayerkillingMarks(void){ + print(3, "Lösche Markierungen von Spieler %s.\n", this->Name); + + for(int i = 0; i < this->NumberOfAttackedPlayers; i += 1){ + *this->FormerAttackedPlayers.at(i) = *this->AttackedPlayers.at(i); + } + + this->NumberOfFormerAttackedPlayers = this->NumberOfAttackedPlayers; + this->NumberOfAttackedPlayers = 0; + this->FormerAggressor = this->Aggressor; + this->FormerLogoutRound = RoundNr; + + if(this->Aggressor){ + this->Aggressor = false; + print(3, "Spieler %s ist kein Aggressor mehr.\n", this->Name); + AnnounceChangedCreature(this->ID, CREATURE_SKULL_CHANGED); + }else{ + for(int i = 0; i < this->NumberOfFormerAttackedPlayers; i += 1){ + TPlayer *Victim = GetPlayer(*this->FormerAttackedPlayers.at(i)); + if(Victim != NULL){ + print(3, "Spieler %s ist kein Angreifer mehr für Spieler %s.\n", this->Name, Victim->Name); + if(Victim->Connection != NULL + && Victim->Connection->KnownCreature(this->ID, false) == KNOWNCREATURE_UPTODATE){ + SendCreatureSkull(Victim->Connection, this->ID); + } + } + } + } + + for(int i = 0; i < FirstFreePlayer; i += 1){ + TPlayer *Player = *PlayerList.at(i); + if(Player != NULL){ + Player->ClearAttacker(this->ID); + }else{ + error("TPlayer::ClearPlayerkillingMarks: Spieler %d existiert nicht.\n", i); + } + } +} + +int TPlayer::GetPlayerkillingMark(TPlayer *Observer){ + if(WorldType == NORMAL){ + if(Observer == NULL){ + error("TPlayer::GetPlayerkillingMark: Beobachter existiert nicht.\n"); + return SKULL_NONE; + } + + ASSERT(this->PlayerData); + if(this->PlayerData->PlayerkillerEnd != 0){ + return SKULL_RED; + } + + if(this->Aggressor){ + return SKULL_WHITE; + } + + if(this->GetPartyLeader(false) != 0 + && this->GetPartyLeader(false) == Observer->GetPartyLeader(false)){ + return SKULL_GREEN; + } + + if(this->IsAttacker(Observer->ID, false)){ + return SKULL_YELLOW; + } + } + + return SKULL_NONE; +} + +uint32 TPlayer::GetPartyLeader(bool CheckFormer){ + if(this->PartyLeavingRound == 0 || (CheckFormer && (this->PartyLeavingRound + 5) >= RoundNr)){ + return this->PartyLeader; + }else{ + return 0; + } +} + +void TPlayer::JoinParty(uint32 LeaderID){ + this->PartyLeavingRound = 0; + this->PartyLeader = LeaderID; +} + +void TPlayer::LeaveParty(void){ + this->PartyLeavingRound = RoundNr; +} + +int TPlayer::GetPartyMark(TPlayer *Observer){ + if(Observer == NULL){ + error("TPlayer::GetPartyMark: Beobachter existiert nicht.\n"); + return PARTY_SHIELD_NONE; + } + + if(Observer->GetPartyLeader(false) == this->ID){ + return PARTY_SHIELD_LEADER; + } + + if(this->GetPartyLeader(false) != 0 + && this->GetPartyLeader(false) == Observer->GetPartyLeader(false)){ + return PARTY_SHIELD_MEMBER; + } + + if(Observer->GetPartyLeader(false) == Observer->ID + && IsInvitedToParty(this->ID, Observer->ID)){ + return PARTY_SHIELD_GUEST; + } + + if(this->GetPartyLeader(false) == this->ID + && IsInvitedToParty(Observer->ID, this->ID)){ + return PARTY_SHIELD_HOST; + } + + return PARTY_SHIELD_NONE; // PARTY_NONE +} + +int TPlayer::RecordTalk(void){ + int Muting = 0; + if(this->TalkBufferFullTime > ServerMilliseconds){ + if(this->TalkBufferFullTime > (ServerMilliseconds + 7500)){ + this->NumberOfMutings += 1; + Muting = (this->NumberOfMutings * this->NumberOfMutings) * 5; + this->MutingEndRound = RoundNr + (uint32)Muting; + }else{ + this->TalkBufferFullTime += 2500; + } + }else{ + this->TalkBufferFullTime = ServerMilliseconds + 2500; + } + return Muting; +} + +int TPlayer::RecordMessage(uint32 AddresseeID){ + STATIC_ASSERT(NARRAY(this->Addressees) == NARRAY(this->AddresseesTimes)); + int AddresseeNr = -1; + for(int i = 0; i < NARRAY(this->Addressees); i += 1){ + if(this->Addressees[i] == AddresseeID){ + AddresseeNr = i; + break; + } + + if(this->Addressees[i] == 0 || RoundNr > (this->AddresseesTimes[i] + 600)){ + AddresseeNr = i; + } + } + + int Muting = 0; + if(AddresseeNr == -1){ + this->NumberOfMutings += 1; + Muting = (this->NumberOfMutings * this->NumberOfMutings) * 5; + this->MutingEndRound = RoundNr + (uint32)Muting; + }else{ + this->Addressees[AddresseeNr] = AddresseeID; + this->AddresseesTimes[AddresseeNr] = RoundNr; + } + return Muting; +} + +int TPlayer::CheckForMuting(void){ + int Muting = 0; + if(this->MutingEndRound > RoundNr){ + Muting = (int)(this->MutingEndRound - RoundNr); + } + return Muting; +} + // Player Utility // ============================================================================= int GetNumberOfPlayers(void){ @@ -689,18 +2006,20 @@ void SaveDepot(TPlayerData *PlayerData, int DepotNr, Object Con){ } PlayerData->Dirty = true; - if(PlayerData->Depot[DepotNr] != NULL){ - delete PlayerData->Depot[DepotNr]; - PlayerData->Depot[DepotNr] = NULL; - } + delete[] PlayerData->Depot[DepotNr]; + PlayerData->Depot[DepotNr] = NULL; + PlayerData->DepotSize[DepotNr] = 0; try{ TDynamicWriteBuffer HelpBuffer(KB(16)); SaveObjects(GetFirstContainerObject(Con), &HelpBuffer, false); - PlayerData->Depot[DepotNr] = new uint8[HelpBuffer.Size]; - PlayerData->DepotSize[DepotNr] = HelpBuffer.Size; - memcpy(PlayerData->Depot[DepotNr], HelpBuffer.Data, HelpBuffer.Size); + if(HelpBuffer.Position > 0){ + int DepotSize = HelpBuffer.Position; + PlayerData->Depot[DepotNr] = new uint8[DepotSize]; + PlayerData->DepotSize[DepotNr] = DepotSize; + memcpy(PlayerData->Depot[DepotNr], HelpBuffer.Data, DepotSize); + } }catch(const char *str){ error("SaveDepot: Kann Depot nicht schreiben (%s).\n", str); PlayerData->Depot[DepotNr] = NULL; diff --git a/src/crskill.cc b/src/crskill.cc index 235f277..923c0ab 100644 --- a/src/crskill.cc +++ b/src/crskill.cc @@ -29,7 +29,11 @@ int TSkill::Get(void){ int TSkill::GetProgress(void){ int Result = 0; if(this->NextLevel > this->LastLevel){ - Result = (this->Exp - this->LastLevel) * 100 / (this->NextLevel - this->LastLevel); + // NOTE(fusion): Use 64-bit integers to avoid overflows. + int64 Result64 = (int64)(this->Exp - this->LastLevel) * 100 + / (int64)(this->NextLevel - this->LastLevel); + + Result = (int)Result64; // TODO(fusion): This feels too much for reporting a mostly *impossible* error. if(Result < 0 || Result > 100){ @@ -64,6 +68,16 @@ void TSkill::Change(int Amount){ } } +void TSkill::SetMax(void){ + this->Set(this->Max); +} + +void TSkill::DecreasePercent(int Percent){ + // NOTE(fusion): Use 64-bit integers to avoid overflows. + int64 Amount64 = ((int64)this->Exp * (int64)Percent) / 100; + this->Decrease((int)Amount64); +} + void TSkill::SetMDAct(int MDAct){ this->MDAct = MDAct; if(this->SkNr == SKILL_GO_STRENGTH && this->Master && this->Master->Type == PLAYER){ diff --git a/src/enums.hh b/src/enums.hh index 940d19e..7eb2671 100644 --- a/src/enums.hh +++ b/src/enums.hh @@ -283,6 +283,14 @@ enum LiquidType: int { LIQUID_LEMONADE = 12, }; +enum PartyShield: int { + PARTY_SHIELD_NONE = 0, + PARTY_SHIELD_HOST = 1, + PARTY_SHIELD_GUEST = 2, + PARTY_SHIELD_MEMBER = 3, + PARTY_SHIELD_LEADER = 4, +}; + // NOTE(fusion): Not in debug symbols. enum PROFESSION: uint8 { PROFESSION_NONE = 0, @@ -290,6 +298,7 @@ enum PROFESSION: uint8 { PROFESSION_PALADIN = 2, PROFESSION_SORCERER = 3, PROFESSION_DRUID = 4, + PROFESSION_PROMOTED = 10, PROFESSION_ELITE_KNIGHT = 11, PROFESSION_ROYAL_PALADIN = 12, PROFESSION_MASTER_SORCERER = 13, @@ -478,6 +487,14 @@ enum Skill: int { SKILL_SOUL = 22, }; +enum Skull: int { + SKULL_NONE = 0, + SKULL_YELLOW = 1, + SKULL_GREEN = 2, + SKULL_WHITE = 3, + SKULL_RED = 4, +}; + // IMPORTANT(fusion): All `DEFAULT_*` values here were renamed from `INVENTORY_*` // to avoid collisions with `InventorySlot`. I could also have chosen other prefix // for inventory slots but I feel we'd be wasting them here where their meaning diff --git a/src/stubs.hh b/src/stubs.hh index 9c251ef..561fc95 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -7,6 +7,7 @@ #include "cr.hh" #include "magic.hh" #include "map.hh" +#include "operate.hh" // IMPORTANT(fusion): These function definitions exist to test compilation. They're // not yet implemented and will cause the linker to fail with unresolved symbols. @@ -15,6 +16,8 @@ typedef void TRefreshSectorFunction(int SectorX, int SectorY, int SectorZ, const typedef void TSendMailsFunction(TPlayerData *PlayerData); extern void AbortWriter(void); +extern void AddBuddyOrder(TCreature *Creature, uint32 CharacterID); +extern void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID); extern void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3); extern void ChangeNPCState(TCreature *Npc, int NewState, bool Stimulus); extern void CharacterDeathOrder(TCreature *Creature, int OldLevel, @@ -46,6 +49,10 @@ extern void ProcessConnections(void); extern void ProcessMonsterhomes(void); extern void ProcessReaderThreadReplies(TRefreshSectorFunction *RefreshSector, TSendMailsFunction *SendMails); extern void ProcessWriterThreadReplies(void); +extern void PunishmentOrder(TCreature *Creature, const char *Name, const char *IPAddress, + int Reason, int Action, const char *Comment, int NumberOfStatements, + vector<TReportedStatement> *ReportedStatements, uint32 StatementID, + bool IPBanishment); extern void ReceiveData(void); extern void SavePlayerData(TPlayerData *Slot); extern bool LoadPlayerData(TPlayerData *Slot); @@ -53,6 +60,7 @@ extern bool PlayerDataExists(uint32 CharacterID); extern void SavePlayerDataOrder(void); extern void SendAll(void); extern void SendAmbiente(TConnection *Connection); +extern void SendBodyInventory(TConnection *Connection, uint32 CreatureID); extern void SendBuddyData(TConnection *Connection, uint32 CharacterID, const char *Name, bool Online); extern void SendBuddyStatus(TConnection *Connection, uint32 CharacterID, bool Online); extern void SendClearTarget(TConnection *Connection); |
