aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md1
-rw-r--r--reference/enums.hh10
-rw-r--r--reference/game.c735
-rw-r--r--src/cr.hh2
-rw-r--r--src/crplayer.cc506
-rw-r--r--src/main.cc6
-rw-r--r--src/operate.hh14
7 files changed, 523 insertions, 751 deletions
diff --git a/TODO.md b/TODO.md
index 896d08d..ab216b8 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,5 +1,4 @@
## TODO NEXT
-- DBFUNCS.CC
- QUERY.CC
- Include `x == 0xFFFF` inside `CheckVisibility`?
diff --git a/reference/enums.hh b/reference/enums.hh
deleted file mode 100644
index 47d5196..0000000
--- a/reference/enums.hh
+++ /dev/null
@@ -1,10 +0,0 @@
-enum CHANNEL: int {
- GUILD_CHANNEL=0,
- GAMEMASTER_CHANNEL=1,
- TUTOR_CHANNEL=2,
- REQUEST_QUEUE=3,
- GAME_CHANNEL=4,
- TRADE_CHANNEL=5,
- REALLIFE_CHANNEL=6,
- HELP_CHANNEL=7
-};
diff --git a/reference/game.c b/reference/game.c
index 955fb2a..db75c28 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -1,738 +1,3 @@
-// DBFUNCS.CC -> PLAYERLOADER.CC ?
-//==============================================================================
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void PlayerDataPath(void)
-
-{
- uint in_stack_00000004;
- char *in_stack_0000000c;
-
- sprintf(in_stack_0000000c,"%s/%02ld/%ld.%s",USERPATH,in_stack_00000004 % 100);
- return;
-}
-
-
-
-bool PlayerDataExists(ulong CharacterID)
-
-{
- bool bVar1;
- char local_100c [4];
- char FileName [4096];
-
- sprintf(local_100c,"%s/%02ld/%ld.%s",USERPATH,CharacterID % 100,CharacterID,&DAT_080f6560);
- bVar1 = FileExists(local_100c);
- return bVar1;
-}
-
-
-
-// WARNING: Removing unreachable block (ram,0x0806d081)
-// WARNING: Removing unreachable block (ram,0x0806d0da)
-// WARNING: Removing unreachable block (ram,0x0806d08b)
-// WARNING: Removing unreachable block (ram,0x0806d095)
-// WARNING: Removing unreachable block (ram,0x0806d0c7)
-// WARNING: Removing unreachable block (ram,0x0806d0a0)
-
-bool LoadPlayerData(TPlayerData *Slot)
-
-{
- bool bVar1;
- char cVar2;
- int SkillNr;
- int iVar3;
- uint uVar4;
- int iVar5;
- uchar *puVar6;
- anon_union_4_2_730cd3ca_for_TOutfit_2 *paVar7;
- int DepotNr;
- int SkillNr_2;
- int *piVar8;
- char *pcVar9;
- undefined1 uVar10;
- char *pcVar11;
- undefined1 auStack_500c [3];
- bool FileOk;
- TReadScriptFile Script;
- undefined1 local_102c [4];
- TDynamicWriteBuffer HelpBuffer;
- char FileName [4096];
-
- if (Slot == (TPlayerData *)0x0) {
- pcVar11 = "LoadPlayerData: Slot ist NULL.\n";
- }
- else {
- uVar4 = Slot->CharacterID;
- if (uVar4 != 0) {
- piVar8 = &HelpBuffer.super_TWriteBuffer.Position;
- pcVar11 = USERPATH;
- sprintf((char *)piVar8,"%s/%02ld/%ld.%s",USERPATH,uVar4 % 100,uVar4,&DAT_080f6560);
- bVar1 = FileExists((char *)piVar8);
- if (!bVar1) {
- Slot->Race = 1;
- iVar3 = 0;
- Slot->Profession = 0;
- (Slot->OriginalOutfit).OutfitID = 0;
- (Slot->OriginalOutfit).field_1 = (anon_union_4_2_730cd3ca_for_TOutfit_2)0x0;
- (Slot->CurrentOutfit).OutfitID = 0;
- (Slot->CurrentOutfit).field_1 = (anon_union_4_2_730cd3ca_for_TOutfit_2)0x0;
- Slot->LastLoginTime = 0;
- Slot->LastLogoutTime = 0;
- Slot->startx = 0;
- Slot->starty = 0;
- Slot->startz = 0;
- Slot->posx = 0;
- Slot->posy = 0;
- Slot->posz = 0;
- Slot->PlayerkillerEnd = 0;
- do {
- Slot->Minimum[iVar3] = -0x80000000;
- iVar3 = iVar3 + 1;
- } while (iVar3 < 0x19);
- puVar6 = Slot->SpellList;
- for (iVar3 = 0x40; iVar3 != 0; iVar3 = iVar3 + -1) {
- puVar6[0] = '\0';
- puVar6[1] = '\0';
- puVar6[2] = '\0';
- puVar6[3] = '\0';
- puVar6 = puVar6 + 4;
- }
- uVar4 = 2000;
- piVar8 = Slot->QuestValues;
- if (((uint)piVar8 & 4) != 0) {
- piVar8 = Slot->QuestValues + 1;
- uVar4 = 0x7cc;
- Slot->QuestValues[0] = 0;
- }
- for (uVar4 = uVar4 >> 2; uVar4 != 0; uVar4 = uVar4 - 1) {
- *piVar8 = 0;
- piVar8 = piVar8 + 1;
- }
- Slot->MurderTimestamps[0] = 0;
- Slot->MurderTimestamps[1] = 0;
- Slot->MurderTimestamps[2] = 0;
- Slot->MurderTimestamps[3] = 0;
- Slot->MurderTimestamps[4] = 0;
- Slot->MurderTimestamps[5] = 0;
- Slot->MurderTimestamps[6] = 0;
- Slot->MurderTimestamps[8] = 0;
- Slot->MurderTimestamps[9] = 0;
- Slot->MurderTimestamps[10] = 0;
- Slot->MurderTimestamps[0xb] = 0;
- Slot->MurderTimestamps[0xc] = 0;
- Slot->MurderTimestamps[7] = 0;
- Slot->MurderTimestamps[0xd] = 0;
- Slot->MurderTimestamps[0xe] = 0;
- Slot->MurderTimestamps[0xf] = 0;
- Slot->MurderTimestamps[0x10] = 0;
- Slot->InventorySize = 0;
- iVar3 = 0;
- Slot->MurderTimestamps[0x11] = 0;
- Slot->MurderTimestamps[0x12] = 0;
- Slot->MurderTimestamps[0x13] = 0;
- Slot->Inventory = (uchar *)0x0;
- do {
- Slot->Depot[iVar3] = (uchar *)0x0;
- Slot->DepotSize[iVar3] = 0;
- iVar3 = iVar3 + 1;
- } while (iVar3 < 9);
- return true;
- }
- TDynamicWriteBuffer::TDynamicWriteBuffer((TDynamicWriteBuffer *)local_102c,0x4000);
- // try { // try from 0806c499 to 0806c49d has its CatchHandler @ 0806d1cf
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)auStack_500c);
- // try { // try from 0806c4ab to 0806c5b3 has its CatchHandler @ 0806d1c6
- TReadScriptFile::open((TReadScriptFile *)auStack_500c,(char *)piVar8,(int)pcVar11);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- pcVar11 = TReadScriptFile::readString((TReadScriptFile *)auStack_500c);
- strcpy(Slot->Name,pcVar11);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Race = iVar3;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Profession = iVar3;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- // try { // try from 0806c5c8 to 0806c626 has its CatchHandler @ 0806d12c
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'(');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- (Slot->OriginalOutfit).OutfitID = iVar3;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- if ((Slot->OriginalOutfit).OutfitID == 0) {
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- (Slot->OriginalOutfit).field_1.ObjectType = (ushort)iVar3;
- }
- else {
- // try { // try from 0806d10d to 0806d111 has its CatchHandler @ 0806d12c
- paVar7 = (anon_union_4_2_730cd3ca_for_TOutfit_2 *)
- TReadScriptFile::readBytesequence((TReadScriptFile *)auStack_500c);
- (Slot->OriginalOutfit).field_1 = *paVar7;
- }
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,')');
- // try { // try from 0806c630 to 0806c64a has its CatchHandler @ 0806d1c6
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- // try { // try from 0806c65f to 0806c6bd has its CatchHandler @ 0806d12c
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'(');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- (Slot->CurrentOutfit).OutfitID = iVar3;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- if ((Slot->CurrentOutfit).OutfitID == 0) {
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- (Slot->CurrentOutfit).field_1.ObjectType = (ushort)iVar3;
- }
- else {
- // try { // try from 0806d0f5 to 0806d0f9 has its CatchHandler @ 0806d12c
- paVar7 = (anon_union_4_2_730cd3ca_for_TOutfit_2 *)
- TReadScriptFile::readBytesequence((TReadScriptFile *)auStack_500c);
- (Slot->CurrentOutfit).field_1 = *paVar7;
- }
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,')');
- // try { // try from 0806c6c7 to 0806d062 has its CatchHandler @ 0806d1c6
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->LastLoginTime = iVar3;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->LastLogoutTime = iVar3;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readCoordinate((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readCoordinate((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->PlayerkillerEnd = iVar3;
- iVar3 = 0;
- do {
- Slot->Minimum[iVar3] = -0x80000000;
- iVar3 = iVar3 + 1;
- uVar10 = iVar3 == 0x18;
- } while (iVar3 < 0x19);
- do {
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- pcVar11 = TReadScriptFile::getIdentifier((TReadScriptFile *)auStack_500c);
- iVar3 = 6;
- pcVar9 = "skill";
- do {
- if (iVar3 == 0) break;
- iVar3 = iVar3 + -1;
- uVar10 = *pcVar11 == *pcVar9;
- pcVar11 = pcVar11 + 1;
- pcVar9 = pcVar9 + 1;
- } while ((bool)uVar10);
- if (!(bool)uVar10) goto LAB_0806cb0a;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'(');
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- bVar1 = false;
- if ((-1 < iVar3) && (iVar3 < 0x19)) {
- bVar1 = true;
- }
- uVar10 = !bVar1;
- if ((bool)uVar10) {
- TReadScriptFile::error((TReadScriptFile *)auStack_500c,"illegal skill number");
- }
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Actual[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Maximum[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Minimum[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->DeltaAct[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->MagicDeltaAct[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Cycle[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->MaxCycle[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Count[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->MaxCount[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->AddLevel[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Experience[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->FactorPercent[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->NextLevel[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->Delta[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,')');
- } while( true );
- }
- pcVar11 = &DAT_080f6720;
- }
- error(pcVar11);
- return false;
-LAB_0806cb0a:
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'{');
-LAB_0806cb3b:
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c != SPECIAL) goto LAB_0806cb7f;
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 != '}') goto code_r0x0806cb64;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'{');
- while( true ) {
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c != SPECIAL) goto LAB_0806cc5a;
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 == '}') break;
- if (_auStack_500c != SPECIAL) goto LAB_0806cc5a;
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 != ',') {
- if ((_auStack_500c != SPECIAL) ||
- (cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c), cVar2 != '('))
- {
-LAB_0806cc5a:
- TReadScriptFile::error((TReadScriptFile *)auStack_500c,"\'(\' expected");
- }
- iVar3 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- bVar1 = false;
- if ((-1 < iVar3) && (iVar3 < 500)) {
- bVar1 = true;
- }
- if (!bVar1) {
- TReadScriptFile::error((TReadScriptFile *)auStack_500c,"illegal quest number");
- }
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,',');
- iVar5 = TReadScriptFile::readNumber((TReadScriptFile *)auStack_500c);
- Slot->QuestValues[iVar3] = iVar5;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,')');
- }
- }
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'{');
-LAB_0806cd45:
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c != SPECIAL) goto LAB_0806cd89;
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 != '}') goto code_r0x0806cd6e;
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'{');
- HelpBuffer.super_TWriteBuffer.Size = 0;
-LAB_0806cdfa:
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c != SPECIAL) goto LAB_0806ce42;
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 != '}') goto code_r0x0806ce27;
- TDynamicWriteBuffer::writeByte((TDynamicWriteBuffer *)local_102c,0xff);
- Slot->InventorySize = HelpBuffer.super_TWriteBuffer.Size;
- puVar6 = (uchar *)operator_new__(HelpBuffer.super_TWriteBuffer.Size);
- Slot->Inventory = puVar6;
- memcpy(puVar6,HelpBuffer.super_TWriteBuffer.super_TWriteStream._vptr_TWriteStream,
- Slot->InventorySize);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- pcVar11 = (char *)0x7b;
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'{');
- iVar3 = 0;
- do {
- Slot->Depot[iVar3] = (uchar *)0x0;
- iVar3 = iVar3 + 1;
- } while (iVar3 < 9);
-LAB_0806cf45:
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c == SPECIAL) goto code_r0x0806cf5c;
- goto LAB_0806cf8d;
-code_r0x0806cb64:
- if ((_auStack_500c != SPECIAL) ||
- (cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c), cVar2 != ',')) {
-LAB_0806cb7f:
- iVar3 = TReadScriptFile::getNumber((TReadScriptFile *)auStack_500c);
- bVar1 = false;
- if ((-1 < iVar3) && (iVar3 < 0x100)) {
- bVar1 = true;
- }
- if (!bVar1) {
- TReadScriptFile::error((TReadScriptFile *)auStack_500c,"illegal spell number");
- }
- Slot->SpellList[iVar3] = '\x01';
- }
- goto LAB_0806cb3b;
-code_r0x0806cd6e:
- if ((_auStack_500c != SPECIAL) ||
- (cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c), cVar2 != ',')) {
-LAB_0806cd89:
- iVar3 = 1;
- do {
- Slot->MurderTimestamps[iVar3 + -1] = Slot->MurderTimestamps[iVar3];
- iVar3 = iVar3 + 1;
- } while (iVar3 < 0x14);
- iVar3 = TReadScriptFile::getNumber((TReadScriptFile *)auStack_500c);
- Slot->MurderTimestamps[0x13] = iVar3;
- }
- goto LAB_0806cd45;
-code_r0x0806ce27:
- if ((_auStack_500c != SPECIAL) ||
- (cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c), cVar2 != ',')) {
-LAB_0806ce42:
- iVar3 = TReadScriptFile::getNumber((TReadScriptFile *)auStack_500c);
- TDynamicWriteBuffer::writeByte((TDynamicWriteBuffer *)local_102c,(uchar)iVar3);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- LoadObjects((TReadScriptFile *)auStack_500c,(TWriteStream *)local_102c,false);
- }
- goto LAB_0806cdfa;
-code_r0x0806cf5c:
- cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c);
- if (cVar2 == '}') {
- TReadScriptFile::nextToken((TReadScriptFile *)auStack_500c);
- if (_auStack_500c != ENDOFFILE) {
- pcVar11 = "end of file expected";
- TReadScriptFile::error((TReadScriptFile *)auStack_500c,"end of file expected");
- }
- TReadScriptFile::close((TReadScriptFile *)auStack_500c,(int)pcVar11);
- // try { // try from 0806d073 to 0806d077 has its CatchHandler @ 0806d1cf
- TReadScriptFile::~TReadScriptFile((TReadScriptFile *)auStack_500c,(int)pcVar11);
- TDynamicWriteBuffer::~TDynamicWriteBuffer((TDynamicWriteBuffer *)local_102c,(int)pcVar11);
- return true;
- }
- if ((_auStack_500c != SPECIAL) ||
- (cVar2 = TReadScriptFile::getSpecial((TReadScriptFile *)auStack_500c), cVar2 != ',')) {
-LAB_0806cf8d:
- iVar3 = TReadScriptFile::getNumber((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readIdentifier((TReadScriptFile *)auStack_500c);
- TReadScriptFile::readSymbol((TReadScriptFile *)auStack_500c,'=');
- HelpBuffer.super_TWriteBuffer.Size = 0;
- LoadObjects((TReadScriptFile *)auStack_500c,(TWriteStream *)local_102c,false);
- Slot->DepotSize[iVar3] = HelpBuffer.super_TWriteBuffer.Size;
- puVar6 = (uchar *)operator_new__(HelpBuffer.super_TWriteBuffer.Size);
- Slot->Depot[iVar3] = puVar6;
- pcVar11 = (char *)HelpBuffer.super_TWriteBuffer.super_TWriteStream;
- memcpy(puVar6,HelpBuffer.super_TWriteBuffer.super_TWriteStream._vptr_TWriteStream,
- Slot->DepotSize[iVar3]);
- }
- goto LAB_0806cf45;
-}
-
-
-
-void SavePlayerData(TPlayerData *Slot)
-
-{
- uint uVar1;
- bool bVar2;
- bool FirstSpell;
- byte bVar3;
- time_t tVar4;
- int Number;
- int SpellNr;
- int *piVar5;
- int Limitation;
- int iVar6;
- char *pcVar7;
- undefined *__fd;
- undefined1 local_203c;
- bool FirstDepot;
- bool FirstPosition;
- bool FirstMurder;
- TReadBuffer Buffer;
- TWriteScriptFile Script;
- char local_101c [4];
- char FileName [4096];
-
- if (Slot == (TPlayerData *)0x0) {
- pcVar7 = "SavePlayerData: Slot ist NULL.\n";
- }
- else {
- uVar1 = Slot->CharacterID;
- if (uVar1 != 0) {
- pcVar7 = USERPATH;
- sprintf(local_101c,"%s/%02ld/%ld.%s",USERPATH,uVar1 % 100,uVar1,&DAT_080f6560);
- // try { // try from 0806d29e to 0806d2a2 has its CatchHandler @ 0806de36
- TWriteScriptFile::TWriteScriptFile((TWriteScriptFile *)&Buffer.Position);
- // try { // try from 0806d2b6 to 0806d3b6 has its CatchHandler @ 0806de30
- TWriteScriptFile::open((TWriteScriptFile *)&Buffer.Position,local_101c,(int)pcVar7);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"ID = ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Slot->CharacterID);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Name = ");
- TWriteScriptFile::writeString((TWriteScriptFile *)&Buffer.Position,Slot->Name);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Race = ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Slot->Race);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Profession = ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Slot->Profession);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"OriginalOutfit = ");
- // try { // try from 0806d3cb to 0806d431 has its CatchHandler @ 0806ddc3
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"(");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,(Slot->OriginalOutfit).OutfitID);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- if ((Slot->OriginalOutfit).OutfitID == 0) {
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,
- (uint)(Slot->OriginalOutfit).field_1.ObjectType);
- }
- else {
- // try { // try from 0806ddad to 0806ddb1 has its CatchHandler @ 0806ddc3
- TWriteScriptFile::writeBytesequence
- ((TWriteScriptFile *)&Buffer.Position,
- (Slot->OriginalOutfit).field_1.Colors,4);
- }
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,")");
- // try { // try from 0806d43b to 0806d455 has its CatchHandler @ 0806de30
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"CurrentOutfit = ");
- // try { // try from 0806d46a to 0806d4d0 has its CatchHandler @ 0806ddc3
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"(");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,(Slot->CurrentOutfit).OutfitID);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- if ((Slot->CurrentOutfit).OutfitID == 0) {
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,
- (uint)(Slot->CurrentOutfit).field_1.ObjectType);
- }
- else {
- // try { // try from 0806dd8b to 0806dd8f has its CatchHandler @ 0806ddc3
- TWriteScriptFile::writeBytesequence
- ((TWriteScriptFile *)&Buffer.Position,(Slot->CurrentOutfit).field_1.Colors
- ,4);
- }
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,")");
- // try { // try from 0806d4da to 0806dd20 has its CatchHandler @ 0806de30
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"LastLogin = ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Slot->LastLoginTime);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"LastLogout = ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Slot->LastLogoutTime)
- ;
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"StartPosition = ");
- TWriteScriptFile::writeCoordinate
- ((TWriteScriptFile *)&Buffer.Position,Slot->startx,Slot->starty,Slot->startz);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"CurrentPosition = ");
- TWriteScriptFile::writeCoordinate
- ((TWriteScriptFile *)&Buffer.Position,Slot->posx,Slot->posy,Slot->posz);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"PlayerkillerEnd = ");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,Slot->PlayerkillerEnd);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- iVar6 = 0;
- piVar5 = Slot->Delta;
- do {
- if (piVar5[-0x113] != -0x80000000) {
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Skill = (");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,iVar6);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x145]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,piVar5[-300])
- ;
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x113]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0xfa]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0xe1]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,piVar5[-200])
- ;
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0xaf]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x96]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x7d]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,piVar5[-100])
- ;
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x4b]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x32]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,piVar5[-0x19]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,*piVar5);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,")");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- }
- iVar6 = iVar6 + 1;
- piVar5 = piVar5 + 1;
- } while (iVar6 < 0x19);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Spells = {");
- bVar2 = true;
- iVar6 = 0;
- do {
- if (Slot->SpellList[iVar6] != '\0') {
- if (!bVar2) {
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- }
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,iVar6);
- bVar2 = false;
- }
- iVar6 = iVar6 + 1;
- } while (iVar6 < 0x100);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"}");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"QuestValues = {");
- bVar2 = true;
- iVar6 = 0;
- do {
- if (Slot->QuestValues[iVar6] != 0) {
- if (!bVar2) {
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- }
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"(");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,iVar6);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeNumber
- ((TWriteScriptFile *)&Buffer.Position,Slot->QuestValues[iVar6]);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,")");
- bVar2 = false;
- }
- iVar6 = iVar6 + 1;
- } while (iVar6 < 500);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"}");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Murders = {");
- bVar2 = true;
- iVar6 = 0;
- tVar4 = time((time_t *)0x0);
- do {
- Number = Slot->MurderTimestamps[iVar6];
- if (tVar4 + -0x278d00 < Number) {
- if (!bVar2) {
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- Number = Slot->MurderTimestamps[iVar6];
- }
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,Number);
- bVar2 = false;
- }
- iVar6 = iVar6 + 1;
- } while (iVar6 < 0x14);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"}");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Inventory = {");
- if (Slot->Inventory != (uchar *)0x0) {
- TReadBuffer::TReadBuffer
- ((TReadBuffer *)&local_203c,Slot->Inventory,Slot->InventorySize);
- bVar2 = true;
- while (bVar3 = TReadBuffer::readByte((TReadBuffer *)&local_203c), bVar3 != 0xff) {
- if (bVar2) {
- bVar2 = false;
- }
- else {
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,",");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText
- ((TWriteScriptFile *)&Buffer.Position," ");
- }
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,(uint)bVar3);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position," Content=");
- SaveObjects((TReadStream *)&local_203c,(TWriteScriptFile *)&Buffer.Position);
- }
- }
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"}");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"Depots = {");
- bVar2 = true;
- iVar6 = 0;
- do {
- if (Slot->Depot[iVar6] != (uchar *)0x0) {
- if (bVar2) {
- bVar2 = false;
- }
- else {
- // try { // try from 0806dd45 to 0806dd6d has its CatchHandler @ 0806de30
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,", ");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::writeText
- ((TWriteScriptFile *)&Buffer.Position," ");
- }
- TWriteScriptFile::writeNumber((TWriteScriptFile *)&Buffer.Position,iVar6);
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position," Content=");
- TReadBuffer::TReadBuffer
- ((TReadBuffer *)&local_203c,Slot->Depot[iVar6],Slot->DepotSize[iVar6])
- ;
- SaveObjects((TReadStream *)&local_203c,(TWriteScriptFile *)&Buffer.Position);
- }
- iVar6 = iVar6 + 1;
- } while (iVar6 < 9);
- __fd = &DAT_080f2aa0;
- TWriteScriptFile::writeText((TWriteScriptFile *)&Buffer.Position,"}");
- TWriteScriptFile::writeLn((TWriteScriptFile *)&Buffer.Position);
- TWriteScriptFile::close((TWriteScriptFile *)&Buffer.Position,(int)__fd);
- // try { // try from 0806dd2a to 0806dd2e has its CatchHandler @ 0806de36
- TWriteScriptFile::~TWriteScriptFile((TWriteScriptFile *)&Buffer.Position,(int)__fd);
- return;
- }
- pcVar7 = &DAT_080f6800;
- }
- error(pcVar7);
- return;
-}
-
-
-
-void UnlinkPlayerData(ulong CharacterID)
-
-{
- char local_100c [4];
- char FileName [4096];
-
- sprintf(local_100c,"%s/%02ld/%ld.%s",USERPATH,CharacterID % 100,CharacterID,&DAT_080f6560);
- unlink(local_100c);
- return;
-}
-
// QUERY.CC
//==============================================================================
diff --git a/src/cr.hh b/src/cr.hh
index e095903..0848d42 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -956,7 +956,7 @@ int GetRaceSummonCost(int Race);
int GetRacePoison(int Race);
bool GetRaceUnpushable(int Race);
TOutfit ReadOutfit(TReadScriptFile *Script);
-void WriteOutfit(TReadScriptFile *Script, TOutfit Outfit);
+void WriteOutfit(TWriteScriptFile *Script, TOutfit Outfit);
void LoadRace(const char *FileName);
void LoadRaces(void);
diff --git a/src/crplayer.cc b/src/crplayer.cc
index b8e1926..a53e676 100644
--- a/src/crplayer.cc
+++ b/src/crplayer.cc
@@ -2104,6 +2104,512 @@ void SendExistingRequests(TConnection *Connection){
delete []Players;
}
+// Player Loader
+// =============================================================================
+void PlayerDataPath(char *Buffer, int BufferSize, uint32 CharacterID){
+ snprintf(Buffer, BufferSize, "%s/%02u/%u.usr",
+ USERPATH, (CharacterID % 100), CharacterID);
+}
+
+bool PlayerDataExists(uint32 CharacterID){
+ char FileName[4096];
+ PlayerDataPath(FileName, sizeof(FileName), CharacterID);
+ return FileExists(FileName);
+}
+
+bool LoadPlayerData(TPlayerData *Slot){
+ if(Slot == NULL){
+ error("LoadPlayerData: Slot ist NULL.\n");
+ return false;
+ }
+
+ if(Slot->CharacterID == 0){
+ error("LoadPlayerData: Slot enthält keinen Charakter.\n");
+ return false;
+ }
+
+ // IMPORTANT(fusion): This function is only called from `AssignPlayerPoolSlot`
+ // which zero initializes it before hand. Note that it would be a problem
+ // otherwise, since we shouldn't write to `CharacterID`, `Locked`, or `Sticky`
+ // outside a critical section, making `memset` not viable and turning this
+ // into an assignment fiesta for no good reason.
+ Slot->Race = 1;
+ Slot->Profession = PROFESSION_NONE;
+ for(int SkillNr = 0;
+ SkillNr < NARRAY(Slot->Minimum);
+ SkillNr += 1){
+ // NOTE(fusion): See `TPlayer::LoadData`.
+ Slot->Minimum[SkillNr] = INT_MIN;
+ }
+
+ // NOTE(fusion): First login. Use defaults.
+ char FileName[4096];
+ PlayerDataPath(FileName, sizeof(FileName), Slot->CharacterID);
+ if(!FileExists(FileName)){
+ return true;
+ }
+
+ bool Result = false;
+ try{
+ // TODO(fusion): Same thing as house loaders. Data is expected to be in
+ // an exact order and we don't check identifiers
+ TDynamicWriteBuffer HelpBuffer(KB(16));
+ TReadScriptFile Script;
+ Script.open(FileName);
+
+ Script.readIdentifier(); // "id"
+ Script.readSymbol('=');
+ Script.readNumber();
+
+ Script.readIdentifier(); // "name"
+ Script.readSymbol('=');
+ strcpy(Slot->Name, Script.readString());
+
+ Script.readIdentifier(); // "race"
+ Script.readSymbol('=');
+ Slot->Race = Script.readNumber();
+
+ Script.readIdentifier(); // "profession"
+ Script.readSymbol('=');
+ Slot->Profession = (uint8)Script.readNumber();
+
+ Script.readIdentifier(); // "originaloutfit"
+ Script.readSymbol('=');
+ Slot->OriginalOutfit = ReadOutfit(&Script);
+
+ Script.readIdentifier(); // "currentoutfit"
+ Script.readSymbol('=');
+ Slot->CurrentOutfit = ReadOutfit(&Script);
+
+ Script.readIdentifier(); // "lastlogin"
+ Script.readSymbol('=');
+ Slot->LastLoginTime = (time_t)Script.readNumber();
+
+ Script.readIdentifier(); // "lastlogout"
+ Script.readSymbol('=');
+ Slot->LastLogoutTime = (time_t)Script.readNumber();
+
+ Script.readIdentifier(); // "startposition"
+ Script.readSymbol('=');
+ Script.readCoordinate(&Slot->startx, &Slot->starty, &Slot->startz);
+
+ Script.readIdentifier(); // "currentposition"
+ Script.readSymbol('=');
+ Script.readCoordinate(&Slot->posx, &Slot->posy, &Slot->posz);
+
+ Script.readIdentifier(); // "playerkillerend"
+ Script.readSymbol('=');
+ Slot->PlayerkillerEnd = Script.readNumber();
+
+ while(strcmp(Script.readIdentifier(), "skill") == 0){
+ Script.readSymbol('=');
+ Script.readSymbol('(');
+ int SkillNr = Script.readNumber();
+ if(SkillNr < 0 || SkillNr >= NARRAY(Slot->Minimum)){
+ Script.error("illegal skill number");
+ }
+ Script.readSymbol(',');
+ Slot->Actual[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Maximum[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Minimum[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->DeltaAct[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->MagicDeltaAct[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Cycle[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->MaxCycle[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Count[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->MaxCount[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->AddLevel[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Experience[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->FactorPercent[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->NextLevel[SkillNr] = Script.readNumber();
+ Script.readSymbol(',');
+ Slot->Delta[SkillNr] = Script.readNumber();
+ Script.readSymbol(')');
+ }
+
+ // "spells", already primed in the loop condition above
+ Script.readSymbol('=');
+ Script.readSymbol('{');
+ while(true){
+ Script.nextToken();
+ if(Script.Token == SPECIAL){
+ if(Script.getSpecial() == '}'){
+ break;
+ }else if(Script.getSpecial() == ','){
+ continue;
+ }
+ }
+
+ int SpellNr = Script.getNumber();
+ if(SpellNr < 0 || SpellNr >= NARRAY(Slot->SpellList)){
+ Script.error("illegal spell number");
+ }
+
+ Slot->SpellList[SpellNr] = 1;
+ }
+
+ Script.readIdentifier(); // "questvalues"
+ Script.readSymbol('=');
+ Script.readSymbol('{');
+ while(true){
+ char Special = Script.readSpecial();
+ if(Special == '}'){
+ break;
+ }else if(Special == ','){
+ continue;
+ }else if(Special != '('){
+ Script.error("'(' expected");
+ }
+
+ int QuestNr = Script.readNumber();
+ if(QuestNr < 0 || QuestNr >= NARRAY(Slot->QuestValues)){
+ Script.error("illegal quest number");
+ }
+ Script.readSymbol(',');
+ Slot->QuestValues[QuestNr] = Script.readNumber();
+ Script.readSymbol(')');
+ }
+
+ Script.readIdentifier(); // "murders"
+ Script.readSymbol('=');
+ Script.readSymbol('{');
+ while(true){
+ Script.nextToken();
+ if(Script.Token == SPECIAL){
+ if(Script.getSpecial() == '}'){
+ break;
+ }else if(Script.getSpecial() == ','){
+ continue;
+ }
+ }
+
+ for(int i = 1; i < NARRAY(Slot->MurderTimestamps); i += 1){
+ Slot->MurderTimestamps[i - 1] = Slot->MurderTimestamps[i];
+ }
+
+ Slot->MurderTimestamps[NARRAY(Slot->MurderTimestamps) - 1] = Script.getNumber();
+ }
+
+ HelpBuffer.Position = 0;
+ Script.readIdentifier(); // "inventory"
+ Script.readSymbol('=');
+ Script.readSymbol('{');
+ while(true){
+ Script.nextToken();
+ if(Script.Token == SPECIAL){
+ if(Script.getSpecial() == '}'){
+ break;
+ }else if(Script.getSpecial() == ','){
+ continue;
+ }
+ }
+
+ int Position = Script.readNumber();
+ if(Position < INVENTORY_FIRST || Position > INVENTORY_LAST){
+ Script.error("illegal inventory position");
+ }
+
+ Script.readIdentifier(); // "content"
+ Script.readSymbol('=');
+ HelpBuffer.writeByte((uint8)Position);
+ LoadObjects(&Script, &HelpBuffer, false);
+ }
+ HelpBuffer.writeByte(0xFF);
+ Slot->Inventory = new uint8[HelpBuffer.Position];
+ Slot->InventorySize = HelpBuffer.Position;
+ memcpy(Slot->Inventory, HelpBuffer.Data, HelpBuffer.Position);
+
+ Script.readIdentifier(); // "depots"
+ Script.readSymbol('=');
+ Script.readSymbol('{');
+ while(true){
+ Script.nextToken();
+ if(Script.Token == SPECIAL){
+ if(Script.getSpecial() == '}'){
+ break;
+ }else if(Script.getSpecial() == ','){
+ continue;
+ }
+ }
+
+ int DepotNr = Script.readNumber();
+ if(DepotNr < 0 || DepotNr >= NARRAY(Slot->Depot)){
+ Script.error("illegal depot number");
+ }
+
+ Script.readIdentifier(); // "content"
+ Script.readSymbol('=');
+ HelpBuffer.Position = 0;
+ LoadObjects(&Script, &HelpBuffer, false);
+ Slot->Depot[DepotNr] = new uint8[HelpBuffer.Position];
+ Slot->DepotSize[DepotNr] = HelpBuffer.Position;
+ memcpy(Slot->Depot[DepotNr], HelpBuffer.Data, HelpBuffer.Position);
+ }
+
+ Script.nextToken();
+ if(Script.Token != ENDOFFILE){
+ Script.error("end of file expected");
+ }
+
+ Result = true;
+ }catch(const char *str){
+ error("LoadPlayerData: Kann Gegenstände des Spielers %u nicht laden.\n",
+ Slot->CharacterID);
+ error("# Fehler: %s\n", str);
+ }catch(const std::bad_alloc &e){
+ error("LoadPlayerData: Kein Speicher frei beim Laden von Spieler %u.\n",
+ Slot->CharacterID);
+ }
+
+ if(!Result){
+ delete[] Slot->Inventory;
+ Slot->Inventory = NULL;
+ Slot->InventorySize = 0;
+
+ for(int DepotNr = 0;
+ DepotNr < NARRAY(Slot->Depot);
+ DepotNr += 1){
+ delete[] Slot->Depot[DepotNr];
+ Slot->Depot[DepotNr] = NULL;
+ Slot->DepotSize[DepotNr] = 0;
+ }
+ }
+
+ return Result;
+}
+
+void SavePlayerData(TPlayerData *Slot){
+ if(Slot == NULL){
+ error("SavePlayerData: Slot ist NULL.\n");
+ return;
+ }
+
+ if(Slot->CharacterID == 0){
+ error("SavePlayerData: Slot enthält keinen Charakter.\n");
+ return;
+ }
+
+ // TODO(fusion): This is prone to problems if we don't backup user files.
+ // Even if we did automatic backups, would only this user get rolled back?
+ // This is probably one of the sources of whole day rollbacks.
+ char FileName[4096];
+ PlayerDataPath(FileName, sizeof(FileName), Slot->CharacterID);
+ try{
+ TWriteScriptFile Script;
+ Script.open(FileName);
+
+ Script.writeText("ID = ");
+ Script.writeNumber(Slot->CharacterID);
+ Script.writeLn();
+
+ Script.writeText("Name = ");
+ Script.writeString(Slot->Name);
+ Script.writeLn();
+
+ Script.writeText("Race = ");
+ Script.writeNumber(Slot->Race);
+ Script.writeLn();
+
+ Script.writeText("Profession = ");
+ Script.writeNumber(Slot->Profession);
+ Script.writeLn();
+
+ Script.writeText("OriginalOutfit = ");
+ WriteOutfit(&Script, Slot->OriginalOutfit);
+ Script.writeLn();
+
+ Script.writeText("CurrentOutfit = ");
+ WriteOutfit(&Script, Slot->CurrentOutfit);
+ Script.writeLn();
+
+ Script.writeText("LastLogin = ");
+ Script.writeNumber((int)Slot->LastLoginTime);
+ Script.writeLn();
+
+ Script.writeText("LastLogout = ");
+ Script.writeNumber((int)Slot->LastLogoutTime);
+ Script.writeLn();
+
+ Script.writeText("StartPosition = ");
+ Script.writeCoordinate(Slot->startx, Slot->starty, Slot->startz);
+ Script.writeLn();
+
+ Script.writeText("CurrentPosition = ");
+ Script.writeCoordinate(Slot->posx, Slot->posy, Slot->posz);
+ Script.writeLn();
+
+ Script.writeText("PlayerkillerEnd = ");
+ Script.writeNumber(Slot->PlayerkillerEnd);
+ Script.writeLn();
+ Script.writeLn();
+
+ for(int SkillNr = 0;
+ SkillNr < NARRAY(Slot->Minimum);
+ SkillNr += 1){
+ if(Slot->Minimum[SkillNr] == INT_MIN){
+ continue;
+ }
+
+ Script.writeText("Skill = (");
+ Script.writeNumber(SkillNr);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Actual[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Maximum[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Minimum[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->DeltaAct[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->MagicDeltaAct[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Cycle[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->MaxCycle[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Count[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->MaxCount[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->AddLevel[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Experience[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->FactorPercent[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->NextLevel[SkillNr]);
+ Script.writeText(",");
+ Script.writeNumber(Slot->Delta[SkillNr]);
+ Script.writeText(")");
+ Script.writeLn();
+ }
+ Script.writeLn();
+
+ bool FirstSpell = true;
+ Script.writeText("Spells = {");
+ for(int SpellNr = 0;
+ SpellNr < NARRAY(Slot->SpellList);
+ SpellNr += 1){
+ if(Slot->SpellList[SpellNr] != 0){
+ if(!FirstSpell){
+ Script.writeText(",");
+ }
+ Script.writeNumber(SpellNr);
+ FirstSpell = false;
+ }
+ }
+ Script.writeText("}");
+ Script.writeLn();
+
+ bool FirstQuest = true;
+ Script.writeText("QuestValues = {");
+ for(int QuestNr = 0;
+ QuestNr < NARRAY(Slot->QuestValues);
+ QuestNr += 1){
+ if(Slot->QuestValues[QuestNr] != 0){
+ if(!FirstQuest){
+ Script.writeText(",");
+ }
+ Script.writeText("(");
+ Script.writeNumber(QuestNr);
+ Script.writeText(",");
+ Script.writeNumber(Slot->QuestValues[QuestNr]);
+ Script.writeText(")");
+ FirstQuest = false;
+ }
+ }
+ Script.writeText("}");
+ Script.writeLn();
+
+ bool FirstMurder = true;
+ int Now = (int)time(NULL);
+ Script.writeText("Murders = {");
+ for(int i = 0; i < NARRAY(Slot->MurderTimestamps); i += 1){
+ // NOTE(fusion): Save murder timestamps for up to a month.
+ if((Now - Slot->MurderTimestamps[i]) < (30 * 24 * 60 * 60)){
+ if(FirstMurder){
+ Script.writeText(",");
+ }
+ Script.writeNumber(Slot->MurderTimestamps[i]);
+ FirstMurder = false;
+ }
+ }
+ Script.writeText("}");
+ Script.writeLn();
+ Script.writeLn();
+
+ bool FirstPosition = true;
+ Script.writeText("Inventory = {");
+ if(Slot->Inventory != NULL){
+ TReadBuffer Buffer(Slot->Inventory, Slot->InventorySize);
+ while(true){
+ int Position = (int)Buffer.readByte();
+ if(Position == 0xFF){
+ break;
+ }
+
+ if(FirstPosition){
+ Script.writeText(",");
+ Script.writeLn();
+ Script.writeText(" ");
+ }
+ Script.writeNumber(Position);
+ Script.writeText(" Content=");
+ SaveObjects(&Buffer, &Script);
+ FirstPosition = false;
+ }
+ }
+ Script.writeText("}");
+ Script.writeLn();
+ Script.writeLn();
+
+ bool FirstDepot = true;
+ Script.writeText("Depots = {");
+ for(int DepotNr = 0;
+ DepotNr < NARRAY(Slot->Depot);
+ DepotNr += 1){
+ if(Slot->Depot[DepotNr] != NULL){
+ TReadBuffer Buffer(Slot->Depot[DepotNr], Slot->DepotSize[DepotNr]);
+ if(FirstDepot){
+ Script.writeText(",");
+ Script.writeLn();
+ Script.writeText(" ");
+ }
+ Script.writeNumber(DepotNr);
+ Script.writeText(" Content=");
+ SaveObjects(&Buffer, &Script);
+ FirstDepot = false;
+ }
+ }
+ Script.writeText("}");
+ Script.writeLn();
+ Script.close();
+
+ }catch(const char *str){
+ error("SavePlayerData: Kann Gegenstände des Spielers %u nicht schreiben.\n", Slot->CharacterID);
+ error("# Fehler: %s\n", str);
+ unlink(FileName);
+ }
+}
+
+void UnlinkPlayerData(uint32 CharacterID){
+ char FileName[4096];
+ PlayerDataPath(FileName, sizeof(FileName), CharacterID);
+ unlink(FileName);
+}
+
// Player Pool
// =============================================================================
void SavePlayerPoolSlot(TPlayerData *Slot){
diff --git a/src/main.cc b/src/main.cc
index 43137bc..92e7e73 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -227,7 +227,7 @@ static void InitAll(void){
InitCommunication();
InitStrings();
InitWriter();
- //InitReader();
+ InitReader();
InitObjects();
InitMap();
InitInfo();
@@ -244,8 +244,6 @@ static void InitAll(void){
}
static void ExitAll(void){
- // TODO(fusion): Probably missing some inlined empty `Exit*` functions here.
-
EndGame();
ExitTime();
ExitCr();
@@ -255,7 +253,7 @@ static void ExitAll(void){
ExitHouses();
ExitMap(SaveMapOn);
ExitObjects();
- //ExitReader();
+ ExitReader();
ExitWriter();
ExitStrings();
ExitCommunication();
diff --git a/src/operate.hh b/src/operate.hh
index 6d55416..ca7062d 100644
--- a/src/operate.hh
+++ b/src/operate.hh
@@ -37,6 +37,20 @@ enum : int {
CHANNEL_LAST = 0xFFFF,
};
+#if 0
+// TODO(fusion): Use the original channel enum instead of the one above?
+enum CHANNEL: int {
+ GUILD_CHANNEL = 0,
+ GAMEMASTER_CHANNEL = 1,
+ TUTOR_CHANNEL = 2,
+ REQUEST_QUEUE = 3,
+ GAME_CHANNEL = 4,
+ TRADE_CHANNEL = 5,
+ REALLIFE_CHANNEL = 6,
+ HELP_CHANNEL = 7,
+};
+#endif
+
struct TChannel {
TChannel(void);