aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-17 20:10:41 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-17 20:10:41 -0300
commitb912ba995c2175b00393f95388ae2ec1afd0494b (patch)
tree20c9eae485c1a365e83db0bcce45f6c691bd4b54
parent56bdec57609cd00d7827a3008a9c6b06707097ca (diff)
downloadgame-b912ba995c2175b00393f95388ae2ec1afd0494b.tar.gz
game-b912ba995c2175b00393f95388ae2ec1afd0494b.zip
TPlayer constructor and destructor
-rw-r--r--reference/game.c1316
-rw-r--r--src/common.hh2
-rw-r--r--src/connection.hh2
-rw-r--r--src/cr.hh65
-rw-r--r--src/crmain.cc19
-rw-r--r--src/crplayer.cc363
-rw-r--r--src/operate.cc1
-rw-r--r--src/stubs.hh14
-rw-r--r--src/time.cc8
9 files changed, 435 insertions, 1355 deletions
diff --git a/reference/game.c b/reference/game.c
index 2b04018..a3130b1 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -18382,1322 +18382,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-// DWARF original prototype: void TPlayer(TPlayer * this, TConnection * Connection, ulong
-// CharacterID)
-
-void __thiscall TPlayer::TPlayer(TPlayer *this,TConnection *Connection,ulong CharacterID)
-
-{
- char *__dest;
- TSkill **ppTVar1;
- TSkill *pTVar2;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar3;
- bool bVar4;
- byte bVar5;
- ushort HouseID;
- int i;
- Object *pOVar6;
- uint uVar7;
- TPlayerData *pTVar8;
- char *__src;
- time_t tVar9;
- TPlayer **ppTVar10;
- int iVar11;
- TCreature *pTVar12;
- tm *__tp;
- int iVar13;
- ulong id;
- int i_1;
- uchar *puVar14;
- int *piVar15;
- char local_ac [4];
- char TimeString [100];
- Object local_3c [4];
- ulong local_2c;
-
- TCreature::TCreature(&this->super_TCreature);
- pOVar6 = this->OpenContainer;
- (this->Depot).ObjectID = 0;
- (this->TradeObject).ObjectID = 0;
- iVar13 = 0xf;
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)&PTR__TPlayer_08127c68;
- do {
- pOVar6->ObjectID = 0;
- iVar13 = iVar13 + -1;
- pOVar6 = pOVar6 + 1;
- } while (iVar13 != -1);
- // try { // try from 080a9026 to 080a902a has its CatchHandler @ 080a9a43
- vector<>::vector(&this->AttackedPlayers,0,10,10);
- // try { // try from 080a9052 to 080a9056 has its CatchHandler @ 080a9a3f
- vector<>::vector(&this->FormerAttackedPlayers,0,10,10);
- (this->super_TCreature).Profession = '\0';
- this->ConstructError = NOERROR;
- (this->super_TCreature).Type = PLAYER;
- (this->Depot).ObjectID = ::NONE.ObjectID;
- local_3c[0] = ::NONE;
- local_2c = ::NONE.ObjectID;
- (this->TradeObject).ObjectID = ::NONE.ObjectID;
- this->OldState = 0;
- this->OpenContainer[0].ObjectID = 0;
- this->OpenContainer[2].ObjectID = 0;
- this->OpenContainer[4].ObjectID = 0;
- this->OpenContainer[1].ObjectID = 0;
- this->OpenContainer[5].ObjectID = 0;
- this->OpenContainer[7].ObjectID = 0;
- this->OpenContainer[6].ObjectID = 0;
- this->OpenContainer[8].ObjectID = 0;
- this->OpenContainer[10].ObjectID = 0;
- this->OpenContainer[3].ObjectID = 0;
- this->OpenContainer[9].ObjectID = 0;
- this->OpenContainer[0xb].ObjectID = 0;
- this->OpenContainer[0xe].ObjectID = 0;
- this->OpenContainer[0xc].ObjectID = 0;
- this->OpenContainer[0xd].ObjectID = 0;
- this->OpenContainer[0xf].ObjectID = 0;
- puVar14 = this->SpellList;
- for (iVar13 = 0x40; iVar13 != 0; iVar13 = iVar13 + -1) {
- puVar14[0] = '\0';
- puVar14[1] = '\0';
- puVar14[2] = '\0';
- puVar14[3] = '\0';
- puVar14 = puVar14 + 4;
- }
- uVar7 = 2000;
- piVar15 = this->QuestValues;
- if (((uint)piVar15 & 4) != 0) {
- uVar7 = 0x7cc;
- this->QuestValues[0] = 0;
- piVar15 = this->QuestValues + 1;
- }
- for (uVar7 = uVar7 >> 2; uVar7 != 0; uVar7 = uVar7 - 1) {
- *piVar15 = 0;
- piVar15 = piVar15 + 1;
- }
- this->Request = 0;
- this->RequestTimestamp = 0;
- this->RequestProcessingGamemaster = 0;
- this->TutorActivities = 0;
- this->NumberOfAttackedPlayers = 0;
- this->NumberOfFormerAttackedPlayers = 0;
- this->PartyLeader = 0;
- (this->super_TCreature).LoseInventory = 1;
- iVar13 = 0;
- this->Guild[0] = '\0';
- this->Rank[0] = '\0';
- this->Title[0] = '\0';
- this->Aggressor = false;
- this->FormerAggressor = false;
- this->TalkBufferFullTime = 0;
- this->MutingEndRound = 0;
- this->NumberOfMutings = 0;
- do {
- this->Addressees[iVar13] = 0;
- iVar13 = iVar13 + 1;
- } while (iVar13 < 0x14);
- // try { // try from 080a91fa to 080a9232 has its CatchHandler @ 080a9a3b
- pTVar8 = AttachPlayerPoolSlot(CharacterID,false);
- this->PlayerData = pTVar8;
- if (pTVar8 == (TPlayerData *)0x0) {
- error("TPlayer::TPlayer: PlayerData-Slot nicht gefunden.\n");
- this->ConstructError = ERROR;
- }
- else {
- SendMails(pTVar8);
- pTVar8 = this->PlayerData;
- __dest = (this->super_TCreature).Name;
- (this->super_TCreature).Connection = Connection;
- strcpy(__dest,pTVar8->Name);
- // try { // try from 080a9266 to 080a99d8 has its CatchHandler @ 080a99f0
- TCreature::SetID(&this->super_TCreature,CharacterID);
- InsertPlayerIndex(&PlayerIndexHead,0,__dest,CharacterID);
- LoadData(this);
- this->AccountID = this->PlayerData->AccountID;
- __src = TConnection::GetIPAddress(Connection);
- strcpy(this->IPAddress,__src);
- pTVar8 = this->PlayerData;
- *(undefined4 *)this->Rights = *(undefined4 *)pTVar8->Rights;
- *(undefined4 *)(this->Rights + 4) = *(undefined4 *)(pTVar8->Rights + 4);
- *(undefined4 *)(this->Rights + 8) = *(undefined4 *)(pTVar8->Rights + 8);
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- Log("game","Spieler besitzt Premium Account.\n");
- }
- pTVar8 = this->PlayerData;
- (this->super_TCreature).Sex = pTVar8->Sex;
- strcpy(this->Guild,pTVar8->Guild);
- strcpy(this->Rank,this->PlayerData->Rank);
- strcpy(this->Title,this->PlayerData->Title);
- pTVar8 = this->PlayerData;
- this->Request = 0;
- this->RequestTimestamp = 0;
- this->RequestProcessingGamemaster = 0;
- tVar9 = time((time_t *)0x0);
- if (pTVar8->PlayerkillerEnd < tVar9) {
- this->PlayerData->PlayerkillerEnd = 0;
- }
- CheckOutfit(this);
- TCreature::SetInCrList(&this->super_TCreature);
- Semaphore::down(&PlayerMutex);
- ppTVar10 = vector<TPlayer*>::operator()(&PlayerList,FirstFreePlayer);
- FirstFreePlayer = FirstFreePlayer + 1;
- *ppTVar10 = this;
- Semaphore::up(&PlayerMutex);
- iVar13 = 1;
- NotifyBuddies((this->super_TCreature).ID,__dest,true);
- IncrementPlayersOnline();
- if ((this->super_TCreature).Profession == '\0') {
- IncrementNewbiesOnline();
- }
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0x16];
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- bVar4 = 9 < (this->super_TCreature).Profession;
- }
- else {
- bVar4 = false;
- }
- iVar11 = 200;
- if (!bVar4) {
- iVar11 = 100;
- }
- pTVar2->Max = iVar11;
- TSkill::Check((this->super_TCreature).super_TSkillBase.Skills[0x16]);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0x16];
- iVar11 = (*pTVar2->_vptr_TSkill[0xd])(pTVar2);
- if (0xe < iVar11) {
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- bVar4 = 9 < (this->super_TCreature).Profession;
- }
- else {
- bVar4 = false;
- }
- iVar13 = 0xf;
- if (!bVar4) {
- iVar13 = 0x78;
- }
- CharacterID = (iVar11 + -1) % iVar13 + 1;
- iVar13 = (iVar11 + -1) / iVar13 + 1;
- TSkillBase::SetTimer(&(this->super_TCreature).super_TSkillBase);
- }
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[2];
- iVar11 = TSkill::Get(pTVar2);
- if (iVar11 < 1) {
- (*pTVar2->_vptr_TSkill[2])(pTVar2,pTVar2->Max,iVar13,CharacterID);
- iVar13 = 0;
- (this->super_TCreature).posx = (this->super_TCreature).startx;
- (this->super_TCreature).posy = (this->super_TCreature).starty;
- (this->super_TCreature).posz = (this->super_TCreature).startz;
- do {
- TSkillBase::DelTimer(&(this->super_TCreature).super_TSkillBase,(ushort)iVar13);
- TSkill::SetMDAct((this->super_TCreature).super_TSkillBase.Skills[iVar13],0);
- ppTVar1 = (this->super_TCreature).super_TSkillBase.Skills + iVar13;
- iVar13 = iVar13 + 1;
- (*ppTVar1)->DAct = 0;
- } while (iVar13 < 0x19);
- aVar3 = (this->super_TCreature).OrgOutfit.field_1;
- (this->super_TCreature).Outfit.OutfitID = (this->super_TCreature).OrgOutfit.OutfitID;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[3];
- (this->super_TCreature).Outfit.field_1 = aVar3;
- (*pTVar2->_vptr_TSkill[2])
- ((this->super_TCreature).super_TSkillBase.Skills[3],pTVar2->Max);
- }
- if (this->PlayerData->LastLoginTime == 0) {
- bVar4 = CheckRight((this->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (bVar4) {
- Log("game","Gamemaster-Charakter %s loggt zum ersten Mal ein -> Level 2 setzen.\n",
- __dest);
- (this->super_TCreature).super_TSkillBase.Skills[0]->Act = 2;
- (this->super_TCreature).super_TSkillBase.Skills[0]->Exp = 100;
- (this->super_TCreature).super_TSkillBase.Skills[0]->LastLevel = 100;
- (this->super_TCreature).super_TSkillBase.Skills[0]->NextLevel = 200;
- }
- }
- bVar4 = CoordinateFlag();
- if (bVar4) {
- Regenerate(this);
- }
- HouseID = GetHouseID((this->super_TCreature).posx,(this->super_TCreature).posy,
- (this->super_TCreature).posz);
- if (HouseID != 0) {
- bVar4 = IsInvited(HouseID,this,this->PlayerData->LastLogoutTime);
- if (!bVar4) {
- bVar4 = CheckRight((this->super_TCreature).ID,ENTER_HOUSES);
- if (!bVar4) {
- GetExitPosition(HouseID,&(this->super_TCreature).posx,
- &(this->super_TCreature).posy,&(this->super_TCreature).posz);
- }
- }
- }
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (!bVar4) {
- bVar4 = IsPremiumArea((this->super_TCreature).startx,(this->super_TCreature).starty,
- (this->super_TCreature).startz);
- if (bVar4) {
- Log("game",&DAT_08103880,__dest);
- bVar5 = (this->super_TCreature).Profession;
- if (9 < bVar5) {
- bVar5 = bVar5 - 10;
- }
- GetStartPosition(&(this->super_TCreature).startx,&(this->super_TCreature).starty,
- &(this->super_TCreature).startz,bVar5 == 0);
- }
- bVar4 = IsPremiumArea((this->super_TCreature).posx,(this->super_TCreature).posy,
- (this->super_TCreature).posz);
- if (bVar4) {
- Log("game",
- "Spieler %s wird aus PayArea geworfen und in seine Heimatstadt gesetzt.\n",
- __dest);
- (this->super_TCreature).posx = (this->super_TCreature).startx;
- (this->super_TCreature).posy = (this->super_TCreature).starty;
- (this->super_TCreature).posz = (this->super_TCreature).startz;
- }
- }
- TCreature::SetOnMap(&this->super_TCreature);
- TConnection::EnterGame(Connection);
- SendInitGame((TConnection *)(this->super_TCreature).ID,id);
- SendRights((this->super_TCreature).Connection);
- SendFullScreen((this->super_TCreature).Connection);
- local_3c[0].ObjectID = (this->super_TCreature).CrObject.ObjectID;
- GraphicalEffect(local_3c,0xb);
- LoadInventory(this,this->PlayerData->LastLoginTime == 0);
- TCreature::NotifyChangeInventory(&this->super_TCreature);
- SendAmbiente((this->super_TCreature).Connection);
- pTVar12 = GetCreature((this->super_TCreature).ID);
- if (pTVar12 == (TCreature *)0x0) {
- error("TPlayer::TPlayer: Kreatur nicht korrekt angelegt.\n");
- }
- else {
- AnnounceChangedCreature((this->super_TCreature).ID,2);
- }
- SendPlayerSkills((this->super_TCreature).Connection);
- this->OldState = 0;
- CheckState(this);
- if (this->PlayerData->LastLoginTime == 0) {
- bVar4 = CheckRight((this->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (!bVar4) {
- Log("game","Spieler %s loggt zum ersten Mal ein -> Outfitwahl.\n",__dest);
- SendMessage((this->super_TCreature).Connection,0x14,
- "Welcome to Tibia! Please choose your outfit.");
- SendOutfit((this->super_TCreature).Connection);
- }
- }
- SendBuddies(this);
- pTVar8 = this->PlayerData;
- if (pTVar8->LastLoginTime != 0) {
- __tp = localtime(&pTVar8->LastLoginTime);
- strftime(local_ac,100,"%d. %b %Y %X %Z",__tp);
- SendMessage((this->super_TCreature).Connection,0x14,"Your last visit in Tibia: %s.",
- local_ac);
- pTVar8 = this->PlayerData;
- }
- tVar9 = time((time_t *)0x0);
- pTVar8->LastLoginTime = tVar9;
- }
- return;
-}
-
-
-
-// DWARF original prototype: void TPlayer(TPlayer * this, TConnection * Connection, ulong
-// CharacterID)
-
-void __thiscall TPlayer::TPlayer(TPlayer *this,TConnection *Connection,ulong CharacterID)
-
-{
- char *__dest;
- TSkill **ppTVar1;
- TSkill *pTVar2;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar3;
- bool bVar4;
- byte bVar5;
- ushort HouseID;
- int i;
- Object *pOVar6;
- uint uVar7;
- TPlayerData *pTVar8;
- char *__src;
- time_t tVar9;
- TPlayer **ppTVar10;
- int iVar11;
- TCreature *pTVar12;
- tm *__tp;
- int iVar13;
- ulong id;
- int i_1;
- uchar *puVar14;
- int *piVar15;
- char local_ac [4];
- char TimeString [100];
- Object local_3c [4];
- ulong local_2c;
-
- TCreature::TCreature(&this->super_TCreature);
- pOVar6 = this->OpenContainer;
- (this->Depot).ObjectID = 0;
- (this->TradeObject).ObjectID = 0;
- iVar13 = 0xf;
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)&PTR__TPlayer_08127c68;
- do {
- pOVar6->ObjectID = 0;
- iVar13 = iVar13 + -1;
- pOVar6 = pOVar6 + 1;
- } while (iVar13 != -1);
- // try { // try from 080a9ad6 to 080a9ada has its CatchHandler @ 080aa4f3
- vector<>::vector(&this->AttackedPlayers,0,10,10);
- // try { // try from 080a9b02 to 080a9b06 has its CatchHandler @ 080aa4ef
- vector<>::vector(&this->FormerAttackedPlayers,0,10,10);
- (this->super_TCreature).Profession = '\0';
- this->ConstructError = NOERROR;
- (this->super_TCreature).Type = PLAYER;
- (this->Depot).ObjectID = ::NONE.ObjectID;
- local_3c[0] = ::NONE;
- local_2c = ::NONE.ObjectID;
- (this->TradeObject).ObjectID = ::NONE.ObjectID;
- this->OpenContainer[0].ObjectID = 0;
- this->OldState = 0;
- this->OpenContainer[3].ObjectID = 0;
- this->OpenContainer[4].ObjectID = 0;
- this->OpenContainer[2].ObjectID = 0;
- this->OpenContainer[6].ObjectID = 0;
- this->OpenContainer[7].ObjectID = 0;
- this->OpenContainer[5].ObjectID = 0;
- this->OpenContainer[9].ObjectID = 0;
- this->OpenContainer[0xb].ObjectID = 0;
- this->OpenContainer[1].ObjectID = 0;
- this->OpenContainer[8].ObjectID = 0;
- this->OpenContainer[0xc].ObjectID = 0;
- this->OpenContainer[0xe].ObjectID = 0;
- this->OpenContainer[10].ObjectID = 0;
- this->OpenContainer[0xd].ObjectID = 0;
- this->OpenContainer[0xf].ObjectID = 0;
- puVar14 = this->SpellList;
- for (iVar13 = 0x40; iVar13 != 0; iVar13 = iVar13 + -1) {
- puVar14[0] = '\0';
- puVar14[1] = '\0';
- puVar14[2] = '\0';
- puVar14[3] = '\0';
- puVar14 = puVar14 + 4;
- }
- uVar7 = 2000;
- piVar15 = this->QuestValues;
- if (((uint)piVar15 & 4) != 0) {
- piVar15 = this->QuestValues + 1;
- uVar7 = 0x7cc;
- this->QuestValues[0] = 0;
- }
- for (uVar7 = uVar7 >> 2; uVar7 != 0; uVar7 = uVar7 - 1) {
- *piVar15 = 0;
- piVar15 = piVar15 + 1;
- }
- this->Request = 0;
- this->RequestTimestamp = 0;
- this->RequestProcessingGamemaster = 0;
- this->TutorActivities = 0;
- (this->super_TCreature).LoseInventory = 1;
- this->NumberOfAttackedPlayers = 0;
- this->NumberOfFormerAttackedPlayers = 0;
- this->NumberOfMutings = 0;
- iVar13 = 0;
- this->Guild[0] = '\0';
- this->Rank[0] = '\0';
- this->Title[0] = '\0';
- this->Aggressor = false;
- this->FormerAggressor = false;
- this->PartyLeader = 0;
- this->TalkBufferFullTime = 0;
- this->MutingEndRound = 0;
- do {
- this->Addressees[iVar13] = 0;
- iVar13 = iVar13 + 1;
- } while (iVar13 < 0x14);
- // try { // try from 080a9caa to 080a9ce2 has its CatchHandler @ 080aa4eb
- pTVar8 = AttachPlayerPoolSlot(CharacterID,false);
- this->PlayerData = pTVar8;
- if (pTVar8 == (TPlayerData *)0x0) {
- error("TPlayer::TPlayer: PlayerData-Slot nicht gefunden.\n");
- this->ConstructError = ERROR;
- }
- else {
- SendMails(pTVar8);
- pTVar8 = this->PlayerData;
- (this->super_TCreature).Connection = Connection;
- __dest = (this->super_TCreature).Name;
- strcpy(__dest,pTVar8->Name);
- // try { // try from 080a9d16 to 080aa488 has its CatchHandler @ 080aa4a0
- TCreature::SetID(&this->super_TCreature,CharacterID);
- InsertPlayerIndex(&PlayerIndexHead,0,__dest,CharacterID);
- LoadData(this);
- this->AccountID = this->PlayerData->AccountID;
- __src = TConnection::GetIPAddress(Connection);
- strcpy(this->IPAddress,__src);
- pTVar8 = this->PlayerData;
- *(undefined4 *)this->Rights = *(undefined4 *)pTVar8->Rights;
- *(undefined4 *)(this->Rights + 4) = *(undefined4 *)(pTVar8->Rights + 4);
- *(undefined4 *)(this->Rights + 8) = *(undefined4 *)(pTVar8->Rights + 8);
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- Log("game","Spieler besitzt Premium Account.\n");
- }
- pTVar8 = this->PlayerData;
- (this->super_TCreature).Sex = pTVar8->Sex;
- strcpy(this->Guild,pTVar8->Guild);
- strcpy(this->Rank,this->PlayerData->Rank);
- strcpy(this->Title,this->PlayerData->Title);
- pTVar8 = this->PlayerData;
- this->Request = 0;
- this->RequestTimestamp = 0;
- this->RequestProcessingGamemaster = 0;
- tVar9 = time((time_t *)0x0);
- if (pTVar8->PlayerkillerEnd < tVar9) {
- this->PlayerData->PlayerkillerEnd = 0;
- }
- CheckOutfit(this);
- TCreature::SetInCrList(&this->super_TCreature);
- Semaphore::down(&PlayerMutex);
- ppTVar10 = vector<TPlayer*>::operator()(&PlayerList,FirstFreePlayer);
- FirstFreePlayer = FirstFreePlayer + 1;
- *ppTVar10 = this;
- Semaphore::up(&PlayerMutex);
- iVar13 = 1;
- NotifyBuddies((this->super_TCreature).ID,__dest,true);
- IncrementPlayersOnline();
- if ((this->super_TCreature).Profession == '\0') {
- IncrementNewbiesOnline();
- }
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0x16];
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- bVar4 = 9 < (this->super_TCreature).Profession;
- }
- else {
- bVar4 = false;
- }
- iVar11 = 200;
- if (!bVar4) {
- iVar11 = 100;
- }
- pTVar2->Max = iVar11;
- TSkill::Check((this->super_TCreature).super_TSkillBase.Skills[0x16]);
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[0x16];
- iVar11 = (*pTVar2->_vptr_TSkill[0xd])(pTVar2);
- if (0xe < iVar11) {
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar4) {
- bVar4 = 9 < (this->super_TCreature).Profession;
- }
- else {
- bVar4 = false;
- }
- iVar13 = 0xf;
- if (!bVar4) {
- iVar13 = 0x78;
- }
- CharacterID = (iVar11 + -1) % iVar13 + 1;
- iVar13 = (iVar11 + -1) / iVar13 + 1;
- TSkillBase::SetTimer(&(this->super_TCreature).super_TSkillBase);
- }
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[2];
- iVar11 = TSkill::Get(pTVar2);
- if (iVar11 < 1) {
- (*pTVar2->_vptr_TSkill[2])(pTVar2,pTVar2->Max,iVar13,CharacterID);
- iVar13 = 0;
- (this->super_TCreature).posx = (this->super_TCreature).startx;
- (this->super_TCreature).posy = (this->super_TCreature).starty;
- (this->super_TCreature).posz = (this->super_TCreature).startz;
- do {
- TSkillBase::DelTimer(&(this->super_TCreature).super_TSkillBase,(ushort)iVar13);
- TSkill::SetMDAct((this->super_TCreature).super_TSkillBase.Skills[iVar13],0);
- ppTVar1 = (this->super_TCreature).super_TSkillBase.Skills + iVar13;
- iVar13 = iVar13 + 1;
- (*ppTVar1)->DAct = 0;
- } while (iVar13 < 0x19);
- aVar3 = (this->super_TCreature).OrgOutfit.field_1;
- (this->super_TCreature).Outfit.OutfitID = (this->super_TCreature).OrgOutfit.OutfitID;
- pTVar2 = (this->super_TCreature).super_TSkillBase.Skills[3];
- (this->super_TCreature).Outfit.field_1 = aVar3;
- (*pTVar2->_vptr_TSkill[2])
- ((this->super_TCreature).super_TSkillBase.Skills[3],pTVar2->Max);
- }
- if (this->PlayerData->LastLoginTime == 0) {
- bVar4 = CheckRight((this->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (bVar4) {
- Log("game","Gamemaster-Charakter %s loggt zum ersten Mal ein -> Level 2 setzen.\n",
- __dest);
- (this->super_TCreature).super_TSkillBase.Skills[0]->Act = 2;
- (this->super_TCreature).super_TSkillBase.Skills[0]->Exp = 100;
- (this->super_TCreature).super_TSkillBase.Skills[0]->LastLevel = 100;
- (this->super_TCreature).super_TSkillBase.Skills[0]->NextLevel = 200;
- }
- }
- bVar4 = CoordinateFlag();
- if (bVar4) {
- Regenerate(this);
- }
- HouseID = GetHouseID((this->super_TCreature).posx,(this->super_TCreature).posy,
- (this->super_TCreature).posz);
- if (HouseID != 0) {
- bVar4 = IsInvited(HouseID,this,this->PlayerData->LastLogoutTime);
- if (!bVar4) {
- bVar4 = CheckRight((this->super_TCreature).ID,ENTER_HOUSES);
- if (!bVar4) {
- GetExitPosition(HouseID,&(this->super_TCreature).posx,
- &(this->super_TCreature).posy,&(this->super_TCreature).posz);
- }
- }
- }
- bVar4 = CheckRight((this->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (!bVar4) {
- bVar4 = IsPremiumArea((this->super_TCreature).startx,(this->super_TCreature).starty,
- (this->super_TCreature).startz);
- if (bVar4) {
- Log("game",&DAT_08103880,__dest);
- bVar5 = (this->super_TCreature).Profession;
- if (9 < bVar5) {
- bVar5 = bVar5 - 10;
- }
- GetStartPosition(&(this->super_TCreature).startx,&(this->super_TCreature).starty,
- &(this->super_TCreature).startz,bVar5 == 0);
- }
- bVar4 = IsPremiumArea((this->super_TCreature).posx,(this->super_TCreature).posy,
- (this->super_TCreature).posz);
- if (bVar4) {
- Log("game",
- "Spieler %s wird aus PayArea geworfen und in seine Heimatstadt gesetzt.\n",
- __dest);
- (this->super_TCreature).posx = (this->super_TCreature).startx;
- (this->super_TCreature).posy = (this->super_TCreature).starty;
- (this->super_TCreature).posz = (this->super_TCreature).startz;
- }
- }
- TCreature::SetOnMap(&this->super_TCreature);
- TConnection::EnterGame(Connection);
- SendInitGame((TConnection *)(this->super_TCreature).ID,id);
- SendRights((this->super_TCreature).Connection);
- SendFullScreen((this->super_TCreature).Connection);
- local_3c[0].ObjectID = (this->super_TCreature).CrObject.ObjectID;
- GraphicalEffect(local_3c,0xb);
- LoadInventory(this,this->PlayerData->LastLoginTime == 0);
- TCreature::NotifyChangeInventory(&this->super_TCreature);
- SendAmbiente((this->super_TCreature).Connection);
- pTVar12 = GetCreature((this->super_TCreature).ID);
- if (pTVar12 == (TCreature *)0x0) {
- error("TPlayer::TPlayer: Kreatur nicht korrekt angelegt.\n");
- }
- else {
- AnnounceChangedCreature((this->super_TCreature).ID,2);
- }
- SendPlayerSkills((this->super_TCreature).Connection);
- this->OldState = 0;
- CheckState(this);
- if (this->PlayerData->LastLoginTime == 0) {
- bVar4 = CheckRight((this->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (!bVar4) {
- Log("game","Spieler %s loggt zum ersten Mal ein -> Outfitwahl.\n",__dest);
- SendMessage((this->super_TCreature).Connection,0x14,
- "Welcome to Tibia! Please choose your outfit.");
- SendOutfit((this->super_TCreature).Connection);
- }
- }
- SendBuddies(this);
- pTVar8 = this->PlayerData;
- if (pTVar8->LastLoginTime != 0) {
- __tp = localtime(&pTVar8->LastLoginTime);
- strftime(local_ac,100,"%d. %b %Y %X %Z",__tp);
- SendMessage((this->super_TCreature).Connection,0x14,"Your last visit in Tibia: %s.",
- local_ac);
- pTVar8 = this->PlayerData;
- }
- tVar9 = time((time_t *)0x0);
- pTVar8->LastLoginTime = tVar9;
- }
- return;
-}
-
-
-
-// DWARF original prototype: void ~TPlayer(TPlayer * this, int __in_chrg)
-
-void __thiscall TPlayer::~TPlayer(TPlayer *this,int __in_chrg)
-
-{
- ulong *puVar1;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar2;
- bool bVar3;
- TCreature *cr;
- time_t tVar4;
- TCreature *pTVar5;
- __pid_t _Var6;
- ulong uVar7;
- TSkill *pTVar8;
- int iVar9;
- TPlayerData *pTVar10;
- int i;
- TCreature *pTVar11;
- uint uVar12;
- uchar *puVar13;
- int *piVar14;
- char *pcVar15;
- char *in_stack_ffffffd8;
- char *pcVar16;
- char *local_14;
-
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)&PTR__TPlayer_08127c68;
- LogoutOrder(this);
- if (this->ConstructError != NOERROR) {
- DelInList(this);
- goto LAB_080aa53c;
- }
- pTVar10 = this->PlayerData;
- tVar4 = time((time_t *)0x0);
- pTVar10->LastLogoutTime = tVar4;
- SaveData(this);
- if ((this->super_TCreature).IsDead == false) {
- Log("game","Spieler %s loggt aus.\n",(this->super_TCreature).Name);
- pcVar16 = (char *)(this->super_TCreature).posz;
- GraphicalEffect();
- SaveInventory(this);
- }
- else {
- pcVar16 = (this->super_TCreature).Name;
- pcVar15 = pcVar16;
- Log("game","Spieler %s ist gestorben.\n",pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("TPlayer::~TPlayer: PlayerData ist NULL.\n");
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) goto LAB_080aa5d9;
- }
- else {
-LAB_080aa5d9:
- if (pTVar10->Inventory != (uchar *)0x0) {
- operator_delete__(pTVar10->Inventory);
- this->PlayerData->Inventory = (uchar *)0x0;
- }
- }
- if (((this->super_TCreature).Profession == '\0') ||
- (iVar9 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0]), 5 < iVar9)) {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
- if (pTVar8->Max < 1) goto LAB_080aa7f3;
- pTVar10 = this->PlayerData;
- pcVar16 = pcVar15;
- }
- else {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
-LAB_080aa7f3:
- if (pTVar8->Max < 1) {
- Log("game",&DAT_08103aa0,pcVar16);
- }
- Log("game",&DAT_08103a60,pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) {
- uVar12 = 2000;
- aVar2 = (pTVar10->OriginalOutfit).field_1;
- (pTVar10->CurrentOutfit).OutfitID = (pTVar10->OriginalOutfit).OutfitID;
- (pTVar10->CurrentOutfit).field_1 = aVar2;
- this->PlayerData->startx = 0;
- this->PlayerData->starty = 0;
- this->PlayerData->startz = 0;
- this->PlayerData->posx = 0;
- this->PlayerData->posy = 0;
- this->PlayerData->posz = 0;
- this->PlayerData->Profession = 0;
- puVar13 = this->PlayerData->SpellList;
- for (iVar9 = 0x40; iVar9 != 0; iVar9 = iVar9 + -1) {
- puVar13[0] = '\0';
- puVar13[1] = '\0';
- puVar13[2] = '\0';
- puVar13[3] = '\0';
- puVar13 = puVar13 + 4;
- }
- pTVar10 = this->PlayerData;
- piVar14 = pTVar10->QuestValues;
- if (((uint)piVar14 & 4) != 0) {
- piVar14 = pTVar10->QuestValues + 1;
- pTVar10->QuestValues[0] = 0;
- uVar12 = 0x7cc;
- }
- iVar9 = 0;
- for (uVar12 = uVar12 >> 2; uVar12 != 0; uVar12 = uVar12 - 1) {
- *piVar14 = 0;
- piVar14 = piVar14 + 1;
- }
- do {
- this->PlayerData->Minimum[iVar9] = -0x80000000;
- iVar9 = iVar9 + 1;
- } while (iVar9 < 0x19);
- pTVar10 = this->PlayerData;
- }
- (this->super_TCreature).LoseInventory = 2;
- }
- if (pTVar10->PlayerkillerEnd != 0) {
- (this->super_TCreature).LoseInventory = 2;
- }
- bVar3 = CheckRight((this->super_TCreature).ID,KEEP_INVENTORY);
- if (bVar3) {
- (this->super_TCreature).LoseInventory = 0;
- }
- }
- local_14 = (this->super_TCreature).Name;
- in_stack_ffffffd8 = (char *)0xe;
- bVar3 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- if (bVar3) {
- CloseProcessedRequests((this->super_TCreature).ID);
- }
- if (this->Request != 0) {
- if (this->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest(local_14);
- }
- else {
- pTVar5 = GetCreature(this->RequestProcessingGamemaster);
- pTVar11 = (TCreature *)0x0;
- if ((pTVar5 != (TCreature *)0x0) && (pTVar11 = pTVar5, pTVar5->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar11 = (TCreature *)0x0;
- }
- if (pTVar11 != (TCreature *)0x0) {
- SendFinishRequest(pTVar11->Connection,local_14);
- in_stack_ffffffd8 = local_14;
- }
- }
- this->Request = 0;
- }
- LeaveAllChannels((this->super_TCreature).ID);
- if (this->PartyLeavingRound == 0) {
- uVar7 = this->PartyLeader;
- }
- else {
- uVar7 = 0;
- }
- if (uVar7 != 0) {
- in_stack_ffffffd8 = (char *)0x1;
- ::LeaveParty((this->super_TCreature).ID,true);
- }
- ClearPlayerkillingMarks(this);
- DelInList(this);
- this->PlayerData->Dirty = true;
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("DecreasePlayerPoolSlotSticky: Slot ist NULL.\n");
- }
- else {
- Semaphore::down(&PlayerDataPoolMutex);
- piVar14 = &pTVar10->Sticky;
- *piVar14 = *piVar14 + -1;
- Semaphore::up(&PlayerDataPoolMutex);
- }
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist NULL.\n";
- }
- else {
- pcVar16 = (char *)pTVar10->CharacterID;
- in_stack_ffffffd8 = "Gebe Slot von Spieler %ld frei.\n";
- print();
- if (pTVar10->Locked == 0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist nicht gesperrt.\n";
- }
- else {
- _Var6 = getpid();
- if (pTVar10->Locked == _Var6) {
- pTVar10->Locked = 0;
- goto LAB_080aa53c;
- }
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist von einem anderen Thread gesperrt.\n";
- }
- }
- error(pcVar15,in_stack_ffffffd8,pcVar16);
-LAB_080aa53c:
- puVar1 = (this->FormerAttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- puVar1 = (this->AttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- TCreature::~TCreature(&this->super_TCreature,(int)in_stack_ffffffd8);
- return;
-}
-
-
-
-// DWARF original prototype: void ~TPlayer(TPlayer * this, int __in_chrg)
-
-void __thiscall TPlayer::~TPlayer(TPlayer *this,int __in_chrg)
-
-{
- ulong *puVar1;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar2;
- bool bVar3;
- TCreature *cr;
- time_t tVar4;
- TCreature *pTVar5;
- __pid_t _Var6;
- ulong uVar7;
- TSkill *pTVar8;
- int iVar9;
- TPlayerData *pTVar10;
- int i;
- TCreature *pTVar11;
- uint uVar12;
- uchar *puVar13;
- int *piVar14;
- char *pcVar15;
- char *in_stack_ffffffd8;
- char *pcVar16;
- char *local_14;
-
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)&PTR__TPlayer_08127c68;
- LogoutOrder(this);
- if (this->ConstructError != NOERROR) {
- DelInList(this);
- goto LAB_080aaa0c;
- }
- pTVar10 = this->PlayerData;
- tVar4 = time((time_t *)0x0);
- pTVar10->LastLogoutTime = tVar4;
- SaveData(this);
- if ((this->super_TCreature).IsDead == false) {
- Log("game","Spieler %s loggt aus.\n",(this->super_TCreature).Name);
- pcVar16 = (char *)(this->super_TCreature).posz;
- GraphicalEffect();
- SaveInventory(this);
- }
- else {
- pcVar16 = (this->super_TCreature).Name;
- pcVar15 = pcVar16;
- Log("game","Spieler %s ist gestorben.\n",pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("TPlayer::~TPlayer: PlayerData ist NULL.\n");
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) goto LAB_080aaaa9;
- }
- else {
-LAB_080aaaa9:
- if (pTVar10->Inventory != (uchar *)0x0) {
- operator_delete__(pTVar10->Inventory);
- this->PlayerData->Inventory = (uchar *)0x0;
- }
- }
- if (((this->super_TCreature).Profession == '\0') ||
- (iVar9 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0]), 5 < iVar9)) {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
- if (pTVar8->Max < 1) goto LAB_080aacc3;
- pTVar10 = this->PlayerData;
- pcVar16 = pcVar15;
- }
- else {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
-LAB_080aacc3:
- if (pTVar8->Max < 1) {
- Log("game",&DAT_08103aa0,pcVar16);
- }
- Log("game",&DAT_08103a60,pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) {
- uVar12 = 2000;
- aVar2 = (pTVar10->OriginalOutfit).field_1;
- (pTVar10->CurrentOutfit).OutfitID = (pTVar10->OriginalOutfit).OutfitID;
- (pTVar10->CurrentOutfit).field_1 = aVar2;
- this->PlayerData->startx = 0;
- this->PlayerData->starty = 0;
- this->PlayerData->startz = 0;
- this->PlayerData->posx = 0;
- this->PlayerData->posy = 0;
- this->PlayerData->posz = 0;
- this->PlayerData->Profession = 0;
- puVar13 = this->PlayerData->SpellList;
- for (iVar9 = 0x40; iVar9 != 0; iVar9 = iVar9 + -1) {
- puVar13[0] = '\0';
- puVar13[1] = '\0';
- puVar13[2] = '\0';
- puVar13[3] = '\0';
- puVar13 = puVar13 + 4;
- }
- pTVar10 = this->PlayerData;
- piVar14 = pTVar10->QuestValues;
- if (((uint)piVar14 & 4) != 0) {
- piVar14 = pTVar10->QuestValues + 1;
- pTVar10->QuestValues[0] = 0;
- uVar12 = 0x7cc;
- }
- iVar9 = 0;
- for (uVar12 = uVar12 >> 2; uVar12 != 0; uVar12 = uVar12 - 1) {
- *piVar14 = 0;
- piVar14 = piVar14 + 1;
- }
- do {
- this->PlayerData->Minimum[iVar9] = -0x80000000;
- iVar9 = iVar9 + 1;
- } while (iVar9 < 0x19);
- pTVar10 = this->PlayerData;
- }
- (this->super_TCreature).LoseInventory = 2;
- }
- if (pTVar10->PlayerkillerEnd != 0) {
- (this->super_TCreature).LoseInventory = 2;
- }
- bVar3 = CheckRight((this->super_TCreature).ID,KEEP_INVENTORY);
- if (bVar3) {
- (this->super_TCreature).LoseInventory = 0;
- }
- }
- local_14 = (this->super_TCreature).Name;
- in_stack_ffffffd8 = (char *)0xe;
- bVar3 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- if (bVar3) {
- CloseProcessedRequests((this->super_TCreature).ID);
- }
- if (this->Request != 0) {
- if (this->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest(local_14);
- }
- else {
- pTVar5 = GetCreature(this->RequestProcessingGamemaster);
- pTVar11 = (TCreature *)0x0;
- if ((pTVar5 != (TCreature *)0x0) && (pTVar11 = pTVar5, pTVar5->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar11 = (TCreature *)0x0;
- }
- if (pTVar11 != (TCreature *)0x0) {
- SendFinishRequest(pTVar11->Connection,local_14);
- in_stack_ffffffd8 = local_14;
- }
- }
- this->Request = 0;
- }
- LeaveAllChannels((this->super_TCreature).ID);
- if (this->PartyLeavingRound == 0) {
- uVar7 = this->PartyLeader;
- }
- else {
- uVar7 = 0;
- }
- if (uVar7 != 0) {
- in_stack_ffffffd8 = (char *)0x1;
- ::LeaveParty((this->super_TCreature).ID,true);
- }
- ClearPlayerkillingMarks(this);
- DelInList(this);
- this->PlayerData->Dirty = true;
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("DecreasePlayerPoolSlotSticky: Slot ist NULL.\n");
- }
- else {
- Semaphore::down(&PlayerDataPoolMutex);
- piVar14 = &pTVar10->Sticky;
- *piVar14 = *piVar14 + -1;
- Semaphore::up(&PlayerDataPoolMutex);
- }
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist NULL.\n";
- }
- else {
- pcVar16 = (char *)pTVar10->CharacterID;
- in_stack_ffffffd8 = "Gebe Slot von Spieler %ld frei.\n";
- print();
- if (pTVar10->Locked == 0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist nicht gesperrt.\n";
- }
- else {
- _Var6 = getpid();
- if (pTVar10->Locked == _Var6) {
- pTVar10->Locked = 0;
- goto LAB_080aaa0c;
- }
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist von einem anderen Thread gesperrt.\n";
- }
- }
- error(pcVar15,in_stack_ffffffd8,pcVar16);
-LAB_080aaa0c:
- puVar1 = (this->FormerAttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- puVar1 = (this->AttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- TCreature::~TCreature(&this->super_TCreature,(int)in_stack_ffffffd8);
- return;
-}
-
-
-
-// DWARF original prototype: void ~TPlayer(TPlayer * this, int __in_chrg)
-
-void __thiscall TPlayer::~TPlayer(TPlayer *this,int __in_chrg)
-
-{
- ulong *puVar1;
- anon_union_4_2_730cd3ca_for_TOutfit_2 aVar2;
- bool bVar3;
- TCreature *cr;
- time_t tVar4;
- TCreature *pTVar5;
- __pid_t _Var6;
- ulong uVar7;
- TSkill *pTVar8;
- int iVar9;
- TPlayerData *pTVar10;
- int i;
- TCreature *pTVar11;
- uint uVar12;
- uchar *puVar13;
- int *piVar14;
- char *pcVar15;
- char *in_stack_ffffffd8;
- char *pcVar16;
- char *local_14;
-
- (this->super_TCreature)._vptr_TCreature = (_func_int_varargs **)&PTR__TPlayer_08127c68;
- LogoutOrder(this);
- if (this->ConstructError != NOERROR) {
- DelInList(this);
- goto LAB_080aaedc;
- }
- pTVar10 = this->PlayerData;
- tVar4 = time((time_t *)0x0);
- pTVar10->LastLogoutTime = tVar4;
- SaveData(this);
- if ((this->super_TCreature).IsDead == false) {
- Log("game","Spieler %s loggt aus.\n",(this->super_TCreature).Name);
- pcVar16 = (char *)(this->super_TCreature).posz;
- GraphicalEffect();
- SaveInventory(this);
- }
- else {
- pcVar16 = (this->super_TCreature).Name;
- pcVar15 = pcVar16;
- Log("game","Spieler %s ist gestorben.\n",pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("TPlayer::~TPlayer: PlayerData ist NULL.\n");
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) goto LAB_080aaf79;
- }
- else {
-LAB_080aaf79:
- if (pTVar10->Inventory != (uchar *)0x0) {
- operator_delete__(pTVar10->Inventory);
- this->PlayerData->Inventory = (uchar *)0x0;
- }
- }
- if (((this->super_TCreature).Profession == '\0') ||
- (iVar9 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0]), 5 < iVar9)) {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
- if (pTVar8->Max < 1) goto LAB_080ab193;
- pTVar10 = this->PlayerData;
- pcVar16 = pcVar15;
- }
- else {
- pTVar8 = (this->super_TCreature).super_TSkillBase.Skills[2];
-LAB_080ab193:
- if (pTVar8->Max < 1) {
- Log("game",&DAT_08103aa0,pcVar16);
- }
- Log("game",&DAT_08103a60,pcVar16);
- pTVar10 = this->PlayerData;
- if (pTVar10 != (TPlayerData *)0x0) {
- uVar12 = 2000;
- aVar2 = (pTVar10->OriginalOutfit).field_1;
- (pTVar10->CurrentOutfit).OutfitID = (pTVar10->OriginalOutfit).OutfitID;
- (pTVar10->CurrentOutfit).field_1 = aVar2;
- this->PlayerData->startx = 0;
- this->PlayerData->starty = 0;
- this->PlayerData->startz = 0;
- this->PlayerData->posx = 0;
- this->PlayerData->posy = 0;
- this->PlayerData->posz = 0;
- this->PlayerData->Profession = 0;
- puVar13 = this->PlayerData->SpellList;
- for (iVar9 = 0x40; iVar9 != 0; iVar9 = iVar9 + -1) {
- puVar13[0] = '\0';
- puVar13[1] = '\0';
- puVar13[2] = '\0';
- puVar13[3] = '\0';
- puVar13 = puVar13 + 4;
- }
- pTVar10 = this->PlayerData;
- piVar14 = pTVar10->QuestValues;
- if (((uint)piVar14 & 4) != 0) {
- piVar14 = pTVar10->QuestValues + 1;
- pTVar10->QuestValues[0] = 0;
- uVar12 = 0x7cc;
- }
- iVar9 = 0;
- for (uVar12 = uVar12 >> 2; uVar12 != 0; uVar12 = uVar12 - 1) {
- *piVar14 = 0;
- piVar14 = piVar14 + 1;
- }
- do {
- this->PlayerData->Minimum[iVar9] = -0x80000000;
- iVar9 = iVar9 + 1;
- } while (iVar9 < 0x19);
- pTVar10 = this->PlayerData;
- }
- (this->super_TCreature).LoseInventory = 2;
- }
- if (pTVar10->PlayerkillerEnd != 0) {
- (this->super_TCreature).LoseInventory = 2;
- }
- bVar3 = CheckRight((this->super_TCreature).ID,KEEP_INVENTORY);
- if (bVar3) {
- (this->super_TCreature).LoseInventory = 0;
- }
- }
- local_14 = (this->super_TCreature).Name;
- in_stack_ffffffd8 = (char *)0xe;
- bVar3 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- if (bVar3) {
- CloseProcessedRequests((this->super_TCreature).ID);
- }
- if (this->Request != 0) {
- if (this->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest(local_14);
- }
- else {
- pTVar5 = GetCreature(this->RequestProcessingGamemaster);
- pTVar11 = (TCreature *)0x0;
- if ((pTVar5 != (TCreature *)0x0) && (pTVar11 = pTVar5, pTVar5->Type != PLAYER)) {
- error("GetPlayer: Kreatur ist kein Spieler.\n");
- pTVar11 = (TCreature *)0x0;
- }
- if (pTVar11 != (TCreature *)0x0) {
- SendFinishRequest(pTVar11->Connection,local_14);
- in_stack_ffffffd8 = local_14;
- }
- }
- this->Request = 0;
- }
- LeaveAllChannels((this->super_TCreature).ID);
- if (this->PartyLeavingRound == 0) {
- uVar7 = this->PartyLeader;
- }
- else {
- uVar7 = 0;
- }
- if (uVar7 != 0) {
- in_stack_ffffffd8 = (char *)0x1;
- ::LeaveParty((this->super_TCreature).ID,true);
- }
- ClearPlayerkillingMarks(this);
- DelInList(this);
- this->PlayerData->Dirty = true;
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- error("DecreasePlayerPoolSlotSticky: Slot ist NULL.\n");
- }
- else {
- Semaphore::down(&PlayerDataPoolMutex);
- piVar14 = &pTVar10->Sticky;
- *piVar14 = *piVar14 + -1;
- Semaphore::up(&PlayerDataPoolMutex);
- }
- pTVar10 = this->PlayerData;
- if (pTVar10 == (TPlayerData *)0x0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist NULL.\n";
- }
- else {
- pcVar16 = (char *)pTVar10->CharacterID;
- in_stack_ffffffd8 = "Gebe Slot von Spieler %ld frei.\n";
- print();
- if (pTVar10->Locked == 0) {
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist nicht gesperrt.\n";
- }
- else {
- _Var6 = getpid();
- if (pTVar10->Locked == _Var6) {
- pTVar10->Locked = 0;
- goto LAB_080aaedc;
- }
- pcVar15 = "ReleasePlayerPoolSlot: Slot ist von einem anderen Thread gesperrt.\n";
- }
- }
- error(pcVar15,in_stack_ffffffd8,pcVar16);
-LAB_080aaedc:
- puVar1 = (this->FormerAttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- puVar1 = (this->AttackedPlayers).entry;
- if (puVar1 != (ulong *)0x0) {
- operator_delete__(puVar1);
- }
- TCreature::~TCreature(&this->super_TCreature,(int)in_stack_ffffffd8);
- operator_delete(this);
- return;
-}
-
-
-
-// DWARF original prototype: void SetInList(TPlayer * this)
-
-void __thiscall TPlayer::SetInList(TPlayer *this)
-
-{
- TPlayer **ppTVar1;
-
- TCreature::SetInCrList(&this->super_TCreature);
- Semaphore::down(&PlayerMutex);
- ppTVar1 = vector<TPlayer*>::operator()(&PlayerList,FirstFreePlayer);
- FirstFreePlayer = FirstFreePlayer + 1;
- *ppTVar1 = this;
- Semaphore::up(&PlayerMutex);
- NotifyBuddies((this->super_TCreature).ID,(this->super_TCreature).Name,true);
- IncrementPlayersOnline();
- if ((this->super_TCreature).Profession != '\0') {
- return;
- }
- IncrementNewbiesOnline();
- return;
-}
-
-
-
-// DWARF original prototype: void DelInList(TPlayer * this)
-
-void __thiscall TPlayer::DelInList(TPlayer *this)
-
-{
- TPlayer **ppTVar1;
- TPlayer **ppTVar2;
- int i;
- int i_00;
-
- i_00 = 0;
- NotifyBuddies((this->super_TCreature).ID,(this->super_TCreature).Name,false);
- if (0 < FirstFreePlayer) {
- do {
- ppTVar1 = vector<TPlayer*>::operator()(&PlayerList,i_00);
- if (*ppTVar1 == this) {
- Semaphore::down(&PlayerMutex);
- ppTVar1 = vector<TPlayer*>::operator()(&PlayerList,i_00);
- ppTVar2 = vector<TPlayer*>::operator()(&PlayerList,FirstFreePlayer + -1);
- *ppTVar1 = *ppTVar2;
- ppTVar1 = vector<TPlayer*>::operator()(&PlayerList,FirstFreePlayer + -1);
- *ppTVar1 = (TPlayer *)0x0;
- FirstFreePlayer = FirstFreePlayer + -1;
- Semaphore::up(&PlayerMutex);
- DecrementPlayersOnline();
- if ((this->super_TCreature).Profession != '\0') {
- return;
- }
- DecrementNewbiesOnline();
- return;
- }
- i_00 = i_00 + 1;
- } while (i_00 < FirstFreePlayer);
- }
- return;
-}
-
-
-
// DWARF original prototype: void ClearConnection(TPlayer * this)
void __thiscall TPlayer::ClearConnection(TPlayer *this)
diff --git a/src/common.hh b/src/common.hh
index 9800e6a..4737c54 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <algorithm>
@@ -139,6 +140,7 @@ char *Capitals(char *Text);
// =============================================================================
extern uint32 RoundNr;
extern uint32 ServerMilliseconds;
+struct tm GetLocalTimeTM(time_t t);
void GetRealTime(int *Hour, int *Minute);
void GetTime(int *Hour, int *Minute);
void GetDate(int *Year, int *Cycle, int *Day);
diff --git a/src/connection.hh b/src/connection.hh
index 44b7360..4a5e544 100644
--- a/src/connection.hh
+++ b/src/connection.hh
@@ -18,6 +18,8 @@ struct TConnection {
TPlayer *GetPlayer(void);
void Logout(int Delay, bool StopFight);
bool IsVisible(int x, int y, int z);
+ void EnterGame(void);
+ const char *GetIPAddress(void);
// DATA
// =================
diff --git a/src/cr.hh b/src/cr.hh
index 20371ad..83ab647 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -433,6 +433,12 @@ struct TFindCreatures {
// TCreature
// =============================================================================
+enum : int {
+ LOSE_INVENTORY_NONE = 0,
+ LOSE_INVENTORY_SOME = 1,
+ LOSE_INVENTORY_ALL = 2,
+};
+
struct TToDoEntry {
ToDoType Code;
union{
@@ -707,7 +713,11 @@ struct TPlayerIndexLeafNode: TPlayerIndexNode {
};
struct TPlayer: TCreature {
- //TPlayer(void);
+ TPlayer(TConnection *Connection, uint32 CharacterID);
+ void SetInList(void);
+ void DelInList(void);
+
+//==
// TODO(fusion): Eventually sort these out when we implement player functions.
uint8 GetRealProfession(void);
@@ -716,22 +726,16 @@ struct TPlayer: TCreature {
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 CheckState(void);
-
void ClearPlayerkillingMarks(void);
void SaveInventory(void);
Object GetOpenContainer(int ContainerNr);
@@ -741,10 +745,16 @@ struct TPlayer: TCreature {
int CheckForMuting(void);
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);
// VIRTUAL FUNCTIONS
// =================
- // TODO
+ ~TPlayer(void) override;
// DATA
// =================
@@ -843,6 +853,45 @@ void ExitNonplayer();
// crplayer.cc
// =============================================================================
+int GetNumberOfPlayers(void);
+TPlayer *GetPlayer(uint32 CharacterID);
+TPlayer *GetPlayer(const char *Name);
+bool IsPlayerOnline(const char *Name);
+int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **OutPlayer);
+void LogoutAllPlayers(void);
+void CloseProcessedRequests(uint32 CharacterID);
+void NotifyBuddies(uint32 CharacterID, const char *Name, bool Login);
+void CreatePlayerList(bool Online);
+void PrintPlayerPositions(void);
+void LoadDepot(TPlayerData *PlayerData, int DepotNr, Object Con);
+void SaveDepot(TPlayerData *PlayerData, int DepotNr, Object Con);
+void GetProfessionName(char *Buffer, int Profession, bool Article, bool Capitals);
+void SendExistingRequests(TConnection *Connection);
+
+void SavePlayerPoolSlot(TPlayerData *Slot);
+void FreePlayerPoolSlot(TPlayerData *Slot);
+TPlayerData *GetPlayerPoolSlot(uint32 CharacterID);
+TPlayerData *AssignPlayerPoolSlot(uint32 CharacterID, bool DontWait);
+TPlayerData *AttachPlayerPoolSlot(uint32 CharacterID, bool DontWait);
+void AttachPlayerPoolSlot(TPlayerData *Slot, bool DontWait);
+void IncreasePlayerPoolSlotSticky(TPlayerData *Slot);
+void DecreasePlayerPoolSlotSticky(TPlayerData *Slot);
+void DecreasePlayerPoolSlotSticky(uint32 CharacterID);
+void ReleasePlayerPoolSlot(TPlayerData *Slot);
+void SavePlayerPoolSlots(void);
+void InitPlayerPool(void);
+void ExitPlayerPool(void);
+
+int GetPlayerIndexEntryNumber(const char *Name, int Position);
+void InsertPlayerIndex(TPlayerIndexInternalNode *Node,
+ int Position, const char *Name, uint32 CharacterID);
+TPlayerIndexEntry *SearchPlayerIndex(const char *Name);
+bool PlayerExists(const char *Name);
+uint32 GetCharacterID(const char *Name);
+const char *GetCharacterName(const char *Name);
+void InitPlayerIndex(void);
+void ExitPlayerIndex(void);
+
void InitPlayer(void);
void ExitPlayer(void);
diff --git a/src/crmain.cc b/src/crmain.cc
index f29a992..ddf5393 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -7,7 +7,6 @@
#include "stubs.hh"
#include <dirent.h>
-#include <time.h>
TRaceData RaceData[MAX_RACES];
priority_queue<uint32, uint32> ToDoQueue(5000, 1000);
@@ -135,7 +134,7 @@ TCreature::TCreature(void) :
this->Direction = 0;
this->Radius = INT_MAX;
this->IsDead = false;
- this->LoseInventory = 2;
+ this->LoseInventory = LOSE_INVENTORY_ALL;
this->LoggingOut = false;
this->LogoutAllowed = false;
this->EarliestLogoutRound = 0;
@@ -226,7 +225,7 @@ TCreature::~TCreature(void){
Change(Corpse, TEXTSTRING, AddDynamicString(Help));
}
- if(this->LoseInventory != 0){ // LOSE_INVENTORY_NONE ?
+ if(this->LoseInventory != LOSE_INVENTORY_NONE){
for(int Position = INVENTORY_FIRST;
Position <= INVENTORY_LAST;
Position += 1){
@@ -235,17 +234,15 @@ TCreature::~TCreature(void){
continue;
}
- if(this->LoseInventory != 2 // LOSE_INVENTORY_ALL ?
- && !Item.getObjectType().getFlag(CONTAINER)
- && random(0, 9) != 0){
- continue;
+ if(this->LoseInventory == LOSE_INVENTORY_ALL
+ || Item.getObjectType().getFlag(CONTAINER)
+ || random(0, 9) == 0){
+ ::Move(0, Item, Corpse, -1, false, NONE);
}
-
- ::Move(0, Item, Corpse, -1, false, NONE);
}
}
- if(this->Type == PLAYER && this->LoseInventory != 2){ // LOSE_INVENTORY_ALL ?
+ if(this->Type == PLAYER && this->LoseInventory != LOSE_INVENTORY_ALL){
((TPlayer*)this)->SaveInventory();
}
}catch(RESULT r){
@@ -757,7 +754,7 @@ int TCreature::Damage(TCreature *Attacker, int Damage, int DamageType){
ObjectType AmuletOfLossType = GetNewObjectType(77, 12);
if(ObjType == AmuletOfLossType){
Log("game", "%s stirbt mit Amulett of Loss.\n", this->Name);
- this->LoseInventory = 0;
+ this->LoseInventory = LOSE_INVENTORY_NONE;
try{
Delete(Obj, -1);
// TODO(fusion): Shouldn't we break here? We could also
diff --git a/src/crplayer.cc b/src/crplayer.cc
index 3205e46..67ff996 100644
--- a/src/crplayer.cc
+++ b/src/crplayer.cc
@@ -19,6 +19,355 @@ static store<TPlayerIndexLeafNode, 100> PlayerIndexLeafNodes;
// TPlayer
// =============================================================================
+TPlayer::TPlayer(TConnection *Connection, uint32 CharacterID):
+ TCreature(),
+ AttackedPlayers(0, 10, 10),
+ FormerAttackedPlayers(0, 10, 10)
+{
+ this->Type = PLAYER;
+ this->LoseInventory = LOSE_INVENTORY_SOME;
+ this->Profession = PROFESSION_NONE;
+ this->AccountID = 0;
+ this->Guild[0] = 0;
+ this->Rank[0] = 0;
+ this->Title[0] = 0;
+ this->IPAddress[0] = 0;
+ this->Depot = NONE;
+ this->DepotNr = 0;
+ this->DepotSpace = 0;
+ this->ConstructError = NOERROR;
+ this->PlayerData = NULL;
+ this->TradeObject = NONE;
+ this->TradePartner = 0;
+ this->TradeAccepted = false;
+ this->OldState = 0;
+ this->Request = 0;
+ this->RequestTimestamp = 0;
+ this->RequestProcessingGamemaster = 0;
+ this->TutorActivities = 0;
+ this->NumberOfAttackedPlayers = 0;
+ this->Aggressor = false;
+ this->NumberOfFormerAttackedPlayers = 0;
+ this->FormerAggressor = false;
+ this->FormerLogoutRound = 0;
+ this->PartyLeader = 0;
+ this->PartyLeavingRound = 0;
+ this->TalkBufferFullTime = 0;
+ this->MutingEndRound = 0;
+ this->NumberOfMutings = 0;
+
+ memset(this->Rights, 0, sizeof(this->Rights));
+
+ for(int SpellNr = 0;
+ SpellNr < NARRAY(this->SpellList);
+ SpellNr += 1){
+ this->SpellList[SpellNr] = 0;
+ }
+
+ for(int QuestNr = 0;
+ QuestNr < NARRAY(this->QuestValues);
+ QuestNr += 1){
+ this->QuestValues[QuestNr] = 0;
+ }
+
+ for(int ContainerNr = 0;
+ ContainerNr < NARRAY(this->OpenContainer);
+ ContainerNr += 1){
+ this->OpenContainer[ContainerNr] = NONE;
+ }
+
+ STATIC_ASSERT(NARRAY(this->Addressees) == NARRAY(this->AddresseesTimes));
+ for(int AddresseeNr = 0;
+ AddresseeNr < NARRAY(this->Addressees);
+ AddresseeNr += 1){
+ this->Addressees[AddresseeNr] = 0;
+ this->AddresseesTimes[AddresseeNr] = 0;
+ }
+
+ TPlayerData *Slot = AttachPlayerPoolSlot(CharacterID, false);
+ if(Slot == NULL){
+ error("TPlayer::TPlayer: PlayerData-Slot nicht gefunden.\n");
+ this->ConstructError = ERROR;
+ return;
+ }
+
+ SendMails(Slot);
+
+ this->PlayerData = Slot;
+ this->Connection = Connection;
+ strcpy(this->Name, Slot->Name);
+ this->SetID(CharacterID);
+
+ InsertPlayerIndex(&PlayerIndexHead, 0, this->Name, CharacterID);
+ this->LoadData();
+ this->AccountID = Slot->AccountID;
+ strcpy(this->IPAddress, Connection->GetIPAddress());
+
+ STATIC_ASSERT(sizeof(this->Rights) == sizeof(Slot->Rights));
+ memcpy(this->Rights, Slot->Rights, sizeof(this->Rights));
+
+ this->Sex = Slot->Sex;
+ strcpy(this->Guild, Slot->Guild);
+ strcpy(this->Rank, Slot->Rank);
+ strcpy(this->Title, Slot->Title);
+
+ if(Slot->PlayerkillerEnd < (int)time(NULL)){
+ Slot->PlayerkillerEnd = 0;
+ }
+
+ this->CheckOutfit();
+ this->SetInList();
+
+ // NOTE(fusion): Soul regen. Could be some inlined function `CheckSoul`.
+ {
+ TSkill *Soul = this->Skills[SKILL_SOUL];
+ Soul->Max = (this->GetActivePromotion() ? 200 : 100);
+ Soul->Check();
+
+ // TODO(fusion): We're rounding up to an extra regen cycle here but I'm
+ // not sure it is correct.
+ int Timer = Soul->TimerValue();
+ if(Timer >= 15){
+ int Interval = (this->GetActivePromotion() ? 15 : 120);
+ int Cycle = (Timer + Interval - 1) / Interval;
+ int Count = (Timer + Interval - 1) % Interval;
+ this->SetTimer(SKILL_SOUL, Cycle, Count, Interval, -1);
+ }
+ }
+
+ // TODO(fusion): Handle login after death?
+ if(this->Skills[SKILL_HITPOINTS]->Get() <= 0){
+ for(int SkillNr = 0;
+ SkillNr < NARRAY(this->Skills);
+ SkillNr += 1){
+ this->DelTimer(SkillNr);
+ this->Skills[SkillNr]->SetMDAct(0);
+ 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->Outfit = this->OrgOutfit;
+ this->posx = this->startx;
+ this->posy = this->starty;
+ this->posz = this->startz;
+ }
+
+ if(Slot->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;
+ this->Skills[SKILL_LEVEL]->LastLevel = 100;
+ this->Skills[SKILL_LEVEL]->NextLevel = 200;
+ }
+
+ if(CoordinateFlag(this->posx, this->posy, this->posz, BED)){
+ this->Regenerate();
+ }
+
+ uint16 HouseID = GetHouseID(this->posx, this->posy, this->posz);
+ if(HouseID != 0
+ && !IsInvited(HouseID, this, Slot->LastLogoutTime)
+ && !CheckRight(CharacterID, ENTER_HOUSES)){
+ GetExitPosition(HouseID, &this->posx, &this->posy, &this->posz);
+ }
+
+ if(!CheckRight(CharacterID, PREMIUM_ACCOUNT)){
+ if(IsPremiumArea(this->startx, this->starty, this->startz)){
+ Log("game", "Spieler %s wird aus PayArea-Stadt ausgebürgert und erhält neue Heimatstadt.\n", this->Name);
+ GetStartPosition(&this->startx, &this->starty, &this->startz, (this->Profession == PROFESSION_NONE));
+ }
+
+ if(IsPremiumArea(this->posx, this->posy, this->posz)){
+ Log("game", "Spieler %s wird aus PayArea geworfen und in seine Heimatstadt gesetzt.\n", this->Name);
+ this->posx = this->startx;
+ this->posy = this->starty;
+ this->posz = this->startz;
+ }
+ }else{
+ Log("game", "Spieler besitzt Premium Account.\n");
+ }
+
+ this->SetOnMap();
+ Connection->EnterGame();
+ SendInitGame(Connection, CharacterID);
+ SendRights(Connection);
+ SendFullScreen(Connection);
+ GraphicalEffect(this->CrObject, EFFECT_ENERGY);
+ this->LoadInventory(Slot->LastLoginTime == 0);
+ this->NotifyChangeInventory();
+ SendAmbiente(Connection);
+ AnnounceChangedCreature(CharacterID, CREATURE_LIGHT_CHANGED);
+ SendPlayerSkills(Connection);
+ this->CheckState();
+ this->SendBuddies();
+
+ if(Slot->LastLoginTime != 0){
+ char TimeString[100];
+ struct tm LastLogin = GetLocalTimeTM(Slot->LastLoginTime);
+ strftime(TimeString, sizeof(TimeString), "%d. %b %Y %X %Z", &LastLogin);
+ SendMessage(Connection, TALK_LOGIN_MESSAGE,
+ "Your last visit in Tibia: %s.", TimeString);
+ }else if(!CheckRight(this->ID, GAMEMASTER_OUTFIT)){
+ Log("game", "Spieler %s loggt zum ersten Mal ein -> Outfitwahl.\n", this->Name);
+ SendMessage(Connection, TALK_LOGIN_MESSAGE,
+ "Welcome to Tibia! Please choose your outfit.");
+ SendOutfit(Connection);
+ }
+
+ Slot->LastLoginTime = time(NULL);
+}
+
+TPlayer::~TPlayer(void){
+ LogoutOrder(this);
+ if(this->ConstructError != NOERROR){
+ this->DelInList();
+ return;
+ }
+
+ ASSERT(this->PlayerData);
+ TPlayerData *Slot = this->PlayerData;
+ Slot->LastLogoutTime = time(NULL);
+ this->SaveData();
+
+ if(!this->IsDead){
+ Log("game", "Spieler %s loggt aus.\n", this->Name);
+ GraphicalEffect(this->posx, this->posy, this->posz, EFFECT_POFF);
+ this->SaveInventory();
+ }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;
+
+ bool ResetCharacter = false;
+ if(this->Profession != PROFESSION_NONE && this->Skills[SKILL_LEVEL]->Get() <= 5){
+ Log("game", "Setze Spieler %s komplett zurück wegen Level.\n", this->Name);
+ ResetCharacter = true;
+ }else if(this->Skills[SKILL_HITPOINTS]->Max <= 0){
+ Log("game", "Setze Spieler %s komplett zurück wegen MaxHitpoints.\n", this->Name);
+ ResetCharacter = true;
+ }
+
+ 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;
+
+ for(int SpellNr = 0;
+ SpellNr < NARRAY(Slot->SpellList);
+ SpellNr += 1){
+ Slot->SpellList[SpellNr] = 0;
+ }
+
+ for(int QuestNr = 0;
+ QuestNr < NARRAY(Slot->QuestValues);
+ QuestNr += 1){
+ Slot->QuestValues[QuestNr] = 0;
+ }
+
+ // TODO(fusion): This one looks sketchy.
+ for(int SkillNr = 0;
+ SkillNr < NARRAY(Slot->Minimum);
+ SkillNr += 1){
+ Slot->Minimum[SkillNr] = INT_MIN;
+ }
+
+ this->LoseInventory = LOSE_INVENTORY_ALL;
+ }
+
+ if(Slot->PlayerkillerEnd != 0){
+ this->LoseInventory = LOSE_INVENTORY_ALL;
+ }
+
+ if(CheckRight(this->ID, KEEP_INVENTORY)){
+ this->LoseInventory = LOSE_INVENTORY_NONE;
+ }
+ }
+
+ if(CheckRight(this->ID, READ_GAMEMASTER_CHANNEL)){
+ 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;
+ }
+
+ LeaveAllChannels(this->ID);
+
+ if(this->GetPartyLeader(false) != 0){
+ ::LeaveParty(this->ID, true);
+ }
+
+ this->ClearPlayerkillingMarks();
+ this->DelInList();
+
+ Slot->Dirty = true;
+ // TODO(fusion): Something is telling me that `Slot->Sticky` is also poorly managed.
+ DecreasePlayerPoolSlotSticky(Slot);
+ ReleasePlayerPoolSlot(Slot);
+}
+
+void TPlayer::SetInList(void){
+ this->SetInCrList();
+
+ PlayerMutex.down();
+ *PlayerList.at(FirstFreePlayer) = this;
+ FirstFreePlayer += 1;
+ PlayerMutex.up();
+
+ NotifyBuddies(this->ID, this->Name, true);
+ IncrementPlayersOnline();
+ if(this->Profession == PROFESSION_NONE){
+ IncrementNewbiesOnline();
+ }
+}
+
+void TPlayer::DelInList(void){
+ NotifyBuddies(this->ID, this->Name, false);
+
+ for(int Index = 0; Index < FirstFreePlayer; Index += 1){
+ if(*PlayerList.at(Index) == this){
+ // TODO(fusion): This can't be right? If the player at `Index` changes
+ // before entering the critical section, we could end up removing the
+ // wrong player from the list..
+ PlayerMutex.down();
+ FirstFreePlayer -= 1;
+ *PlayerList.at(Index) = *PlayerList.at(FirstFreePlayer);
+ *PlayerList.at(FirstFreePlayer) = NULL;
+ PlayerMutex.up();
+
+ DecrementPlayersOnline();
+ if(this->Profession == PROFESSION_NONE){
+ DecrementNewbiesOnline();
+ }
+
+ break;
+ }
+ }
+}
+
uint8 TPlayer::GetRealProfession(void){
return this->Profession;
}
@@ -202,8 +551,10 @@ void CloseProcessedRequests(uint32 CharacterID){
continue;
}
- SendCloseRequest(Player->Connection);
- Player->Request = 0;
+ if(Player->Request != 0 && Player->RequestProcessingGamemaster == CharacterID){
+ SendCloseRequest(Player->Connection);
+ Player->Request = 0;
+ }
}
}
@@ -930,8 +1281,8 @@ void InitPlayerIndex(void){
// be hardcoded.
uint32 CharacterIDs[10000];
char Names[10000][30];
- TQueryManagerConnection *QueryManager = new TQueryManagerConnection(360007);
- if(!QueryManager->isConnected()){
+ TQueryManagerConnection QueryManager(360007);
+ if(!QueryManager.isConnected()){
error("InitPlayerIndex: Kann nicht zum Query-Manager verbinden.\n");
return;
}
@@ -939,7 +1290,7 @@ void InitPlayerIndex(void){
int MinimumCharacterID = 0;
while(true){
int NumberOfPlayers;
- int Ret = QueryManager->loadPlayers(MinimumCharacterID,
+ int Ret = QueryManager.loadPlayers(MinimumCharacterID,
&NumberOfPlayers, Names, CharacterIDs);
if(Ret != 0){
error("InitPlayerIndex: Kann Spielerdaten nicht ermitteln.\n");
@@ -956,8 +1307,6 @@ void InitPlayerIndex(void){
MinimumCharacterID = CharacterIDs[9999] + 1;
}
-
- delete QueryManager;
}
void ExitPlayerIndex(void){
diff --git a/src/operate.cc b/src/operate.cc
index 18829a3..7dc1fef 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -5,7 +5,6 @@
#include "stubs.hh"
#include <dirent.h>
-#include <time.h>
static fifo<TStatement> Statements(1024);
static fifo<TListener> Listeners(1024);
diff --git a/src/stubs.hh b/src/stubs.hh
index 719f88d..9c251ef 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -23,24 +23,20 @@ extern void CleanHouseField(int x, int y, int z);
extern void ConvinceMonster(TCreature *Master, TCreature *Slave);
extern void ChallengeMonster(TCreature *Challenger, TCreature *Monster);
extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect);
-extern void CreatePlayerList(bool Online);
-extern uint32 GetCharacterID(const char *Name);
-extern const char *GetCharacterName(const char *Name);
+extern void DeleteGamemasterRequest(const char *Name);
extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z);
extern TConnection *GetFirstConnection(void);
extern TConnection *GetNextConnection(void);
extern const char *GetHouseName(uint16 HouseID);
extern const char *GetHouseOwner(uint16 HouseID);
-extern TPlayer *GetPlayer(uint32 CreatureID);
-extern void GetProfessionName(char *Buffer, int Profession, bool Article, bool Capitals);
-extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player);
extern void InitLog(const char *ProtocolName);
+extern bool IsInvited(uint16 HouseID, TPlayer *Player, int TimeStamp);
extern void KickGuest(uint16 HouseID, TPlayer *Host, TPlayer *Guest);
extern void KillStatisticsOrder(int NumberOfRaces, const char *RaceNames, int *KilledPlayers, int *KilledCreatures);
extern bool LagDetected(void);
extern void LoadSectorOrder(int SectorX, int SectorY, int SectorZ);
extern void Log(const char *ProtocolName, const char *Text, ...) ATTR_PRINTF(2, 3);
-extern void LogoutAllPlayers(void);
+extern void LogoutOrder(TPlayer *Player);
extern void NetLoadCheck(void);
extern void NetLoadSummary(void);
extern void PrepareHouseCleanup(void);
@@ -80,8 +76,12 @@ extern void SendChangeInContainer(TConnection *Connection, int ContainerNr, Obje
extern void SendDeleteInventory(TConnection *Connection, int Position);
extern void SendSetInventory(TConnection *Connection, int Position, Object Obj);
extern void SendEditList(TConnection *Connection, uint8 ListType, uint32 ID, const char *Text);
+extern void SendFinishRequest(TConnection *Connection, const char *Name);
extern void SendFullScreen(TConnection *Connection);
extern void SendFloors(TConnection *Connection, bool Up);
+extern void SendInitGame(TConnection *Connection, uint32 CharacterID);
+extern void SendRights(TConnection *Connection);
+extern void SendOutfit(TConnection *Connection);
extern void SendGraphicalEffect(TConnection *Connection, int x, int y, int z, int Type);
extern void SendTextualEffect(TConnection *Connection, int x, int y, int z, int Color, const char *Text);
extern void SendMissileEffect(TConnection *Connection, int OrigX, int OrigY, int OrigZ, int DestX, int DestY, int DestZ, int Type);
diff --git a/src/time.cc b/src/time.cc
index 0003c39..ad42c47 100644
--- a/src/time.cc
+++ b/src/time.cc
@@ -1,7 +1,5 @@
#include "common.hh"
-#include <time.h>
-
// IMPORTANT(fusion): `RoundNr` is just the number of seconds since startup which
// is why `GetRoundAtTime` and `GetRoundForNextMinute` straight up uses it as
// seconds. It is incremented every 1 second inside `AdvanceGame`.
@@ -12,12 +10,12 @@ uint32 ServerMilliseconds = 0;
// NOTE(fusion): This isn't strictly required because each server process is
// single threaded and don't share static memory, which is what the result of
// the regular `localtime` function uses.
-static struct tm GetLocalTimeTM(time_t timer){
+struct tm GetLocalTimeTM(time_t t){
struct tm result;
#if COMPILER_MSVC
- localtime_s(&result, &timer);
+ localtime_s(&result, &t);
#else
- localtime_r(&timer, &result);
+ localtime_r(&t, &result);
#endif
return result;
}