aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-18 18:57:37 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-18 18:57:37 -0300
commite5b8aadd493b8b5df4ed661f2491de33d634b001 (patch)
tree694e90810ca82d621573f8d26f64481f7001d183
parentb912ba995c2175b00393f95388ae2ec1afd0494b (diff)
downloadgame-e5b8aadd493b8b5df4ed661f2491de33d634b001.tar.gz
game-e5b8aadd493b8b5df4ed661f2491de33d634b001.zip
finish `crplayer.cc`
-rw-r--r--Makefile10
-rw-r--r--TODO.md1
-rw-r--r--reference/game.c2460
-rw-r--r--src/common.hh2
-rw-r--r--src/connection.hh2
-rw-r--r--src/cr.hh72
-rw-r--r--src/crmain.cc4
-rw-r--r--src/crplayer.cc1477
-rw-r--r--src/crskill.cc16
-rw-r--r--src/enums.hh17
-rw-r--r--src/stubs.hh8
11 files changed, 1496 insertions, 2573 deletions
diff --git a/Makefile b/Makefile
index c937038..a10d2e8 100644
--- a/Makefile
+++ b/Makefile
@@ -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 $@ $<
diff --git a/TODO.md b/TODO.md
index ecfef37..eed0a40 100644
--- a/TODO.md
+++ b/TODO.md
@@ -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
// =================
diff --git a/src/cr.hh b/src/cr.hh
index 83ab647..37671b8 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -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);