aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-05-24 20:57:24 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-05-24 20:57:24 -0300
commit3f557369c7bbd08fdf2e6dbd9271873b20a9a144 (patch)
tree28bb9b4ad9c0324036d753eea772855a180c37f3
parentb7432b4e74284138f1740f4577b9cb32e1f120d0 (diff)
downloadgame-3f557369c7bbd08fdf2e6dbd9271873b20a9a144.tar.gz
game-3f557369c7bbd08fdf2e6dbd9271873b20a9a144.zip
halfway of `map.cc` and start of `objects.cc`
-rw-r--r--TODO.md6
-rw-r--r--reference/enums.hh21
-rw-r--r--reference/game.c3167
-rw-r--r--reference/types.hh38
-rw-r--r--src/common.hh5
-rw-r--r--src/config.cc12
-rw-r--r--src/crcombat.cc31
-rw-r--r--src/creature.cc50
-rw-r--r--src/creature.hh2
-rw-r--r--src/enums.hh21
-rw-r--r--src/main.cc5
-rw-r--r--src/map.cc1418
-rw-r--r--src/map.hh75
-rw-r--r--src/objects.cc196
-rw-r--r--src/objects.hh73
-rw-r--r--src/script.hh2
16 files changed, 1870 insertions, 3252 deletions
diff --git a/TODO.md b/TODO.md
index bf2c2ae..ec487dc 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,4 +1,7 @@
## TODO NEXT
+- MAP.CC
+- OBJECTS.CC
+- STRINGS.CC
- TCreature
- TPlayer
- TNonPlayer
@@ -9,6 +12,7 @@ The decompiled file has ~115K lines of C. If we take ~15K lines to be rubbish, t
## TODO AFTER FIRST PASS
- Trim some rough edges.
- Avoid unsafe libc functions like `strcpy`, `strncpy`, `strcat`, `sprintf` etc...
-- Handle connections inline with `poll` (probably?).
+- Handle connections inline with `poll`/`epoll` (probably?).
+- Remove exceptions.
- Review signal usage for timing (SIGALRM, etc...).
- Support Windows.
diff --git a/reference/enums.hh b/reference/enums.hh
index abbed3d..5e045f3 100644
--- a/reference/enums.hh
+++ b/reference/enums.hh
@@ -85,27 +85,6 @@ enum ConditionType: int {
CONDITION_RANDOM=25
};
-enum INSTANCEATTRIBUTE: int {
- CONTENT=0,
- CHESTQUESTNUMBER=1,
- AMOUNT=2,
- KEYNUMBER=3,
- KEYHOLENUMBER=4,
- DOORLEVEL=5,
- DOORQUESTNUMBER=6,
- DOORQUESTVALUE=7,
- CHARGES=8,
- TEXTSTRING=9,
- EDITOR=10,
- CONTAINERLIQUIDTYPE=11,
- POOLLIQUIDTYPE=12,
- ABSTELEPORTDESTINATION=13,
- RESPONSIBLE=14,
- REMAININGEXPIRETIME=15,
- SAVEDEXPIRETIME=16,
- REMAININGUSES=17
-};
-
enum SPECIALMEANING: int {
MONEY_ONE=1,
MONEY_HUNDRED=2,
diff --git a/reference/game.c b/reference/game.c
index 1df63aa..1a48631 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -4965,173 +4965,6 @@ bool ObjectTypeExists(uchar Group,uchar Number)
return (bool)((byte)~(byte)((uint)NewType[CONCAT11(Group,Number)] >> 0x18) >> 7);
}
-
-
-// DWARF original prototype: void setTypeID(ObjectType * this, int _TypeID)
-
-void __thiscall ObjectType::setTypeID(ObjectType *this,int _TypeID)
-
-{
- bool bVar1;
-
- bVar1 = false;
- if ((ObjectTypes.min <= _TypeID) && (_TypeID <= ObjectTypes.max)) {
- bVar1 = true;
- }
- if (!bVar1) {
- error(&DAT_080f0a80,_TypeID);
- _TypeID = 0;
- }
- this->TypeID = _TypeID;
- return;
-}
-
-
-
-// DWARF original prototype: char * getName(ObjectType * this, int Count)
-
-char * __thiscall ObjectType::getName(ObjectType *this)
-
-{
- char *pcVar1;
- TObjectType *pTVar2;
- int in_stack_00000008;
- char local_4c [4];
- char ObjectName [50];
-
- local_4c[0] = '\0';
- if (this->TypeID == 99) {
- error("ObjectType::getName: Der Kreaturtyp hat keinen Namen.\n");
- pcVar1 = (char *)0x0;
- }
- else {
- pTVar2 = vector<>::operator()(&ObjectTypes,this->TypeID);
- if (pTVar2->Name != (char *)0x0) {
- strcpy(local_4c,pTVar2->Name);
- }
- pcVar1 = Plural(local_4c,in_stack_00000008);
- }
- return pcVar1;
-}
-
-
-
-// DWARF original prototype: char * getDescription(ObjectType * this)
-
-char * __thiscall ObjectType::getDescription(ObjectType *this)
-
-{
- TObjectType *pTVar1;
-
- pTVar1 = vector<>::operator()(&ObjectTypes,this->TypeID);
- return pTVar1->Description;
-}
-
-
-
-// DWARF original prototype: bool getFlag(ObjectType * this, FLAG Flag)
-
-bool __thiscall ObjectType::getFlag(ObjectType *this,FLAG Flag)
-
-{
- uint uVar1;
- TObjectType *pTVar2;
- FLAG FVar3;
- uchar b;
-
- FVar3 = Flag + USEEVENT;
- if (-1 < (int)Flag) {
- FVar3 = Flag;
- }
- uVar1 = 1 << ((char)Flag + (char)((int)FVar3 >> 3) * -8 & 0x1fU);
- pTVar2 = vector<>::operator()(&ObjectTypes,this->TypeID);
- return (uint)(pTVar2->Flags[(int)FVar3 >> 3] & (byte)uVar1) == (uVar1 & 0xff);
-}
-
-
-
-// DWARF original prototype: ulong getAttribute(ObjectType * this, TYPEATTRIBUTE Attribute)
-
-ulong __thiscall ObjectType::getAttribute(ObjectType *this,TYPEATTRIBUTE Attribute)
-
-{
- FLAG FVar1;
- uint uVar2;
- TObjectType *pTVar3;
- ulong uVar4;
- FLAG FVar5;
- uchar b;
-
- FVar1 = TypeAttributeFlags[Attribute];
- FVar5 = FVar1 + USEEVENT;
- if (-1 < (int)FVar1) {
- FVar5 = FVar1;
- }
- uVar2 = 1 << ((char)FVar1 + (char)((int)FVar5 >> 3) * -8 & 0x1fU);
- pTVar3 = vector<>::operator()(&ObjectTypes,this->TypeID);
- if ((uint)(pTVar3->Flags[(int)FVar5 >> 3] & (byte)uVar2) == (uVar2 & 0xff)) {
- pTVar3 = vector<>::operator()(&ObjectTypes,this->TypeID);
- uVar4 = pTVar3->Attributes[Attribute];
- }
- else {
- error(&DAT_080f0c60,this->TypeID,TypeAttributeFlags[Attribute],Attribute);
- uVar4 = 0;
- }
- return uVar4;
-}
-
-
-
-// DWARF original prototype: int getAttributeOffset(ObjectType * this, INSTANCEATTRIBUTE Attribute)
-
-int __thiscall ObjectType::getAttributeOffset(ObjectType *this,INSTANCEATTRIBUTE Attribute)
-
-{
- FLAG FVar1;
- uint uVar2;
- TObjectType *pTVar3;
- int iVar4;
- FLAG FVar5;
- uchar b;
-
- FVar1 = InstanceAttributeFlags[Attribute];
- FVar5 = FVar1 + USEEVENT;
- if (-1 < (int)FVar1) {
- FVar5 = FVar1;
- }
- uVar2 = 1 << ((char)FVar1 + (char)((int)FVar5 >> 3) * -8 & 0x1fU);
- pTVar3 = vector<>::operator()(&ObjectTypes,this->TypeID);
- if ((uint)(pTVar3->Flags[(int)FVar5 >> 3] & (byte)uVar2) == (uVar2 & 0xff)) {
-LAB_08055e2a:
- pTVar3 = vector<>::operator()(&ObjectTypes,this->TypeID);
- iVar4 = pTVar3->AttributeOffsets[Attribute];
- }
- else {
- if (Attribute == CONTENT) {
- pTVar3 = vector<>::operator()(&ObjectTypes,this->TypeID);
- if ((pTVar3->Flags[0] & 0x20) != 0) goto LAB_08055e2a;
- }
- iVar4 = -1;
- }
- return iVar4;
-}
-
-
-
-bool ObjectTypeExists(int TypeID)
-
-{
- bool bVar1;
-
- bVar1 = false;
- if ((ObjectTypes.min <= TypeID) && (TypeID <= ObjectTypes.max)) {
- bVar1 = true;
- }
- return bVar1;
-}
-
-
-
ObjectType GetSpecialObject(SPECIALMEANING Meaning)
{
@@ -5359,334 +5192,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-
-
-TObject * AccessObject(Object *Obj)
-
-{
- TObject *pTVar1;
- ulong Position;
- uint uVar2;
-
- if (Obj->ObjectID == NONE.ObjectID) {
- error(&DAT_080f1200);
- pTVar1 = (TObject *)*HashTableData;
- }
- else {
- uVar2 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar2] == '\x02') {
- UnswapSector(HashTableData[uVar2]);
- }
- if ((HashTableType[uVar2] != '\x01') ||
- (pTVar1 = (TObject *)HashTableData[uVar2], pTVar1->ObjectID != Obj->ObjectID)) {
- pTVar1 = (TObject *)*HashTableData;
- }
- }
- return pTVar1;
-}
-
-
-
-// DWARF original prototype: bool exists(Object * this)
-
-bool __thiscall Object::exists(Object *this)
-
-{
- bool bVar1;
- ulong Position;
- uint uVar2;
-
- bVar1 = false;
- if (this->ObjectID != 0) {
- uVar2 = this->ObjectID & HashTableMask;
- if (HashTableType[uVar2] == '\x02') {
- UnswapSector(HashTableData[uVar2]);
- }
- if ((HashTableType[uVar2] == '\x01') && (*(ulong *)HashTableData[uVar2] == this->ObjectID))
- {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- return bVar1;
-}
-
-
-
-// DWARF original prototype: ObjectType getObjectType(Object * this)
-
-ObjectType __thiscall Object::getObjectType(Object *this)
-
-{
- TObject *pTVar1;
- ulong *in_stack_00000008;
- Object local_1c [5];
-
- local_1c[0].ObjectID = *in_stack_00000008;
- pTVar1 = AccessObject(local_1c);
- ObjectType::setTypeID((ObjectType *)this,(pTVar1->Type).TypeID);
- return (ObjectType)(int)this;
-}
-
-
-
-// DWARF original prototype: ulong getAttribute(Object * this, INSTANCEATTRIBUTE Attribute)
-
-ulong __thiscall Object::getAttribute(Object *this,INSTANCEATTRIBUTE Attribute)
-
-{
- bool bVar1;
- TObject *pTVar2;
- int iVar3;
- int Offset;
- Object local_3c [4];
- Object local_2c [7];
-
- local_3c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- iVar3 = ObjectType::getAttributeOffset((ObjectType *)local_2c,Attribute);
- if (iVar3 == -1) {
- local_2c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- error(&DAT_080f12a0,Attribute,local_3c[0].ObjectID);
- }
- else {
- bVar1 = false;
- if ((-1 < iVar3) && (iVar3 < 4)) {
- bVar1 = true;
- }
- if (bVar1) {
- local_3c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_3c);
- return pTVar2->Attributes[iVar3];
- }
- local_2c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- error(&DAT_080f1240,iVar3,Attribute,local_3c[0].ObjectID);
- }
- return 0;
-}
-
-
-
-// DWARF original prototype: void setAttribute(Object * this, INSTANCEATTRIBUTE Attribute, ulong
-// Value)
-
-void __thiscall Object::setAttribute(Object *this,INSTANCEATTRIBUTE Attribute,ulong Value)
-
-{
- bool bVar1;
- TObject *pTVar2;
- int iVar3;
- int Offset;
- Object local_3c [4];
- Object local_2c [7];
-
- local_3c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- iVar3 = ObjectType::getAttributeOffset((ObjectType *)local_2c,Attribute);
- if (iVar3 == -1) {
- local_2c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- error(&DAT_080f1360,Attribute,local_3c[0].ObjectID);
- }
- else {
- bVar1 = false;
- if ((-1 < iVar3) && (iVar3 < 4)) {
- bVar1 = true;
- }
- if (bVar1) {
- if (Value == 0) {
- if (((Attribute == AMOUNT) || (Attribute == POOLLIQUIDTYPE)) ||
- (Attribute == CHARGES)) {
- Value = 1;
- }
- if ((Value == 0) && (Attribute == REMAININGUSES)) {
- local_2c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- Value = ObjectType::getAttribute((ObjectType *)local_3c,TOTALUSES);
- }
- }
- local_3c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_3c);
- pTVar2->Attributes[iVar3] = Value;
- }
- else {
- local_2c[0] = (Object)this->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- error(&DAT_080f1300,iVar3,Attribute,local_3c[0].ObjectID);
- }
- }
- return;
-}
-
-
-
-// DWARF original prototype: Object getNextObject(Object * this)
-
-Object __thiscall Object::getNextObject(Object *this)
-
-{
- TObject *pTVar1;
- ulong *in_stack_00000008;
- Object local_1c [5];
-
- local_1c[0].ObjectID = *in_stack_00000008;
- pTVar1 = AccessObject(local_1c);
- this->ObjectID = (pTVar1->NextObject).ObjectID;
- return (Object)(ulong)this;
-}
-
-
-
-// DWARF original prototype: Object getContainer(Object * this)
-
-Object __thiscall Object::getContainer(Object *this)
-
-{
- TObject *pTVar1;
- ulong *in_stack_00000008;
- Object local_1c [5];
-
- local_1c[0].ObjectID = *in_stack_00000008;
- pTVar1 = AccessObject(local_1c);
- this->ObjectID = (pTVar1->Container).ObjectID;
- return (Object)(ulong)this;
-}
-
-
-
-// DWARF original prototype: ulong getCreatureID(Object * this)
-
-ulong __thiscall Object::getCreatureID(Object *this)
-
-{
- TObject *pTVar1;
- ulong uVar2;
- Object local_3c [4];
- ObjectType local_2c [7];
-
- local_3c[0] = (Object)this->ObjectID;
- pTVar1 = AccessObject(local_3c);
- ObjectType::setTypeID(local_2c,(pTVar1->Type).TypeID);
- if (local_2c[0].TypeID == 99) {
- local_3c[0] = (Object)this->ObjectID;
- pTVar1 = AccessObject(local_3c);
- uVar2 = pTVar1->Attributes[1];
- }
- else {
- error("Object::getCreatureID: Objekt ist keine Kreatur.\n");
- uVar2 = 0;
- }
- return uVar2;
-}
-
-
-
-void GetObjectCoordinates(Object *Obj,int *x,int *y,int *z)
-
-{
- bool bVar1;
- TObject *pTVar2;
- ulong Position;
- uint uVar3;
- Object local_4c [4];
- Object local_3c [4];
- ObjectType local_2c [7];
-
- bVar1 = false;
- if (Obj->ObjectID != 0) {
- uVar3 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar3] == '\x02') {
- UnswapSector(HashTableData[uVar3]);
- }
- if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- while( true ) {
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID(local_2c,(pTVar2->Type).TypeID);
- if (local_2c[0].TypeID == 0) break;
- local_4c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_4c);
- local_2c[0].TypeID = (pTVar2->Container).ObjectID;
- Obj->ObjectID = local_2c[0].TypeID;
- }
- local_4c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_4c);
- *x = pTVar2->Attributes[1];
- local_4c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_4c);
- *y = pTVar2->Attributes[2];
- local_4c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_4c);
- *z = (uint)(byte)pTVar2->Attributes[3];
- }
- else {
- error(&DAT_080f1400);
- *x = 0;
- *y = 0;
- *z = 0;
- }
- return;
-}
-
-
-
-uchar GetMapContainerFlags(Object *Obj)
-
-{
- bool bVar1;
- TObject *pTVar2;
- ulong Position;
- uint uVar3;
- Object local_3c [4];
- ObjectType local_2c [7];
-
- bVar1 = false;
- if (Obj->ObjectID != 0) {
- uVar3 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar3] == '\x02') {
- UnswapSector(HashTableData[uVar3]);
- }
- if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID(local_2c,(pTVar2->Type).TypeID);
- if (local_2c[0].TypeID == 0) {
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- return *(uchar *)((int)pTVar2->Attributes + 0xd);
- }
- }
- error("GetMapContainerFlags: Objekt ist kein MapContainer.\n");
- return '\0';
-}
-
-
-
void CronMove(int Destination,int Source)
{
@@ -6339,164 +5844,6 @@ void MoveObject(Object *Obj,Object *Con)
}
-
-void ChangeObject(Object *Obj,ObjectType *Type)
-
-{
- bool bVar1;
- TObject *pTVar2;
- ulong uVar3;
- ulong Position;
- uint uVar4;
- ulong *puVar5;
- ulong local_5c;
- ulong SavedExpireTime;
- int Delay;
- ulong local_50;
- ulong Amount;
- Object local_3c [4];
- Object local_2c [7];
-
- bVar1 = false;
- local_5c = 0;
- SavedExpireTime = 0xffffffff;
- local_50 = 0;
- if (Obj->ObjectID != 0) {
- uVar4 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar4] == '\x02') {
- UnswapSector(HashTableData[uVar4]);
- }
- if ((HashTableType[uVar4] == '\x01') && (*(ulong *)HashTableData[uVar4] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- ObjectType::setTypeID((ObjectType *)local_3c,0);
- if (local_2c[0].ObjectID != local_3c[0].ObjectID) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CUMULATIVE);
- if (bVar1) {
- local_50 = Object::getAttribute(Obj,AMOUNT);
- }
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,EXPIRE);
- if (bVar1) {
- local_3c[0] = (Object)Obj->ObjectID;
- local_5c = CronStop(local_3c);
- bVar1 = ObjectType::getFlag(Type,CUMULATIVE);
- if (bVar1) {
- local_50 = 1;
- }
- }
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,TEXT);
- if (bVar1) {
- bVar1 = ObjectType::getFlag(Type,TEXT);
- if (!bVar1) {
- uVar3 = Object::getAttribute(Obj,TEXTSTRING);
- DeleteDynamicString(uVar3);
- Object::setAttribute(Obj,TEXTSTRING,0);
- uVar3 = Object::getAttribute(Obj,EDITOR);
- DeleteDynamicString(uVar3);
- Object::setAttribute(Obj,EDITOR,0);
- }
- }
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,EXPIRESTOP);
- if (bVar1) {
- uVar3 = Object::getAttribute(Obj,SAVEDEXPIRETIME);
- if (uVar3 != 0) {
- SavedExpireTime = Object::getAttribute(Obj,SAVEDEXPIRETIME);
- }
- }
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,MAGICFIELD);
- if (bVar1) {
- Object::setAttribute(Obj,RESPONSIBLE,0);
- }
- }
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)&Amount,Type->TypeID);
- ObjectType::setTypeID(&pTVar2->Type,Amount);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)&Amount,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&Amount,CUMULATIVE);
- if (bVar1) {
- Delay = 1;
- puVar5 = (ulong *)&Delay;
- if (local_50 != 0) {
- puVar5 = &local_50;
- }
- Object::setAttribute(Obj,AMOUNT,*puVar5);
- }
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)&Amount,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&Amount,RUNE);
- if (bVar1) {
- uVar3 = Object::getAttribute(Obj,CHARGES);
- if (uVar3 == 0) {
- Object::setAttribute(Obj,CHARGES,1);
- }
- }
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)&Amount,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&Amount,LIQUIDPOOL);
- if (bVar1) {
- uVar3 = Object::getAttribute(Obj,POOLLIQUIDTYPE);
- if (uVar3 == 0) {
- Object::setAttribute(Obj,POOLLIQUIDTYPE,1);
- }
- }
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)&Amount,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&Amount,WEAROUT);
- if (bVar1) {
- uVar3 = Object::getAttribute(Obj,REMAININGUSES);
- if (uVar3 == 0) {
- uVar3 = ObjectType::getAttribute(Type,TOTALUSES);
- Object::setAttribute(Obj,REMAININGUSES,uVar3);
- }
- }
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)&Amount,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&Amount,EXPIRESTOP);
- if (bVar1) {
- Object::setAttribute(Obj,SAVEDEXPIRETIME,local_5c);
- }
- Amount = Obj->ObjectID;
- CronExpire((Object *)&Amount,SavedExpireTime);
- }
- else {
- error(&DAT_080f19c0);
- }
- return;
-}
-
-
-
// WARNING: Variable defined which should be unmapped: Attribute_local
void ChangeObject(Object *Obj,INSTANCEATTRIBUTE Attribute,ulong Value)
@@ -6528,473 +5875,6 @@ void ChangeObject(Object *Obj,INSTANCEATTRIBUTE Attribute,ulong Value)
return;
}
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-TObject * GetFreeObjectSlot(void)
-
-{
- ulong *puVar1;
- TObject *Help;
- TObject *pTVar2;
-
- if (FirstFreeObject == (TObject *)0x0) {
- SwapSector();
- }
- pTVar2 = FirstFreeObject;
- if (FirstFreeObject == (TObject *)0x0) {
- error("GetFreeObjectSlot: Kein freier Platz mehr.\n");
- pTVar2 = (TObject *)0x0;
- }
- else {
- puVar1 = &FirstFreeObject->ObjectID;
- FirstFreeObject = (TObject *)(FirstFreeObject->NextObject).ObjectID;
- *puVar1 = 0;
- (pTVar2->NextObject).ObjectID = 0;
- (pTVar2->Container).ObjectID = 0;
- (pTVar2->Type).TypeID = 0;
- pTVar2->Attributes[0] = 0;
- pTVar2->Attributes[1] = 0;
- pTVar2->Attributes[2] = 0;
- pTVar2->Attributes[3] = 0;
- }
- return pTVar2;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: NewMask
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ResizeHashTable(void)
-
-{
- uint *puVar1;
- size_t __size;
- ulong *puVar2;
- uchar *__s;
- uchar *__ptr;
- int iVar3;
- int i;
- int iVar4;
- ulong nr;
- size_t __size_00;
- uint uVar5;
- uchar *NewType;
- TObject *Entry;
- ulong *NewData;
- int NewMask;
-
- iVar4 = 1;
- __size = HashTableSize * 2;
- __size_00 = HashTableSize << 3;
- error(&DAT_080f1a40,__size);
- puVar2 = (ulong *)malloc(__size_00);
- __s = (uchar *)malloc(__size);
- memset(__s,0,__size);
- *__s = 0xff;
- iVar3 = HashTableSize;
- *puVar2 = *HashTableData;
- __ptr = HashTableType;
- if (1 < iVar3) {
- do {
- if (__ptr[iVar4] != '\0') {
- if (__ptr[iVar4] == '\x02') {
- UnswapSector(HashTableData[iVar4]);
- __ptr = HashTableType;
- }
- if (__ptr[iVar4] == '\x01') {
- puVar1 = (uint *)HashTableData[iVar4];
- uVar5 = __size - 1 & *puVar1;
- __s[uVar5] = '\x01';
- puVar2[uVar5] = (ulong)puVar1;
- iVar3 = HashTableSize;
- }
- else {
- error("ResizeHashTable: Fehler beim Reorganisieren der HashTabelle.\n");
- __ptr = HashTableType;
- iVar3 = HashTableSize;
- }
- }
- iVar4 = iVar4 + 1;
- } while (iVar4 < iVar3);
- }
- free(__ptr);
- free(HashTableData);
- iVar3 = HashTableSize;
- HashTableSize = __size;
- HashTableType = __s;
- HashTableFree = HashTableFree + iVar3;
- HashTableData = puVar2;
- HashTableMask = __size - 1;
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-Object CreateObject(void)
-
-{
- uchar uVar1;
- ulong *puVar2;
- ulong uVar3;
- TObject *Help;
- int iVar4;
- Object OVar5;
- TObject *pTVar6;
- ulong *in_stack_00000004;
-
- iVar4 = HashTableSize;
- if (0x7fffffff < (uint)HashTableSize) {
- iVar4 = HashTableSize + 0xf;
- }
- if (HashTableFree < iVar4 >> 4) {
- ResizeHashTable();
- }
- uVar1 = HashTableType[CreateObject::Iterator & HashTableMask];
- while (uVar1 != '\0') {
- CreateObject::Iterator = CreateObject::Iterator + 1;
- uVar1 = HashTableType[CreateObject::Iterator & HashTableMask];
- }
- if (FirstFreeObject == (TObject *)0x0) {
- SwapSector();
- }
- pTVar6 = FirstFreeObject;
- if (FirstFreeObject == (TObject *)0x0) {
- pTVar6 = (TObject *)0x0;
- error("GetFreeObjectSlot: Kein freier Platz mehr.\n");
- }
- else {
- puVar2 = &FirstFreeObject->ObjectID;
- FirstFreeObject = (TObject *)(FirstFreeObject->NextObject).ObjectID;
- *puVar2 = 0;
- (pTVar6->NextObject).ObjectID = 0;
- (pTVar6->Container).ObjectID = 0;
- (pTVar6->Type).TypeID = 0;
- pTVar6->Attributes[0] = 0;
- pTVar6->Attributes[1] = 0;
- pTVar6->Attributes[2] = 0;
- pTVar6->Attributes[3] = 0;
- }
- uVar3 = HashTableMask;
- iVar4 = CreateObject::Iterator;
- if (pTVar6 == (TObject *)0x0) {
- error("CreateObject: Kann Objekt nicht anlegen.\n");
- OVar5 = NONE;
- }
- else {
- pTVar6->ObjectID = CreateObject::Iterator;
- HashTableData[iVar4 & uVar3] = (ulong)pTVar6;
- HashTableType[iVar4 & HashTableMask] = '\x01';
- HashTableFree = HashTableFree + -1;
- IncrementObjectCounter();
- OVar5.ObjectID = CreateObject::Iterator;
- }
- *in_stack_00000004 = OVar5.ObjectID;
- return (Object)(ulong)in_stack_00000004;
-}
-
-
-
-int GetObjectPriority(Object *Obj)
-
-{
- bool bVar1;
- TObject *pTVar2;
- int iVar3;
- ulong Position;
- uint uVar4;
- Object local_3c [4];
- Object local_2c [7];
-
- bVar1 = false;
- if (Obj->ObjectID != 0) {
- uVar4 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar4] == '\x02') {
- UnswapSector(HashTableData[uVar4]);
- }
- if ((HashTableType[uVar4] == '\x01') && (*(ulong *)HashTableData[uVar4] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- local_3c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,BANK);
- iVar3 = 0;
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CLIP);
- iVar3 = 1;
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,BOTTOM);
- iVar3 = 2;
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,TOP);
- iVar3 = 3;
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- iVar3 = (local_3c[0].ObjectID != 99) + 4;
- }
- }
- }
- }
- }
- else {
- error(&DAT_080f1b00);
- iVar3 = 0x7fffffff;
- }
- return iVar3;
-}
-
-
-
-void PlaceObject(Object *Obj,Object *Con,bool Append)
-
-{
- bool bVar1;
- TObject *pTVar2;
- int iVar3;
- int iVar4;
- int SearchPriority;
- Object *pAddr;
- uint uVar5;
- Object *pOVar6;
- int ObjPriority;
- char *pcVar7;
- int iStack_78;
- bool Append_local;
- int x;
- int y;
- int z;
- Object local_5c [4];
- Object local_4c [4];
- Object local_3c [4];
- ulong local_2c;
- Object Search;
-
- local_2c = 0;
- bVar1 = false;
- if (Obj->ObjectID != 0) {
- uVar5 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar5] == '\x02') {
- UnswapSector(HashTableData[uVar5]);
- }
- if ((HashTableType[uVar5] == '\x01') && (*(ulong *)HashTableData[uVar5] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (!bVar1) {
- pcVar7 = &DAT_080f1ca0;
-LAB_080595eb:
- error(pcVar7);
- return;
- }
- bVar1 = false;
- if (Con->ObjectID != 0) {
- uVar5 = Con->ObjectID & HashTableMask;
- if (HashTableType[uVar5] == '\x02') {
- UnswapSector(HashTableData[uVar5]);
- }
- if ((HashTableType[uVar5] == '\x01') && (*(ulong *)HashTableData[uVar5] == Con->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (!bVar1) {
- pcVar7 = &DAT_080f1b40;
- goto LAB_080595eb;
- }
- local_4c[0] = (Object)Con->ObjectID;
- pTVar2 = AccessObject(local_4c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CONTAINER);
- if (!bVar1) {
- local_3c[0] = (Object)Con->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_4c,CHEST);
- if (!bVar1) {
- local_3c[0] = (Object)Con->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID);
- error("PlaceObject: Con (%d) ist kein Container.\n",local_4c[0].ObjectID);
- return;
- }
- }
- local_3c[0] = (Object)Con->ObjectID;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_4c,(pTVar2->Type).TypeID);
- if (local_4c[0].ObjectID != 0) {
- z = Con->ObjectID;
- pTVar2 = AccessObject((Object *)&z);
- pOVar6 = (Object *)pTVar2->Attributes;
- local_2c = Object::getAttribute(Con,CONTENT);
- z = local_2c;
- if ((Append) && (z = NONE.ObjectID, local_2c != NONE.ObjectID)) {
- do {
- z = local_2c;
- local_5c[0].ObjectID = NONE.ObjectID;
- pTVar2 = AccessObject((Object *)&z);
- pOVar6 = &pTVar2->NextObject;
- local_4c[0].ObjectID = local_2c;
- pTVar2 = AccessObject(local_4c);
- local_2c = (pTVar2->NextObject).ObjectID;
- z = NONE.ObjectID;
- } while (local_2c != NONE.ObjectID);
- }
- goto LAB_08059780;
- }
- local_4c[0] = (Object)Obj->ObjectID;
- iVar3 = GetObjectPriority(local_4c);
- local_4c[0] = (Object)Con->ObjectID;
- pTVar2 = AccessObject(local_4c);
- pOVar6 = (Object *)pTVar2->Attributes;
- local_5c[0] = (Object)Con->ObjectID;
- z = NONE.ObjectID;
- if (local_5c[0].ObjectID == NONE.ObjectID) {
- error(&DAT_080f1b80);
-LAB_080596ed:
- local_3c[0].ObjectID = NONE.ObjectID;
- }
- else {
- Object::getObjectType((Object *)&z);
- bVar1 = ObjectType::getFlag((ObjectType *)&z,CONTAINER);
- if (!bVar1) {
- Object::getObjectType((Object *)&z);
- bVar1 = ObjectType::getFlag((ObjectType *)&z,CHEST);
- if (!bVar1) {
- Object::getObjectType((Object *)&z);
- error("GetFirstContainerObject: Con (%d) ist kein Container.\n",z);
- goto LAB_080596ed;
- }
- }
- local_3c[0].ObjectID = Object::getAttribute(local_5c,CONTENT);
- }
- z = NONE.ObjectID;
- local_2c = local_3c[0].ObjectID;
- local_4c[0].ObjectID = local_3c[0].ObjectID;
- if (local_3c[0].ObjectID != NONE.ObjectID) {
- do {
- z = local_2c;
- local_5c[0].ObjectID = NONE.ObjectID;
- iVar4 = GetObjectPriority((Object *)&z);
- if (iVar3 < iVar4) break;
- if ((Append) || (1 < iVar4 - 4U)) {
- if ((iVar4 == iVar3) && (((iVar3 == 0 || (iVar3 == 2)) || (iVar3 == 3)))) {
- z = Con->ObjectID;
- GetObjectCoordinates((Object *)&z,&stack0xffffff88,&x,&y);
- local_5c[0].ObjectID = local_2c;
- pTVar2 = AccessObject(local_5c);
- ObjectType::setTypeID((ObjectType *)&z,(pTVar2->Type).TypeID);
- iVar4 = z;
- local_4c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_4c);
- ObjectType::setTypeID((ObjectType *)local_5c,(pTVar2->Type).TypeID);
- if (iVar3 == 0) {
- pcVar7 = "BANK";
- }
- else {
- pcVar7 = "BOTTOM";
- if (iVar3 != 2) {
- pcVar7 = "TOP";
- }
- }
- error("PlaceObject: Zwei %s-Objekte (%d und %d) auf Feld [%d,%d,%d].\n",pcVar7,
- local_5c[0].ObjectID,iVar4,iStack_78,x,y);
- }
- }
- else if (iVar4 == iVar3) break;
- z = local_2c;
- pTVar2 = AccessObject((Object *)&z);
- pOVar6 = &pTVar2->NextObject;
- local_4c[0].ObjectID = local_2c;
- pTVar2 = AccessObject(local_4c);
- local_2c = (pTVar2->NextObject).ObjectID;
- z = NONE.ObjectID;
- } while (local_2c != NONE.ObjectID);
- }
-LAB_08059780:
- local_5c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_5c);
- local_4c[0].ObjectID = local_2c;
- (pTVar2->NextObject).ObjectID = local_2c;
- z = local_2c;
- local_5c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_5c);
- (pTVar2->Container).ObjectID = Con->ObjectID;
- pOVar6->ObjectID = Obj->ObjectID;
- return;
-}
-
-
-
-Object AppendObject(Object *Con,ObjectType *Type)
-
-{
- bool bVar1;
- ulong Position;
- uint uVar2;
- int *in_stack_0000000c;
- Object local_4c [4];
- Object local_3c [4];
- ulong local_2c;
- Object Obj;
-
- bVar1 = false;
- if (Type->TypeID != 0) {
- uVar2 = Type->TypeID & HashTableMask;
- if (HashTableType[uVar2] == '\x02') {
- UnswapSector(HashTableData[uVar2]);
- }
- if ((HashTableType[uVar2] == '\x01') && (*(int *)HashTableData[uVar2] == Type->TypeID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- CreateObject();
- ObjectType::setTypeID((ObjectType *)local_3c,*in_stack_0000000c);
- local_4c[0].ObjectID = local_2c;
- ChangeObject(local_4c,(ObjectType *)local_3c);
- local_4c[0].ObjectID = Type->TypeID;
- local_3c[0].ObjectID = local_2c;
- PlaceObject(local_3c,local_4c,true);
- }
- else {
- error(&DAT_080f1ce0);
- local_2c = NONE.ObjectID;
- }
- Con->ObjectID = local_2c;
- return (Object)(ulong)Con;
-}
-
-
-
Object SetObject(Object *Con,ObjectType *Type,ulong CreatureID)
{
@@ -7169,23 +6049,6 @@ LAB_08059d74:
return (Object)(ulong)Con;
}
-
-
-void PutFreeObjectSlot(TObject *Entry)
-
-{
- if (Entry == (TObject *)0x0) {
- error("PutFreeObjectSlot: Entry ist NULL.\n");
- }
- else {
- (Entry->NextObject).ObjectID = (ulong)FirstFreeObject;
- FirstFreeObject = Entry;
- }
- return;
-}
-
-
-
void CutObject(Object *Obj)
{
@@ -7428,207 +6291,6 @@ void DeleteObject(Object *Obj)
return;
}
-
-
-Object GetMapContainer(int x,int y,int z)
-
-{
- int iVar1;
- bool bVar2;
- bool bVar3;
- matrix3d<TSector*> *pmVar4;
- int sx;
- int iVar5;
- Object OVar6;
- TSector **ppTVar7;
- int sy;
- int iVar8;
- int iVar9;
- int iVar10;
- int iVar11;
- int in_stack_00000010;
-
- pmVar4 = Sector;
- bVar3 = false;
- iVar9 = y + 0x1f;
- iVar11 = z + 0x1f;
- iVar10 = iVar9;
- if (-1 < y) {
- iVar10 = y;
- }
- iVar5 = iVar11;
- if (-1 < z) {
- iVar5 = z;
- }
- bVar2 = false;
- if ((SectorXMin <= iVar10 >> 5) && (bVar2 = true, SectorXMax < iVar10 >> 5)) {
- bVar2 = false;
- }
- if (bVar2) {
- bVar2 = false;
- if (SectorYMin <= iVar5 >> 5) {
- bVar2 = true;
- if (SectorYMax < iVar5 >> 5) {
- bVar2 = false;
- }
- }
- if (((bVar2) && (bVar3 = false, SectorZMin <= in_stack_00000010)) &&
- (bVar3 = true, SectorZMax < in_stack_00000010)) {
- bVar3 = false;
- }
- }
- if (bVar3) {
- iVar10 = iVar9;
- if (-1 < y) {
- iVar10 = y;
- }
- iVar5 = iVar11;
- if (-1 < z) {
- iVar5 = z;
- }
- iVar8 = (iVar5 >> 5) - Sector->ymin;
- iVar5 = in_stack_00000010 - Sector->zmin;
- iVar10 = (iVar10 >> 5) - Sector->xmin;
- if ((((iVar10 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar10)) ||
- ((iVar8 < 0 || ((Sector->dy <= iVar8 || (iVar5 < 0)))))) || (Sector->dz <= iVar5)) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar10 + Sector->xmin,
- iVar8 + Sector->ymin,iVar5 + Sector->zmin);
- ppTVar7 = pmVar4->entry;
- }
- else {
- ppTVar7 = Sector->entry + iVar10 + iVar8 * iVar1 + iVar5 * iVar1 * Sector->dy;
- }
- pmVar4 = Sector;
- OVar6.ObjectID = NONE.ObjectID;
- if (*ppTVar7 != (TSector *)0x0) {
- iVar10 = iVar9;
- if (-1 < y) {
- iVar10 = y;
- }
- iVar5 = iVar11;
- if (-1 < z) {
- iVar5 = z;
- }
- iVar8 = (iVar5 >> 5) - Sector->ymin;
- iVar5 = in_stack_00000010 - Sector->zmin;
- iVar10 = (iVar10 >> 5) - Sector->xmin;
- if (((((iVar10 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar10)) || (iVar8 < 0)) ||
- ((Sector->dy <= iVar8 || (iVar5 < 0)))) || (Sector->dz <= iVar5)) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar10 + Sector->xmin,
- iVar8 + Sector->ymin,iVar5 + Sector->zmin);
- ppTVar7 = pmVar4->entry;
- }
- else {
- ppTVar7 = Sector->entry + iVar10 + iVar8 * iVar1 + iVar5 * iVar1 * Sector->dy;
- }
- (*ppTVar7)->TimeStamp = RoundNr;
- pmVar4 = Sector;
- if (-1 < y) {
- iVar9 = y;
- }
- if (-1 < z) {
- iVar11 = z;
- }
- iVar8 = (iVar11 >> 5) - Sector->ymin;
- iVar10 = in_stack_00000010 - Sector->zmin;
- iVar5 = (iVar9 >> 5) - Sector->xmin;
- if (((iVar5 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar5)) ||
- ((iVar8 < 0 || (((Sector->dy <= iVar8 || (iVar10 < 0)) || (Sector->dz <= iVar10))))))
- {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar5 + Sector->xmin,
- iVar8 + Sector->ymin,iVar10 + Sector->zmin);
- ppTVar7 = pmVar4->entry;
- }
- else {
- ppTVar7 = Sector->entry + iVar10 * iVar1 * Sector->dy + iVar8 * iVar1 + iVar5;
- }
- OVar6.ObjectID =
- *(ulong *)((z + (iVar11 >> 5) * -0x20 + (y + (iVar9 >> 5) * -0x20) * 0x20) * 4 +
- (int)*ppTVar7);
- }
- *(ulong *)x = OVar6.ObjectID;
- }
- else {
- *(ulong *)x = NONE.ObjectID;
- }
- return (Object)x;
-}
-
-
-
-Object GetMapContainer(Object *Obj)
-
-{
- bool bVar1;
- TObject *pTVar2;
- Object OVar3;
- ulong Position;
- uint uVar4;
- uint *in_stack_00000008;
- Object local_4c [4];
- Object local_3c [4];
- ObjectType local_2c [7];
-
- bVar1 = false;
- if (*in_stack_00000008 != 0) {
- uVar4 = *in_stack_00000008 & HashTableMask;
- if (HashTableType[uVar4] == '\x02') {
- UnswapSector(HashTableData[uVar4]);
- }
- if ((HashTableType[uVar4] == '\x01') &&
- (*(uint *)HashTableData[uVar4] == *in_stack_00000008)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- while( true ) {
- local_3c[0].ObjectID = *in_stack_00000008;
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID(local_2c,(pTVar2->Type).TypeID);
- if (local_2c[0].TypeID == 0) break;
- local_4c[0].ObjectID = *in_stack_00000008;
- pTVar2 = AccessObject(local_4c);
- local_2c[0].TypeID = (pTVar2->Container).ObjectID;
- *in_stack_00000008 = local_2c[0].TypeID;
- }
- OVar3.ObjectID = *in_stack_00000008;
- }
- else {
- error(&DAT_080f1fe0);
- OVar3 = NONE;
- }
- Obj->ObjectID = (ulong)OVar3;
- return (Object)(ulong)Obj;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-Object GetFirstObject(void)
-
-{
- Object OVar1;
- ulong *in_stack_00000004;
- int in_stack_00000008;
- int in_stack_0000000c;
- Object local_1c;
- Object MapCon;
-
- GetMapContainer((int)&local_1c,in_stack_00000008,in_stack_0000000c);
- OVar1 = NONE;
- if (local_1c.ObjectID != NONE.ObjectID) {
- OVar1.ObjectID = Object::getAttribute(&local_1c,CONTENT);
- }
- *in_stack_00000004 = OVar1.ObjectID;
- return (Object)(ulong)in_stack_00000004;
-}
-
-
-
// WARNING: Unknown calling convention -- yet parameter storage is locked
Object GetFirstSpecObject(void)
@@ -7664,111 +6326,6 @@ Object GetFirstSpecObject(void)
return (Object)(ulong)in_stack_00000004;
}
-
-
-Object GetFirstContainerObject(Object *Con)
-
-{
- bool bVar1;
- TObject *pTVar2;
- Object OVar3;
- Object *in_stack_00000008;
- Object local_3c [4];
- Object local_2c [7];
-
- local_2c[0].ObjectID = NONE.ObjectID;
- local_3c[0].ObjectID = in_stack_00000008->ObjectID;
- if (local_3c[0].ObjectID == NONE.ObjectID) {
- error(&DAT_080f1b80);
- OVar3 = NONE;
- }
- else {
- pTVar2 = AccessObject(local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER);
- if (!bVar1) {
- local_2c[0].ObjectID = in_stack_00000008->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_3c,CHEST);
- if (!bVar1) {
- local_2c[0].ObjectID = in_stack_00000008->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)local_3c,(pTVar2->Type).TypeID);
- error("GetFirstContainerObject: Con (%d) ist kein Container.\n",local_3c[0].ObjectID
- );
- OVar3 = NONE;
- goto LAB_0805abe7;
- }
- }
- OVar3.ObjectID = Object::getAttribute(in_stack_00000008,CONTENT);
- }
-LAB_0805abe7:
- Con->ObjectID = (ulong)OVar3;
- return (Object)(ulong)Con;
-}
-
-
-
-Object GetContainerObject(Object *Con,int nr)
-
-{
- bool bVar1;
- TObject *pTVar2;
- ulong Position;
- uint uVar3;
- int in_stack_0000000c;
- Object local_5c [4];
- ulong local_4c;
- ulong local_3c;
- Object local_2c;
- Object Obj;
-
- bVar1 = false;
- if (*(uint *)nr != 0) {
- uVar3 = *(uint *)nr & HashTableMask;
- if (HashTableType[uVar3] == '\x02') {
- UnswapSector(HashTableData[uVar3]);
- }
- if ((HashTableType[uVar3] == '\x01') && (*(int *)HashTableData[uVar3] == *(int *)nr)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (bVar1) {
- if (-1 < in_stack_0000000c) {
- local_3c = *(ulong *)nr;
- GetFirstContainerObject(&local_2c);
- if (local_2c.ObjectID != NONE.ObjectID) {
- do {
- if (in_stack_0000000c == 0) goto LAB_0805ad80;
- in_stack_0000000c = in_stack_0000000c + -1;
- local_5c[0].ObjectID = local_2c.ObjectID;
- local_4c = NONE.ObjectID;
- local_3c = NONE.ObjectID;
- pTVar2 = AccessObject(local_5c);
- local_2c.ObjectID = (pTVar2->NextObject).ObjectID;
- } while (local_2c.ObjectID != NONE.ObjectID);
- }
- Con->ObjectID = (ulong)NONE;
- return (Object)(ulong)Con;
- }
- error(&DAT_080f2020);
- local_2c = NONE;
- }
- else {
- error(&DAT_080f2060);
- local_2c = NONE;
- }
-LAB_0805ad80:
- Con->ObjectID = (ulong)local_2c;
- return (Object)(ulong)Con;
-}
-
-
-
bool IsOnMap(int x,int y,int z)
{
@@ -8224,472 +6781,6 @@ bool GetMarkPosition(void)
}
-
-void InitSector(int x,int y,int z)
-
-{
- int iVar1;
- matrix3d<TSector*> *pmVar2;
- int iVar3;
- TSector *pTVar4;
- TSector **ppTVar5;
- uint uVar6;
- TObject *pTVar7;
- int iVar8;
- int iVar9;
- TSector *pTVar10;
- int yy;
- TSector *Sec;
- int local_5c;
- int xx;
- Object local_3c [4];
- ulong local_2c;
- Object Obj;
-
- pmVar2 = Sector;
- iVar9 = y - Sector->ymin;
- iVar3 = z - Sector->zmin;
- iVar8 = x - Sector->xmin;
- if ((((iVar8 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar8)) || (iVar9 < 0)) ||
- (((Sector->dy <= iVar9 || (iVar3 < 0)) || (Sector->dz <= iVar3)))) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar8 + Sector->xmin,
- iVar9 + Sector->ymin,iVar3 + Sector->zmin);
- ppTVar5 = pmVar2->entry;
- }
- else {
- ppTVar5 = Sector->entry + iVar3 * iVar1 * Sector->dy + iVar9 * iVar1 + iVar8;
- }
- if (*ppTVar5 == (TSector *)0x0) {
- pTVar4 = (TSector *)malloc(0x1008);
- pmVar2 = Sector;
- iVar9 = y - Sector->ymin;
- iVar3 = z - Sector->zmin;
- iVar8 = x - Sector->xmin;
- if (((iVar8 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar8)) ||
- ((iVar9 < 0 || (((Sector->dy <= iVar9 || (iVar3 < 0)) || (Sector->dz <= iVar3)))))) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar8 + Sector->xmin,
- iVar9 + Sector->ymin,iVar3 + Sector->zmin);
- ppTVar5 = pmVar2->entry;
- }
- else {
- ppTVar5 = Sector->entry + iVar3 * iVar1 * Sector->dy + iVar9 * iVar1 + iVar8;
- }
- *ppTVar5 = pTVar4;
- uVar6 = 0x1008;
- pTVar10 = pTVar4;
- if (((uint)pTVar4 & 4) != 0) {
- pTVar4->MapCon[0][0].ObjectID = 0;
- uVar6 = 0x1004;
- pTVar10 = (TSector *)(pTVar4->MapCon[0] + 1);
- }
- for (uVar6 = uVar6 >> 2; uVar6 != 0; uVar6 = uVar6 - 1) {
- pTVar10->MapCon[0][0].ObjectID = 0;
- pTVar10 = (TSector *)(pTVar10->MapCon[0] + 1);
- }
- pTVar4->Status = '\0';
- pTVar4->TimeStamp = RoundNr;
- local_5c = 0;
- do {
- iVar3 = 0;
- do {
- CreateObject();
- local_3c[0].ObjectID = local_2c;
- pTVar7 = AccessObject(local_3c);
- pTVar7->Attributes[1] = x * 0x20 + local_5c;
- local_3c[0].ObjectID = local_2c;
- pTVar7 = AccessObject(local_3c);
- pTVar7->Attributes[2] = y * 0x20 + iVar3;
- local_3c[0].ObjectID = local_2c;
- pTVar7 = AccessObject(local_3c);
- pTVar7->Attributes[3] = z;
- iVar8 = iVar3 + 1;
- pTVar4->MapCon[local_5c][iVar3].ObjectID = local_2c;
- iVar3 = iVar8;
- } while (iVar8 < 0x20);
- local_5c = local_5c + 1;
- } while (local_5c < 0x20);
- pTVar4->MapFlags = '\0';
- pTVar4->Status = '\x01';
- }
- else {
- error("InitSector: Sektor %d/%d/%d existiert schon.\n",x,y,z);
- }
- return;
-}
-
-
-
-void SwapObject(TWriteBinaryFile *File,Object *Obj,ulong FileNumber)
-
-{
- TObject *Entry_00;
- bool bVar1;
- TObject *pTVar2;
- ulong Position;
- uint uVar3;
- TObject *Entry;
- TObject *local_5c;
- TObject *local_4c;
- Object Help;
- Object local_3c;
- Object Search;
- Object local_2c [7];
-
- bVar1 = false;
- if (Obj->ObjectID != 0) {
- uVar3 = Obj->ObjectID & HashTableMask;
- if (HashTableType[uVar3] == '\x02') {
- UnswapSector(HashTableData[uVar3]);
- }
- if ((HashTableType[uVar3] == '\x01') && (*(ulong *)HashTableData[uVar3] == Obj->ObjectID)) {
- bVar1 = true;
- }
- else {
- bVar1 = false;
- }
- }
- if (!bVar1) {
- // try { // try from 0805b9bf to 0805bb3b has its CatchHandler @ 0805bb46
- error(&DAT_080f2300);
- return;
- }
- Entry_00 = (TObject *)HashTableData[HashTableMask & Obj->ObjectID];
- (*(File->super_TWriteStream)._vptr_TWriteStream[5])(File,Entry_00,0x20);
- local_3c = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(&local_3c);
- ObjectType::setTypeID((ObjectType *)local_2c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)local_2c,CONTAINER);
- if (!bVar1) {
- local_2c[0] = (Object)Obj->ObjectID;
- pTVar2 = AccessObject(local_2c);
- ObjectType::setTypeID((ObjectType *)&local_3c,(pTVar2->Type).TypeID);
- bVar1 = ObjectType::getFlag((ObjectType *)&local_3c,CHEST);
- if (!bVar1) goto LAB_0805bad8;
- }
- local_3c.ObjectID = Object::getAttribute(Obj,CONTENT);
- local_2c[0].ObjectID = NONE.ObjectID;
- local_4c = (TObject *)NONE.ObjectID;
- if (local_3c.ObjectID != NONE.ObjectID) {
- do {
- Entry = (TObject *)local_3c.ObjectID;
- local_4c = (TObject *)local_3c.ObjectID;
- local_2c[0].ObjectID = NONE.ObjectID;
- pTVar2 = AccessObject((Object *)&Entry);
- local_5c = (TObject *)(pTVar2->NextObject).ObjectID;
- Entry = local_4c;
- local_3c.ObjectID = (ulong)local_5c;
- local_2c[0].ObjectID = (ulong)local_5c;
- SwapObject(File,(Object *)&Entry,FileNumber);
- local_2c[0].ObjectID = NONE.ObjectID;
- local_4c = (TObject *)NONE.ObjectID;
- } while (local_3c.ObjectID != NONE.ObjectID);
- }
-LAB_0805bad8:
- PutFreeObjectSlot(Entry_00);
- HashTableType[HashTableMask & Obj->ObjectID] = '\x02';
- HashTableData[HashTableMask & Obj->ObjectID] = FileNumber;
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void SwapSector(void)
-
-{
- int iVar1;
- TSector *pTVar2;
- matrix3d<TSector*> *pmVar3;
- bool bVar4;
- TSector *Help;
- int iVar5;
- TSector **ppTVar6;
- int iVar7;
- int iVar8;
- int *piVar9;
- Object *Obj;
- char *__oflag;
- int local_206c;
- int local_2068;
- int yy;
- int xx;
- TSector *local_205c;
- int z;
- int y;
- int x;
- ulong Oldest;
- TSector *Sec;
- int SecZ;
- int SecY;
- int SecX;
- undefined1 local_202c [4];
- TWriteBinaryFile File;
- char local_101c [4];
- char FileName [4096];
-
- Oldest = 0;
- SecY = 0;
- SecZ = 0;
- x = RoundNr + 1;
- Sec = (TSector *)0x0;
- y = SectorXMin;
- iVar5 = SectorYMax;
- iVar7 = SectorXMax;
- if (SectorXMin <= SectorXMax) {
- do {
- z = SectorYMin;
- if (SectorYMin <= iVar5) {
- local_206c = SectorZMax;
- do {
- local_205c = (TSector *)SectorZMin;
- if (SectorZMin <= local_206c) {
- do {
- pmVar3 = Sector;
- iVar8 = z - Sector->ymin;
- iVar5 = (int)local_205c - Sector->zmin;
- iVar7 = y - Sector->xmin;
- if (((((iVar7 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar7)) ||
- (iVar8 < 0)) || ((Sector->dy <= iVar8 || (iVar5 < 0)))) ||
- (Sector->dz <= iVar5)) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",
- iVar7 + Sector->xmin,iVar8 + Sector->ymin,iVar5 + Sector->zmin
- );
- ppTVar6 = pmVar3->entry;
- local_206c = SectorZMax;
- }
- else {
- ppTVar6 = Sector->entry +
- iVar5 * iVar1 * Sector->dy + iVar8 * iVar1 + iVar7;
- }
- pTVar2 = *ppTVar6;
- if (((pTVar2 != (TSector *)0x0) && (pTVar2->Status == '\x01')) &&
- (pTVar2->TimeStamp < (uint)x)) {
- SecZ = z;
- SecY = y;
- Sec = local_205c;
- x = pTVar2->TimeStamp;
- Oldest = (ulong)pTVar2;
- }
- local_205c = (TSector *)((int)&local_205c->MapCon[0][0].ObjectID + 1);
- iVar5 = SectorYMax;
- } while ((int)local_205c <= local_206c);
- }
- z = z + 1;
- iVar7 = SectorXMax;
- } while (z <= iVar5);
- }
- y = y + 1;
- } while (y <= iVar7);
- }
- if (Oldest == 0) {
- error("FATAL ERROR in SwapSector: Es kann kein Sektor ausgelagert werden.\n");
- // WARNING: Subroutine does not return
- abort();
- }
- do {
- SwapSector::lexical_block_2::FileNumber = SwapSector::lexical_block_2::FileNumber + 1;
- if (99999999 < SwapSector::lexical_block_2::FileNumber) {
- SwapSector::lexical_block_2::FileNumber = 1;
- }
- __oflag = SAVEPATH;
- sprintf(local_101c,"%s/%08ld.swp",SAVEPATH,SwapSector::lexical_block_2::FileNumber);
- bVar4 = FileExists(local_101c);
- } while (bVar4);
- TWriteBinaryFile::TWriteBinaryFile((TWriteBinaryFile *)local_202c);
- // try { // try from 0805bd5f to 0805be46 has its CatchHandler @ 0805bee3
- TWriteBinaryFile::open((TWriteBinaryFile *)local_202c,local_101c,(int)__oflag);
- print();
- TWriteStream::writeQuad((TWriteStream *)local_202c,SecY);
- TWriteStream::writeQuad((TWriteStream *)local_202c,SecZ);
- TWriteStream::writeQuad((TWriteStream *)local_202c,(ulong)Sec);
- yy = 0;
- do {
- local_2068 = 0;
- piVar9 = (int *)(Oldest + yy * 0x80);
- do {
- SecX = *piVar9;
- Obj = (Object *)&SecX;
- SwapObject((TWriteBinaryFile *)local_202c,Obj,SwapSector::lexical_block_2::FileNumber);
- local_2068 = local_2068 + 1;
- piVar9 = piVar9 + 1;
- } while (local_2068 < 0x20);
- yy = yy + 1;
- } while (yy < 0x20);
- *(undefined1 *)(Oldest + 0x1004) = 2;
- TWriteBinaryFile::close((TWriteBinaryFile *)local_202c,(int)Obj);
- TWriteBinaryFile::~TWriteBinaryFile((TWriteBinaryFile *)local_202c,(int)Obj);
- return;
-}
-
-
-
-void UnswapSector(ulong FileNumber)
-
-{
- int iVar1;
- TSector *pTVar2;
- ulong *puVar3;
- matrix3d<TSector*> *pmVar4;
- uchar *puVar5;
- int iVar6;
- TObject *pTVar7;
- ulong uVar8;
- ulong uVar9;
- int iVar10;
- TSector **ppTVar11;
- int iVar12;
- ulong nr;
- int iVar13;
- uint uVar14;
- TSector *Sec;
- char *pcVar15;
- ulong uVar16;
- TObject *local_204c;
- int SecZ;
- int SecY;
- int SecX;
- int FileSize;
- TReadBinaryFile File;
- char local_101c [4];
- char FileName [4096];
-
- pcVar15 = SAVEPATH;
- sprintf(local_101c,"%s/%08ld.swp",SAVEPATH,FileNumber);
- TReadBinaryFile::TReadBinaryFile((TReadBinaryFile *)&FileSize);
- // try { // try from 0805bf7c to 0805c0c2 has its CatchHandler @ 0805c257
- TReadBinaryFile::open((TReadBinaryFile *)&FileSize,local_101c,(int)pcVar15);
- iVar6 = TReadBinaryFile::getSize((TReadBinaryFile *)&FileSize);
- pTVar7 = (TObject *)TReadStream::readQuad((TReadStream *)&FileSize);
- uVar8 = TReadStream::readQuad((TReadStream *)&FileSize);
- uVar9 = TReadStream::readQuad((TReadStream *)&FileSize);
- pcVar15 = "Lagere Sector %d/%d/%d ein...\n";
- uVar16 = uVar9;
- print();
- pmVar4 = Sector;
- iVar13 = uVar8 - Sector->ymin;
- iVar10 = uVar9 - Sector->zmin;
- iVar12 = (int)pTVar7 - Sector->xmin;
- if ((((iVar12 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar12)) || (iVar13 < 0)) ||
- (((Sector->dy <= iVar13 || (iVar10 < 0)) || (Sector->dz <= iVar10)))) {
- pcVar15 = (char *)(iVar12 + Sector->xmin);
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",pcVar15,iVar13 + Sector->ymin,
- iVar10 + Sector->zmin,uVar16);
- ppTVar11 = pmVar4->entry;
- }
- else {
- ppTVar11 = Sector->entry + iVar12 + iVar13 * iVar1 + iVar10 * iVar1 * Sector->dy;
- }
- pTVar2 = *ppTVar11;
- if (pTVar2 == (TSector *)0x0) {
- pcVar15 = "UnswapSector: Sektor %d/%d/%d existiert nicht.\n";
- }
- else {
- if (pTVar2->Status == '\x02') {
- while( true ) {
- // try { // try from 0805c0db to 0805c1ee has its CatchHandler @ 0805c257
- iVar10 = TReadBinaryFile::getPosition((TReadBinaryFile *)&FileSize);
- if (iVar6 <= iVar10) break;
- if (FirstFreeObject == (TObject *)0x0) {
- SwapSector();
- }
- local_204c = FirstFreeObject;
- if (FirstFreeObject == (TObject *)0x0) {
- error("GetFreeObjectSlot: Kein freier Platz mehr.\n");
- local_204c = (TObject *)0x0;
- }
- else {
- puVar3 = &FirstFreeObject->ObjectID;
- FirstFreeObject = (TObject *)(FirstFreeObject->NextObject).ObjectID;
- *puVar3 = 0;
- (local_204c->NextObject).ObjectID = 0;
- (local_204c->Container).ObjectID = 0;
- (local_204c->Type).TypeID = 0;
- local_204c->Attributes[0] = 0;
- local_204c->Attributes[1] = 0;
- local_204c->Attributes[2] = 0;
- local_204c->Attributes[3] = 0;
- }
- pTVar7 = local_204c;
- TReadBinaryFile::readBytes((TReadBinaryFile *)&FileSize,(uchar *)local_204c,0x20);
- puVar5 = HashTableType;
- pcVar15 = (char *)local_204c->ObjectID;
- uVar14 = (uint)pcVar15 & HashTableMask;
- if (HashTableType[uVar14] == '\x02') {
- HashTableData[uVar14] = (ulong)local_204c;
- puVar5[uVar14] = '\x01';
- pcVar15 = (char *)pTVar7;
- }
- else {
- error("UnswapSector: Objekt %ld existiert schon.\n");
- }
- }
- pTVar2->Status = '\x01';
- TReadBinaryFile::close((TReadBinaryFile *)&FileSize,(int)pcVar15);
- unlink(local_101c);
- goto LAB_0805c0c3;
- }
- pcVar15 = "UnswapSector: Sektor %d/%d/%d ist nicht ausgelagert.\n";
- }
- error(pcVar15,pTVar7,uVar8,uVar9,uVar16);
- TReadBinaryFile::close((TReadBinaryFile *)&FileSize,(int)pTVar7);
- pcVar15 = (char *)pTVar7;
-LAB_0805c0c3:
- TReadBinaryFile::~TReadBinaryFile((TReadBinaryFile *)&FileSize,(int)pcVar15);
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void DeleteSwappedSectors(void)
-
-{
- DIR *__dirp;
- dirent *pdVar1;
- size_t sVar2;
- int iVar3;
- dirent *DirEntry;
- char *pcVar4;
- char *pcVar5;
- bool bVar6;
- char *s;
- DIR *WorkDir;
- char FileName [4096];
-
- __dirp = opendir(SAVEPATH);
- if (__dirp == (DIR *)0x0) {
- error("DeleteSwappedSectors: Unterverzeichnis %s nicht gefunden\n",SAVEPATH);
- }
- else {
- while (pdVar1 = readdir(__dirp), pdVar1 != (dirent *)0x0) {
- sVar2 = strlen(pdVar1->d_name);
- bVar6 = sVar2 == 0xc;
- if (bVar6) {
- iVar3 = 4;
- pcVar4 = pdVar1->d_name + 8;
- pcVar5 = ".swp";
- do {
- if (iVar3 == 0) break;
- iVar3 = iVar3 + -1;
- bVar6 = *pcVar4 == *pcVar5;
- pcVar4 = pcVar4 + 1;
- pcVar5 = pcVar5 + 1;
- } while (bVar6);
- if (bVar6) {
- sprintf((char *)&WorkDir,"%s/%s",SAVEPATH,pdVar1->d_name);
- unlink((char *)&WorkDir);
- }
- }
- }
- closedir(__dirp);
- }
- return;
-}
-
-
-
int GetInstanceAttributeByName(char *Name)
{
@@ -8711,504 +6802,6 @@ int GetInstanceAttributeByName(char *Name)
return -1;
}
-
-
-// WARNING: Variable defined which should be unmapped: Skip_local
-
-void LoadObjects(TReadScriptFile *Script,TWriteStream *Stream,bool Skip)
-
-{
- bool bVar1;
- char cVar2;
- uint uVar3;
- undefined4 *puVar4;
- char *pcVar5;
- int iVar6;
- ushort TypeID;
- char (*s1) [30];
- uint local_24;
- int i;
- int iStack_18;
- bool ProcessObjects;
- int Depth;
- bool Skip_local;
-
- iStack_18 = 1;
- // try { // try from 0805c41e to 0805c65e has its CatchHandler @ 0805c661
- TReadScriptFile::readSymbol(Script,'{');
- bVar1 = true;
- TReadScriptFile::nextToken(Script);
- do {
- if (bVar1) {
- if (Script->Token == SPECIAL) {
- cVar2 = TReadScriptFile::getSpecial(Script);
- if (cVar2 == '}') {
- if (!Skip) {
- (*Stream->_vptr_TWriteStream[2])(Stream,0xffff);
- }
- iStack_18 = iStack_18 + -1;
- bVar1 = false;
- if (iStack_18 < 1) {
- return;
- }
- goto LAB_0805c45f;
- }
- if ((Script->Token == SPECIAL) &&
- (cVar2 = TReadScriptFile::getSpecial(Script), cVar2 == ',')) {
- TReadScriptFile::nextToken(Script);
- }
- }
- uVar3 = TReadScriptFile::getNumber(Script);
- bVar1 = ObjectTypeExists(uVar3 & 0xffff);
- if (!bVar1) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = "unknown object type";
-LAB_0805c49b:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar4,char_const*::typeinfo,0);
- }
- if (!Skip) {
- (*Stream->_vptr_TWriteStream[2])(Stream,uVar3 & 0xffff);
- }
- bVar1 = false;
-LAB_0805c45f:
- TReadScriptFile::nextToken(Script);
- }
- else {
- if (Script->Token != SPECIAL) {
- pcVar5 = TReadScriptFile::getIdentifier(Script);
- s1 = InstanceAttributeNames;
- local_24 = 0;
- do {
- iVar6 = stricmp(*s1,pcVar5,-1);
- if (iVar6 == 0) goto LAB_0805c564;
- local_24 = local_24 + 1;
- s1 = s1 + 1;
- } while ((int)local_24 < 0x12);
- local_24 = 0xffffffff;
-LAB_0805c564:
- if (local_24 == 0xffffffff) {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = "unknown attribute";
- goto LAB_0805c49b;
- }
- TReadScriptFile::readSymbol(Script,'=');
- if (!Skip) {
- (*Stream->_vptr_TWriteStream[1])(Stream,local_24 & 0xff);
- }
- if (local_24 == 0) {
- iStack_18 = iStack_18 + 1;
- TReadScriptFile::readSymbol(Script,'{');
- bVar1 = true;
- }
- else if (local_24 - 9 < 2) {
- if (Skip) {
- TReadScriptFile::readString(Script);
- }
- else {
- pcVar5 = TReadScriptFile::readString(Script);
- (*Stream->_vptr_TWriteStream[4])(Stream,pcVar5);
- }
- }
- else if (Skip) {
- TReadScriptFile::readNumber(Script);
- }
- else {
- iVar6 = TReadScriptFile::readNumber(Script);
- (*Stream->_vptr_TWriteStream[3])(Stream,iVar6);
- }
- goto LAB_0805c45f;
- }
- if (!Skip) {
- (*Stream->_vptr_TWriteStream[1])(Stream,0xff);
- }
- bVar1 = true;
- }
- if (iStack_18 < 1) {
- return;
- }
- } while( true );
-}
-
-
-
-void LoadObjects(TReadStream *Stream,Object *Con)
-
-{
- bool bVar1;
- char cVar2;
- ulong Value;
- uint uVar3;
- TObject *pTVar4;
- INSTANCEATTRIBUTE IVar5;
- ulong Value_00;
- int NewDelay;
- ulong Value_1;
- ushort TypeID;
- int Depth;
- int iVar6;
- char local_108c [3];
- bool ProcessObjects;
- char Help [4096];
- ObjectType local_7c [4];
- ulong local_6c [4];
- Object local_5c;
- ObjectType Type;
- Object local_3c [4];
- Object local_2c;
- Object Obj;
-
- iVar6 = 1;
- bVar1 = true;
- local_2c.ObjectID = NONE.ObjectID;
- do {
- if (bVar1) {
- // try { // try from 0805c6bb to 0805c867 has its CatchHandler @ 0805c870
- uVar3 = (*Stream->_vptr_TReadStream[2])(Stream);
- if ((short)uVar3 == -1) {
- iVar6 = iVar6 + -1;
- local_5c = (Object)Con->ObjectID;
- local_3c[0].ObjectID = local_5c.ObjectID;
- local_2c.ObjectID = local_5c.ObjectID;
- pTVar4 = AccessObject(&local_5c);
- local_3c[0].ObjectID = (pTVar4->Container).ObjectID;
- Con->ObjectID = (ulong)local_3c[0];
- }
- else {
- ObjectCounter = ObjectCounter + 1;
- ObjectType::setTypeID((ObjectType *)&local_5c,uVar3 & 0xffff);
- bVar1 = false;
- if ((0 < (int)local_5c.ObjectID) && ((int)local_5c.ObjectID < 0xb)) {
- bVar1 = true;
- }
- if (bVar1) {
- local_6c[0] = Con->ObjectID;
- GetContainerObject(local_3c,(int)local_6c);
- }
- else {
- ObjectType::setTypeID(local_7c,local_5c.ObjectID);
- Help._4092_4_ = Con->ObjectID;
- AppendObject(local_3c,(ObjectType *)(Help + 0xffc));
- }
- local_2c.ObjectID = local_3c[0].ObjectID;
- }
- bVar1 = false;
- }
- else {
- IVar5 = (*Stream->_vptr_TReadStream[1])(Stream);
- cVar2 = (char)IVar5;
- if (cVar2 != -1) {
- if (cVar2 != '\0') {
- if ((byte)(cVar2 - 9U) < 2) {
- (*Stream->_vptr_TReadStream[4])(Stream,local_108c,0x1000);
- Value_00 = AddDynamicString(local_108c);
- }
- else {
- if (cVar2 == '\x0f') {
- NewDelay = (*Stream->_vptr_TReadStream[3])(Stream);
- if (NewDelay != 0) {
- Help[0xffc] = (undefined1)local_2c.ObjectID;
- Help[0xffd] = local_2c.ObjectID._1_1_;
- Help[0xffe] = local_2c.ObjectID._2_1_;
- Help[0xfff] = local_2c.ObjectID._3_1_;
- CronChange((Object *)(Help + 0xffc),NewDelay);
- }
- goto LAB_0805c72d;
- }
- Value_00 = (*Stream->_vptr_TReadStream[3])(Stream);
- }
- Object::setAttribute(&local_2c,IVar5 & 0xff,Value_00);
- goto LAB_0805c72d;
- }
- iVar6 = iVar6 + 1;
- local_7c[0].TypeID = local_2c.ObjectID;
- Con->ObjectID = (ulong)local_2c;
- Help[0xffc] = (undefined1)local_2c.ObjectID;
- Help[0xffd] = local_2c.ObjectID._1_1_;
- Help[0xffe] = local_2c.ObjectID._2_1_;
- Help[0xfff] = local_2c.ObjectID._3_1_;
- }
- bVar1 = true;
- }
-LAB_0805c72d:
- if (iVar6 < 1) {
- return;
- }
- } while( true );
-}
-
-
-
-void LoadSector(char *FileName,int x,int y,int z)
-
-{
- int iVar1;
- TSector *pTVar2;
- bool bVar3;
- matrix3d<TSector*> *pmVar4;
- char cVar5;
- uchar *Help;
- int iVar6;
- TSector **ppTVar7;
- char *pcVar8;
- TObject *pTVar9;
- byte *pbVar10;
- int iVar11;
- int iVar12;
- int iVar13;
- char *pcVar14;
- undefined1 uVar15;
- char *pcVar16;
- uint local_4034;
- int yy;
- int xx;
- TSector *Sec;
- undefined1 local_400c [4];
- TReadBuffer ReadBuffer;
- TReadScriptFile Script;
-
- bVar3 = false;
- if ((SectorXMin <= x) && (x <= SectorXMax)) {
- bVar3 = true;
- }
- if (bVar3) {
- bVar3 = false;
- if ((SectorYMin <= y) && (y <= SectorYMax)) {
- bVar3 = true;
- }
- if (bVar3) {
- bVar3 = false;
- if ((SectorZMin <= z) && (z <= SectorZMax)) {
- bVar3 = true;
- }
- if (bVar3) {
- iVar12 = z;
- // try { // try from 0805c920 to 0805c932 has its CatchHandler @ 0805cde4
- InitSector(x,y,z);
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)&ReadBuffer.Position);
- // try { // try from 0805c943 to 0805cd14 has its CatchHandler @ 0805cd60
- TReadScriptFile::open((TReadScriptFile *)&ReadBuffer.Position,FileName,iVar12);
- pcVar16 = "Lade Sektor %d/%d/%d ...\n";
- iVar12 = z;
- print();
- pmVar4 = Sector;
- iVar13 = y - Sector->ymin;
- iVar6 = z - Sector->zmin;
- iVar11 = x - Sector->xmin;
- if (((((iVar11 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar11)) || (iVar13 < 0)) ||
- ((Sector->dy <= iVar13 || (iVar6 < 0)))) || (Sector->dz <= iVar6)) {
- pcVar16 = (char *)(iVar11 + Sector->xmin);
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",pcVar16,
- iVar13 + Sector->ymin,iVar6 + Sector->zmin,iVar12);
- ppTVar7 = pmVar4->entry;
- }
- else {
- ppTVar7 = Sector->entry + iVar6 * iVar1 * Sector->dy + iVar13 * iVar1 + iVar11;
- }
- pTVar2 = *ppTVar7;
- yy = -1;
- local_4034 = 0xffffffff;
-LAB_0805ca1d:
- do {
- while( true ) {
- while( true ) {
- do {
- TReadScriptFile::nextToken((TReadScriptFile *)&ReadBuffer.Position);
- if (ReadBuffer.Position == 0) {
- TReadScriptFile::close
- ((TReadScriptFile *)&ReadBuffer.Position,(int)pcVar16)
- ;
- // try { // try from 0805cd1e to 0805cd22 has its CatchHandler @ 0805cde4
- TReadScriptFile::~TReadScriptFile
- ((TReadScriptFile *)&ReadBuffer.Position,(int)pcVar16)
- ;
- return;
- }
- } while ((ReadBuffer.Position == 6) &&
- (cVar5 = TReadScriptFile::getSpecial
- ((TReadScriptFile *)&ReadBuffer.Position),
- cVar5 == ','));
- if (ReadBuffer.Position != 4) break;
- pbVar10 = TReadScriptFile::getBytesequence
- ((TReadScriptFile *)&ReadBuffer.Position);
- yy = (int)*pbVar10;
- local_4034 = (uint)pbVar10[1];
- pcVar16 = (char *)0x3a;
- TReadScriptFile::readSymbol((TReadScriptFile *)&ReadBuffer.Position,':')
- ;
- }
- if (ReadBuffer.Position == 1) break;
- pcVar16 = "next map point expected";
-LAB_0805ca73:
- TReadScriptFile::error((TReadScriptFile *)&ReadBuffer.Position,pcVar16);
- }
- uVar15 = yy == -1;
- if ((bool)uVar15) {
- pcVar16 = "coordinate expected";
- TReadScriptFile::error
- ((TReadScriptFile *)&ReadBuffer.Position,"coordinate expected");
- }
- pcVar8 = TReadScriptFile::getIdentifier((TReadScriptFile *)&ReadBuffer.Position)
- ;
- iVar12 = 8;
- pcVar14 = "refresh";
- do {
- if (iVar12 == 0) break;
- iVar12 = iVar12 + -1;
- uVar15 = *pcVar8 == *pcVar14;
- pcVar8 = pcVar8 + 1;
- pcVar14 = pcVar14 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- pcVar8 = TReadScriptFile::getIdentifier
- ((TReadScriptFile *)&ReadBuffer.Position);
- iVar12 = 9;
- pcVar14 = "nologout";
- do {
- if (iVar12 == 0) break;
- iVar12 = iVar12 + -1;
- uVar15 = *pcVar8 == *pcVar14;
- pcVar8 = pcVar8 + 1;
- pcVar14 = pcVar14 + 1;
- } while ((bool)uVar15);
- if ((bool)uVar15) {
- pTVar2->MapFlags = pTVar2->MapFlags | 2;
- local_400c = (undefined1 [4])pTVar2->MapCon[yy][local_4034].ObjectID;
- pTVar9 = AccessObject((Object *)local_400c);
- pTVar9->Attributes[3] = pTVar9->Attributes[3] | 0x200;
- }
- else {
- pcVar8 = TReadScriptFile::getIdentifier
- ((TReadScriptFile *)&ReadBuffer.Position);
- iVar12 = 0xf;
- pcVar14 = "protectionzone";
- do {
- if (iVar12 == 0) break;
- iVar12 = iVar12 + -1;
- uVar15 = *pcVar8 == *pcVar14;
- pcVar8 = pcVar8 + 1;
- pcVar14 = pcVar14 + 1;
- } while ((bool)uVar15);
- if ((bool)uVar15) {
- pTVar2->MapFlags = pTVar2->MapFlags | 4;
- local_400c = (undefined1 [4])
- pTVar2->MapCon[yy][local_4034].ObjectID;
- pTVar9 = AccessObject((Object *)local_400c);
- pTVar9->Attributes[3] = pTVar9->Attributes[3] | 0x400;
- }
- else {
- pcVar16 = TReadScriptFile::getIdentifier
- ((TReadScriptFile *)&ReadBuffer.Position);
- iVar12 = 8;
- pcVar8 = "content";
- do {
- if (iVar12 == 0) break;
- iVar12 = iVar12 + -1;
- uVar15 = *pcVar16 == *pcVar8;
- pcVar16 = pcVar16 + 1;
- pcVar8 = pcVar8 + 1;
- } while ((bool)uVar15);
- if (!(bool)uVar15) {
- pcVar16 = "unknown map flag";
- goto LAB_0805ca73;
- }
- TReadScriptFile::readSymbol
- ((TReadScriptFile *)&ReadBuffer.Position,'=');
- HelpBuffer.super_TWriteBuffer.Position = 0;
- LoadObjects((TReadScriptFile *)&ReadBuffer.Position,
- (TWriteStream *)&HelpBuffer,false);
- TReadBuffer::TReadBuffer
- ((TReadBuffer *)local_400c,
- HelpBuffer.super_TWriteBuffer.Data,
- HelpBuffer.super_TWriteBuffer.Position);
- GetMapContainer((int)&Sec,x * 0x20 + yy,y * 0x20 + local_4034);
- pcVar16 = (char *)&Sec;
- LoadObjects((TReadStream *)local_400c,(Object *)pcVar16);
- }
- }
- goto LAB_0805ca1d;
- }
- pTVar2->MapFlags = pTVar2->MapFlags | 1;
- local_400c = (undefined1 [4])pTVar2->MapCon[yy][local_4034].ObjectID;
- pTVar9 = AccessObject((Object *)local_400c);
- pTVar9->Attributes[3] = pTVar9->Attributes[3] | 0x100;
- } while( true );
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void LoadMap(void)
-
-{
- char *__s;
- DIR *__dirp;
- dirent *pdVar1;
- size_t sVar2;
- undefined4 *puVar3;
- int iVar4;
- dirent *DirEntry;
- char *pcVar5;
- char *pcVar6;
- bool bVar7;
- DIR *WorkDir;
- int SectorCounter;
- int x;
- int y;
- int z;
- char FileName [4096];
-
- __dirp = opendir(MAPPATH);
- if (__dirp == (DIR *)0x0) {
- error("LoadMap: Unterverzeichnis %s nicht gefunden\n",MAPPATH);
- puVar3 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar3 = "Cannot load map";
- // WARNING: Subroutine does not return
- __cxa_throw(puVar3,char_const*::typeinfo,0);
- }
- // try { // try from 0805ce35 to 0805cfb2 has its CatchHandler @ 0805cfb3
- print();
- ObjectCounter = 0;
- do {
- do {
- pdVar1 = readdir(__dirp);
- if (pdVar1 == (dirent *)0x0) {
- closedir(__dirp);
- print();
- print();
- return;
- }
- __s = pdVar1->d_name;
- sVar2 = strlen(__s);
- bVar7 = sVar2 == 8;
- } while (sVar2 < 9);
- iVar4 = 5;
- pcVar5 = pdVar1->d_name + (sVar2 - 4);
- pcVar6 = ".sec";
- do {
- if (iVar4 == 0) break;
- iVar4 = iVar4 + -1;
- bVar7 = *pcVar5 == *pcVar6;
- pcVar5 = pcVar5 + 1;
- pcVar6 = pcVar6 + 1;
- } while (bVar7);
- if (bVar7) {
- iVar4 = sscanf(__s,"%d-%d-%d.sec",&SectorCounter,&x,&y);
- if (iVar4 == 3) {
- sprintf((char *)&z,"%s/%s",MAPPATH,__s);
- LoadSector((char *)&z,SectorCounter,x,y);
- }
- }
- } while( true );
-}
-
-
-
void SaveObjects(Object *Obj,TWriteStream *Stream,bool Stop)
{
@@ -9442,193 +7035,6 @@ void SaveObjects(TReadStream *Stream,TWriteScriptFile *Script)
return;
}
-
-
-void SaveSector(char *FileName,int x,int y,int z)
-
-{
- int iVar1;
- TSector *pTVar2;
- bool bVar3;
- bool bVar4;
- matrix3d<TSector*> *pmVar5;
- byte bVar6;
- int iVar7;
- TSector **ppTVar8;
- int iVar9;
- int iVar10;
- TSector *Sec;
- int Flags;
- char *__fd;
- int in_stack_ffffef5c;
- int local_106c;
- int yy;
- int xx;
- bool Empty;
- undefined1 local_105c [4];
- TReadBuffer ReadBuffer;
- _func_int_varargs **local_103c;
- Object Obj;
- undefined1 local_102c [4];
- TWriteScriptFile Script;
-
- pmVar5 = Sector;
- iVar10 = y - Sector->ymin;
- iVar7 = z - Sector->zmin;
- iVar9 = x - Sector->xmin;
- if (((((iVar9 < 0) || (iVar1 = Sector->dx, iVar1 <= iVar9)) || (iVar10 < 0)) ||
- ((Sector->dy <= iVar10 || (iVar7 < 0)))) || (Sector->dz <= iVar7)) {
- in_stack_ffffef5c = iVar10 + Sector->ymin;
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",iVar9 + Sector->xmin,
- in_stack_ffffef5c,iVar7 + Sector->zmin);
- ppTVar8 = pmVar5->entry;
- }
- else {
- ppTVar8 = Sector->entry + iVar7 * iVar1 * Sector->dy + iVar10 * iVar1 + iVar9;
- }
- pTVar2 = *ppTVar8;
- if (pTVar2 != (TSector *)0x0) {
- TWriteScriptFile::TWriteScriptFile((TWriteScriptFile *)local_102c);
- // try { // try from 0805d5d8 to 0805d76d has its CatchHandler @ 0805d923
- TWriteScriptFile::open((TWriteScriptFile *)local_102c,FileName,in_stack_ffffef5c);
- print();
- TWriteScriptFile::writeText
- ((TWriteScriptFile *)local_102c,"# Tibia - graphical Multi-User-Dungeon");
- TWriteScriptFile::writeLn((TWriteScriptFile *)local_102c);
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"# Data for sector ");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)local_102c,x);
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"/");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)local_102c,y);
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"/");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)local_102c,z);
- TWriteScriptFile::writeLn((TWriteScriptFile *)local_102c);
- TWriteScriptFile::writeLn((TWriteScriptFile *)local_102c);
- bVar4 = true;
- yy = 0;
- do {
- local_106c = 0;
- do {
- __fd = (char *)(x * 0x20 + yy);
- GetFirstObject();
- ReadBuffer.Position = pTVar2->MapCon[yy][local_106c].ObjectID;
- bVar6 = GetMapContainerFlags((Object *)&ReadBuffer.Position);
- bVar3 = false;
- ReadBuffer.Position = NONE.ObjectID;
- if ((local_103c == (_func_int_varargs **)NONE.ObjectID) && (bVar6 == 0)) {
- bVar3 = true;
- }
- if (!bVar3) {
- TWriteScriptFile::writeNumber((TWriteScriptFile *)local_102c,yy);
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"-");
- TWriteScriptFile::writeNumber((TWriteScriptFile *)local_102c,local_106c);
- __fd = &DAT_080f2ab7;
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,": ");
- if ((bVar6 & 1) != 0) {
- __fd = "Refresh, ";
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"Refresh, ");
- }
- if ((bVar6 & 2) != 0) {
- __fd = "NoLogout, ";
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"NoLogout, ");
- }
- if ((bVar6 & 4) != 0) {
- __fd = "ProtectionZone, ";
- TWriteScriptFile::writeText
- ((TWriteScriptFile *)local_102c,"ProtectionZone, ");
- }
- ReadBuffer.Position = NONE.ObjectID;
- local_105c = (undefined1 [4])NONE.ObjectID;
- if (local_103c != (_func_int_varargs **)NONE.ObjectID) {
- TWriteScriptFile::writeText((TWriteScriptFile *)local_102c,"Content=");
- HelpBuffer.super_TWriteBuffer.Position = 0;
- local_105c = (undefined1 [4])local_103c;
- SaveObjects((Object *)local_105c,(TWriteStream *)&HelpBuffer,false);
- TReadBuffer::TReadBuffer
- ((TReadBuffer *)local_105c,HelpBuffer.super_TWriteBuffer.Data,
- HelpBuffer.super_TWriteBuffer.Position);
- __fd = (char *)local_102c;
- SaveObjects((TReadStream *)local_105c,(TWriteScriptFile *)local_102c);
- }
- TWriteScriptFile::writeLn((TWriteScriptFile *)local_102c);
- bVar4 = false;
- }
- local_106c = local_106c + 1;
- } while (local_106c < 0x20);
- yy = yy + 1;
- } while (yy < 0x20);
- TWriteScriptFile::close((TWriteScriptFile *)local_102c,(int)__fd);
- if (bVar4) {
- // try { // try from 0805d7ac to 0805d8f2 has its CatchHandler @ 0805d923
- error("SaveSector: Sektor %d/%d/%d ist leer.\n",x,y,z);
- unlink(FileName);
- __fd = (char *)x;
- }
- TWriteScriptFile::~TWriteScriptFile((TWriteScriptFile *)local_102c,(int)__fd);
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void SaveMap(void)
-
-{
- int iVar1;
- int iVar2;
- int iVar3;
- int z;
- int iVar4;
- int y;
- int y_00;
- int x;
- int x_00;
- char local_101c [4];
- char FileName [4096];
-
- if (SaveMap::SavingMap) {
- error("SaveMap: Karte wird schon gespeichert.\n");
- }
- else {
- SaveMap::SavingMap = true;
- print();
- ObjectCounter = 0;
- iVar2 = SectorXMax;
- iVar3 = SectorYMax;
- x_00 = SectorXMin;
- if (SectorXMin <= SectorXMax) {
- do {
- iVar1 = SectorZMax;
- y_00 = SectorYMin;
- if (SectorYMin <= iVar3) {
- do {
- iVar2 = SectorZMin;
- if (SectorZMin <= iVar1) {
- do {
- sprintf(local_101c,"%s/%04u-%04u-%02u.sec",MAPPATH,x_00,y_00,iVar2);
- iVar4 = iVar2 + 1;
- SaveSector(local_101c,x_00,y_00,iVar2);
- iVar1 = SectorZMax;
- iVar3 = SectorYMax;
- iVar2 = iVar4;
- } while (iVar4 <= SectorZMax);
- }
- y_00 = y_00 + 1;
- iVar2 = SectorXMax;
- } while (y_00 <= iVar3);
- }
- x_00 = x_00 + 1;
- } while (x_00 <= iVar2);
- }
- print();
- SaveMap::SavingMap = false;
- }
- return;
-}
-
-
-
void RefreshSector(int x,int y,int z,TReadStream *Stream)
{
@@ -10295,579 +7701,6 @@ LAB_0805e958:
goto LAB_0805e966;
}
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ReadMapConfig(void)
-
-{
- TReadScriptFile *pTVar1;
- char *pcVar2;
- TMark *pTVar3;
- size_t sVar4;
- TDepotInfo *pTVar5;
- undefined4 *puVar6;
- int iVar7;
- undefined1 uVar8;
- int *__s;
- char *pcVar9;
- int *piVar10;
- int DepotNumber;
- char Ident [30];
- TReadScriptFile Script;
- int local_101c;
- char FileName [4096];
-
- NewbieStartPositionY = 0;
- SectorYMin = 1000;
- SectorYMax = 0x3f7;
- SectorZMax = 0xf;
- RefreshedCylinders = 1;
- SectorXMax = 0x3f7;
- HashTableSize = 0x100000;
- SectorXMin = 1000;
- SectorZMin = 0;
- OBCount = 0xa0000;
- NewbieStartPositionX = 0;
- VeteranStartPositionX = 0;
- __s = &local_101c;
- Marks = 0;
- NewbieStartPositionZ = 0;
- VeteranStartPositionY = 0;
- VeteranStartPositionZ = 0;
- pcVar9 = DATAPATH;
- sprintf((char *)__s,"%s/map.dat");
- // try { // try from 0805f114 to 0805f118 has its CatchHandler @ 0805f850
- TReadScriptFile::TReadScriptFile((TReadScriptFile *)(Ident + 0x1c));
- // try { // try from 0805f126 to 0805f5e6 has its CatchHandler @ 0805f831
- TReadScriptFile::open((TReadScriptFile *)(Ident + 0x1c),(char *)__s,(int)pcVar9);
- do {
- TReadScriptFile::nextToken((TReadScriptFile *)(Ident + 0x1c));
- if (stack0xffffb004 == 0) {
- TReadScriptFile::close((TReadScriptFile *)(Ident + 0x1c),(int)__s);
- if (SectorXMin < 1) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorXMin";
- }
- else if (SectorXMax < 0x7ff) {
- if (SectorYMin < 1) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorYMin";
- }
- else if (SectorYMax < 0x7ff) {
- if (SectorZMin < 0) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorZMin";
- }
- else if (SectorZMax < 0x10) {
- if (SectorXMax < SectorXMin) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "SectorXMin is greater than SectorXMax";
- }
- else if (SectorYMax < SectorYMin) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "SectorYMin is greater than SectorYMax";
- }
- else if (SectorZMax < SectorZMin) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "SectorZMin is greater than SectorZMax";
- }
- else if ((OBCount & 0x7fffU) == 0) {
- if (OBCount < 1) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for CacheSize";
- }
- else {
- if (0x7fffffff < (uint)OBCount) {
- OBCount = OBCount + 0x7fff;
- }
- OBCount = OBCount >> 0xf;
- if (HashTableSize < 1) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for Objects";
- }
- else if ((HashTableSize - 1U & HashTableSize) == 0) {
- if (NewbieStartPositionX == 0) {
- puVar6 = (undefined4 *)
- __cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "no start position for newbies specified";
- }
- else {
- if (VeteranStartPositionX != 0) {
- // try { // try from 0805f6c4 to 0805f6c8 has its CatchHandler @ 0805f850
- TReadScriptFile::~TReadScriptFile
- ((TReadScriptFile *)(Ident + 0x1c),(int)__s);
- return;
- }
- puVar6 = (undefined4 *)
- __cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "no start position for veterans specified";
- }
- }
- else {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "Objects must be a power of 2";
- }
- }
- }
- else {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "CacheSize must be a multiple of 32768";
- }
- }
- else {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorZMax";
- }
- }
- else {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorYMax";
- }
- }
- else {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4,__s,pcVar9);
- *puVar6 = "illegal value for SectorXMax";
- }
- // WARNING: Subroutine does not return
- // try { // try from 0805f6f9 to 0805f6fd has its CatchHandler @ 0805f831
- __cxa_throw(puVar6,char_const*::typeinfo,0);
- }
- uVar8 = stack0xffffb004 == 1;
- if (!(bool)uVar8) {
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"Identifier expected");
- }
- pcVar2 = TReadScriptFile::getIdentifier((TReadScriptFile *)(Ident + 0x1c));
- strcpy((char *)&DepotNumber,pcVar2);
- __s = (int *)0x3d;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'=');
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorxmin";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorXMin = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorxmax";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorXMax = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorymin";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorYMin = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorymax";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorYMax = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorzmin";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorZMin = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0xb;
- piVar10 = &DepotNumber;
- pcVar2 = "sectorzmax";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- SectorZMax = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 0x13;
- piVar10 = &DepotNumber;
- pcVar2 = "refreshedcylinders";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- RefreshedCylinders = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 8;
- piVar10 = &DepotNumber;
- pcVar2 = "objects";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- HashTableSize = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 10;
- piVar10 = &DepotNumber;
- pcVar2 = "cachesize";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- OBCount = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- }
- iVar7 = 6;
- piVar10 = &DepotNumber;
- pcVar2 = "depot";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'(');
- iVar7 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- pTVar1 = (TReadScriptFile *)(Ident + 0x1c);
- TReadScriptFile::readSymbol(pTVar1,',');
- TReadScriptFile::nextToken(pTVar1);
- if (stack0xffffb004 != 3) {
- TReadScriptFile::error(pTVar1,"town name expected");
- }
- pcVar2 = TReadScriptFile::getString((TReadScriptFile *)(Ident + 0x1c));
- sVar4 = strlen(pcVar2);
- uVar8 = sVar4 == 0x13;
- if (0x13 < sVar4) {
- TReadScriptFile::error((TReadScriptFile *)(Ident + 0x1c),"town name too long");
- }
- pcVar2 = TReadScriptFile::getString((TReadScriptFile *)(Ident + 0x1c));
- pTVar5 = vector<TDepotInfo>::operator()(&DepotInfo,iVar7);
- strcpy(pTVar5->Town,pcVar2);
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),',');
- pTVar5 = vector<TDepotInfo>::operator()(&DepotInfo,iVar7);
- iVar7 = TReadScriptFile::readNumber((TReadScriptFile *)(Ident + 0x1c));
- pTVar5->Size = iVar7;
- __s = (int *)0x29;
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),')');
- }
- iVar7 = 5;
- piVar10 = &DepotNumber;
- pcVar2 = "mark";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- TReadScriptFile::readSymbol((TReadScriptFile *)(Ident + 0x1c),'(');
- pcVar9 = TReadScriptFile::readString((TReadScriptFile *)(Ident + 0x1c));
- pTVar3 = vector<TMark>::operator()(&Mark,Marks);
- pTVar1 = (TReadScriptFile *)(Ident + 0x1c);
- strcpy(pTVar3->Name,pcVar9);
- TReadScriptFile::readSymbol(pTVar1,',');
- vector<TMark>::operator()(&Mark,Marks);
- pTVar3 = vector<TMark>::operator()(&Mark,Marks);
- pcVar9 = (char *)&pTVar3->y;
- vector<TMark>::operator()(&Mark,Marks);
- TReadScriptFile::readCoordinate(pTVar1);
- __s = (int *)0x29;
- TReadScriptFile::readSymbol(pTVar1,')');
- Marks = Marks + 1;
- uVar8 = Marks == 0;
- }
- iVar7 = 0xc;
- piVar10 = &DepotNumber;
- pcVar2 = "newbiestart";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- piVar10 = &NewbieStartPositionY;
- __s = &NewbieStartPositionX;
- TReadScriptFile::readCoordinate((TReadScriptFile *)(Ident + 0x1c));
- pcVar9 = (char *)piVar10;
- }
- iVar7 = 0xd;
- piVar10 = &DepotNumber;
- pcVar2 = "veteranstart";
- do {
- if (iVar7 == 0) break;
- iVar7 = iVar7 + -1;
- uVar8 = (char)*piVar10 == *pcVar2;
- piVar10 = (int *)((int)piVar10 + 1);
- pcVar2 = pcVar2 + 1;
- } while ((bool)uVar8);
- if ((bool)uVar8) {
- piVar10 = &VeteranStartPositionY;
- __s = &VeteranStartPositionX;
- TReadScriptFile::readCoordinate((TReadScriptFile *)(Ident + 0x1c));
- pcVar9 = (char *)piVar10;
- }
- } while( true );
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void InitMap(void)
-
-{
- int iVar1;
- ulong *puVar2;
- TObjectBlock **ppTVar3;
- ulong *puVar4;
- int i_2;
- matrix3d<TSector*> *this;
- TObject *pTVar5;
- TObjectBlock *pTVar6;
- int j;
- int iVar7;
- int iVar8;
- TObject *Help;
- int i_1;
- int iVar9;
- int i;
- int iVar10;
-
- // try { // try from 0805f869 to 0805f879 has its CatchHandler @ 0805fad4
- ReadMapConfig();
- this = (matrix3d<TSector*> *)operator_new(0x1c);
- // try { // try from 0805f8bd to 0805f8c1 has its CatchHandler @ 0805fab7
- matrix3d<TSector*>::matrix3d
- (this,SectorXMin,SectorXMax,SectorYMin,SectorYMax,SectorZMin,SectorZMax,(TSector *)0x0
- );
- Sector = this;
- // try { // try from 0805f8c8 to 0805fa67 has its CatchHandler @ 0805fad4
- DeleteSwappedSectors();
- iVar10 = 0;
- ObjectBlock = (TObjectBlock **)malloc(OBCount << 2);
- if (0 < OBCount) {
- do {
- ppTVar3 = ObjectBlock;
- pTVar6 = (TObjectBlock *)malloc(0x100000);
- ppTVar3[iVar10] = pTVar6;
- iVar10 = iVar10 + 1;
- } while (iVar10 < OBCount);
- }
- iVar10 = OBCount;
- ppTVar3 = ObjectBlock;
- iVar9 = 0;
- if (0 < OBCount) {
- iVar1 = OBCount + -1;
- do {
- iVar7 = 0;
- do {
- iVar8 = iVar7 + 1;
- ppTVar3[iVar9]->Object[iVar7].NextObject.ObjectID =
- (ulong)(ppTVar3[iVar9]->Object + iVar7 + 1);
- iVar7 = iVar8;
- } while (iVar8 < 0x7fff);
- if (iVar9 < iVar1) {
- ppTVar3[iVar9]->Object[0x7fff].NextObject.ObjectID = (ulong)ppTVar3[iVar9 + 1];
- }
- else {
- ppTVar3[iVar9]->Object[0x7fff].NextObject.ObjectID = 0;
- }
- iVar9 = iVar9 + 1;
- } while (iVar9 < iVar10);
- }
- FirstFreeObject = (*ObjectBlock)->Object;
- HashTableMask = HashTableSize - 1;
- HashTableData = (ulong *)malloc(HashTableSize << 2);
- HashTableType = (uchar *)malloc(HashTableSize);
- memset(HashTableType,0,HashTableSize);
- HashTableFree = HashTableSize + -1;
- *HashTableType = 0xff;
- puVar4 = HashTableData;
- if (FirstFreeObject == (TObject *)0x0) {
- SwapSector();
- }
- pTVar5 = FirstFreeObject;
- if (FirstFreeObject == (TObject *)0x0) {
- error("GetFreeObjectSlot: Kein freier Platz mehr.\n");
- pTVar5 = (TObject *)0x0;
- }
- else {
- puVar2 = &FirstFreeObject->ObjectID;
- FirstFreeObject = (TObject *)(FirstFreeObject->NextObject).ObjectID;
- *puVar2 = 0;
- (pTVar5->NextObject).ObjectID = 0;
- (pTVar5->Container).ObjectID = 0;
- (pTVar5->Type).TypeID = 0;
- pTVar5->Attributes[0] = 0;
- pTVar5->Attributes[1] = 0;
- pTVar5->Attributes[2] = 0;
- pTVar5->Attributes[3] = 0;
- }
- *puVar4 = (ulong)pTVar5;
- iVar10 = 0;
- do {
- CronHashTable[iVar10] = -1;
- iVar10 = iVar10 + 1;
- } while (iVar10 < 0x7ff);
- CronEntries = 0;
- LoadMap();
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: x
-
-void ExitMap(bool save)
-
-{
- TObjectBlock **ppTVar1;
- int iVar2;
- TSector **ppTVar3;
- int iVar4;
- int iVar5;
- int i;
- int iVar6;
- matrix3d<TSector*> *pmVar7;
- int local_1c;
- int z;
- int y;
- int x;
-
- if (save) {
- SaveMap();
- }
- iVar6 = 0;
- free(HashTableType);
- free(HashTableData);
- if (0 < OBCount) {
- do {
- ppTVar1 = ObjectBlock + iVar6;
- iVar6 = iVar6 + 1;
- free(*ppTVar1);
- } while (iVar6 < OBCount);
- }
- free(ObjectBlock);
- y = SectorXMin;
- iVar6 = SectorXMax;
- iVar4 = SectorYMax;
- pmVar7 = Sector;
- if (SectorXMin <= SectorXMax) {
- do {
- z = SectorYMin;
- iVar5 = SectorZMax;
- if (SectorYMin <= iVar4) {
- do {
- local_1c = SectorZMin;
- if (SectorZMin <= iVar5) {
- do {
- iVar5 = z - pmVar7->ymin;
- iVar6 = local_1c - pmVar7->zmin;
- iVar4 = y - pmVar7->xmin;
- if ((((iVar4 < 0) || (iVar2 = pmVar7->dx, iVar2 <= iVar4)) ||
- (iVar5 < 0)) ||
- (((pmVar7->dy <= iVar5 || (iVar6 < 0)) || (pmVar7->dz <= iVar6)))) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",
- iVar4 + pmVar7->xmin,iVar5 + pmVar7->ymin,iVar6 + pmVar7->zmin
- );
- ppTVar3 = pmVar7->entry;
- pmVar7 = Sector;
- }
- else {
- ppTVar3 = pmVar7->entry +
- iVar6 * iVar2 * pmVar7->dy + iVar5 * iVar2 + iVar4;
- }
- if (*ppTVar3 != (TSector *)0x0) {
- iVar5 = z - pmVar7->ymin;
- iVar6 = local_1c - pmVar7->zmin;
- iVar4 = y - pmVar7->xmin;
- if (((iVar4 < 0) || (iVar2 = pmVar7->dx, iVar2 <= iVar4)) ||
- ((iVar5 < 0 ||
- (((pmVar7->dy <= iVar5 || (iVar6 < 0)) || (pmVar7->dz <= iVar6))
- )))) {
- error("matrix3d::operator(): Ungueltiger Index %d/%d/%d.\n",
- iVar4 + pmVar7->xmin,iVar5 + pmVar7->ymin,
- iVar6 + pmVar7->zmin);
- ppTVar3 = pmVar7->entry;
- }
- else {
- ppTVar3 = pmVar7->entry +
- iVar6 * iVar2 * pmVar7->dy + iVar5 * iVar2 + iVar4;
- }
- free(*ppTVar3);
- pmVar7 = Sector;
- }
- local_1c = local_1c + 1;
- iVar5 = SectorZMax;
- iVar4 = SectorYMax;
- } while (local_1c <= SectorZMax);
- }
- z = z + 1;
- iVar6 = SectorXMax;
- } while (z <= iVar4);
- }
- y = y + 1;
- } while (y <= iVar6);
- }
- if (pmVar7 != (matrix3d<TSector*> *)0x0) {
- if (pmVar7->entry != (TSector **)0x0) {
- operator_delete__(pmVar7->entry);
- }
- operator_delete(pmVar7);
- }
- DeleteSwappedSectors();
- return;
-}
-
-
-
void __tcf_0(void *param_1)
{
diff --git a/reference/types.hh b/reference/types.hh
index 6b59f4d..b2c0719 100644
--- a/reference/types.hh
+++ b/reference/types.hh
@@ -355,13 +355,6 @@ struct TShortwayPoint {
struct TShortwayPoint *NextToExpand;
};
-struct TCronEntry {
- struct Object Obj;
- ulong RoundNr;
- int Previous;
- int Next;
-};
-
struct TMonsterhome {
int Race;
int x;
@@ -407,13 +400,6 @@ struct TCondition {
int Number;
};
-struct TSector {
- struct Object MapCon[32][32];
- ulong TimeStamp;
- uchar Status;
- uchar MapFlags;
-};
-
struct TChannel {
ulong Moderator;
char ModeratorName[30];
@@ -545,13 +531,6 @@ struct listIterator<storeunit<TNode,_256>_> { // Original name: listIterator<sto
struct listnode<storeunit<TNode,_256>_> *actNode;
};
-struct TMark {
- char Name[20];
- int x;
- int y;
- int z;
-};
-
struct store<TNode,256> {
struct list<storeunit<TNode,_256>_> *Units;
union storeitem<TNode> *firstFreeItem;
@@ -607,11 +586,6 @@ struct listIterator<storeunit<TPlayerIndexInternalNode,_100>_> { // Original nam
};
-struct TDepotInfo {
- char Town[20];
- int Size;
-};
-
struct fifoIterator<TStatement> {
struct fifo<TStatement> *Fifo;
int Position;
@@ -729,18 +703,6 @@ struct TMoveUseDatabase {
int NumberOfRules;
};
-struct TObject {
- ulong ObjectID;
- struct Object NextObject;
- struct Object Container;
- struct ObjectType Type;
- ulong Attributes[4];
-};
-
-struct TObjectBlock {
- struct TObject Object[32768];
-};
-
struct TFindCreatures {
int startx;
int starty;
diff --git a/src/common.hh b/src/common.hh
index 124dd84..02cad88 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -154,6 +154,8 @@ struct TReadBuffer: TReadStream {
// REGULAR FUNCTIONS
// =========================================================================
TReadBuffer(uint8 *Data, int Size);
+ TReadBuffer(const TWriteBuffer &WriteBuffer)
+ : TReadBuffer(WriteBuffer.Data, WriteBuffer.Size) {}
// VIRTUAL FUNCTIONS
// =========================================================================
@@ -177,7 +179,7 @@ struct TWriteStream {
virtual void writeFlag(bool Flag); // VTABLE[0]
virtual void writeByte(uint8 Byte) = 0; // VTABLE[1]
virtual void writeWord(uint16 Word); // VTABLE[2]
- virtual void writeQuad(uint16 Quad); // VTABLE[3]
+ virtual void writeQuad(uint32 Quad); // VTABLE[3]
virtual void writeString(const char *String); // VTABLE[4]
virtual void writeBytes(const uint8 *Buffer, int Count); // VTABLE[5]
};
@@ -186,6 +188,7 @@ struct TWriteBuffer: TWriteStream {
// REGULAR FUNCTIONS
// =========================================================================
TWriteBuffer(uint8 *Data, int Size);
+ void reset(void) { this->Position = 0; }
// VIRTUAL FUNCTIONS
// =========================================================================
diff --git a/src/config.cc b/src/config.cc
index bae583a..0be4eec 100644
--- a/src/config.cc
+++ b/src/config.cc
@@ -128,14 +128,10 @@ void ReadConfig(void){
return;
}
- // TODO(fusion): Probably some `expectIdentifier` function inlined?
- // It seems `getIdentifier` also does the same check so this one is
- // redundant?
- if(Script.Token != IDENTIFIER){
- Script.error("Identifier expected");
- }
-
- char *Identifier = Script.getIdentifier();
+ // TODO(fusion): If the following `readSymbol` calls `nextToken`, then the
+ // buffer the identifier is in will get wiped. (UPDATE: Yes, the original
+ // version copies it into a local stack buffer, lol.)
+ const char *Identifier = Script.readIdentifier();
Script.readSymbol('=');
// TODO(fusion): Ughh... Get rid of all `strcpy`s. A malicious configuration
diff --git a/src/crcombat.cc b/src/crcombat.cc
new file mode 100644
index 0000000..6b0df86
--- /dev/null
+++ b/src/crcombat.cc
@@ -0,0 +1,31 @@
+#include "creature.hh"
+
+TCombat::TCombat(void){
+ this->Master = NULL;
+ this->EarliestAttackTime = 0;
+ this->EarliestDefendTime = 0;
+ this->LastDefendTime = 0;
+ this->LatestAttackTime = 0;
+ this->AttackMode = 2;
+ this->ChaseMode = 0;
+ this->SecureMode = 1;
+ this->AttackDest = 0;
+ this->Following;
+ this->Shield = NONE;
+ this->Close = NONE;
+ this->Missile = NONE;
+ this->Throw = NONE;
+ this->Wand = NONE;
+ this->Ammo = NONE;
+ this->Fist = false;
+ this->CombatDamage = 0;
+ this->ActCombatEntry = 0;
+ for(int i = 0; i < NARRAY(this->CombatList); i += 1){
+ this->CombatList[i].ID = 0;
+ this->CombatList[i].Damage = 0;
+ this->CombatList[i].TimeStamp = 0;
+ }
+ this->LearningPoints = 0;
+}
+
+// TODO(fusion): Probably better to figure out how Object work.
diff --git a/src/creature.cc b/src/creature.cc
index effac42..e2cb5ce 100644
--- a/src/creature.cc
+++ b/src/creature.cc
@@ -2,6 +2,56 @@
#include "enums.hh"
+TCreature::TCreature(void) :
+ TSkillBase(),
+ Combat(),
+ ToDoList(0, 20, 10)
+{
+ this->Master = this;
+ this->ID = 0;
+ this->NextHashEntry = NULL;
+ this->NextChainCreature = 0;
+ this->Murderer[0] = 0;
+ this->startx = 0;
+ this->starty = 0;
+ this->startz = 0;
+ this->posx = 0;
+ this->posy = 0;
+ this->posz = 0;
+ this->Direction = 0;
+ this->Radius = INT_MAX;
+ this->IsDead = false;
+ this->LoseInventory = 2;
+ this->LoggingOut = false;
+ this->LogoutAllowed = false;
+ this->EarliestLogoutRound = 0;
+ this->EarliestProtectionZoneRound = 0;
+ this->EarliestYellRound = 0;
+ this->EarliestTradeChannelRound = 0;
+ this->EarliestSpellTime = 0;
+ this->EarliestMultiuseTime = 0;
+ this->EarliestWalkTime = 0;
+ this->LifeEndRound = 0;
+ this->FirstKnowingConnection = NULL;
+ this->SummonedCreatures = 0;
+ this->FireDamageOrigin = 0;
+ this->PoisonDamageOrigin = 0;
+ this->EnergyDamageOrigin = 0;
+ this->CrObject = NONE;
+ this->ActToDo = 0;
+ this->NrToDo = 0;
+ this->NextWakeup = 0;
+ this->Stop = false;
+ this->LockToDo = false;
+ this->Connection = NULL;
+
+ for(int i = 0; i < NARRAY(this->Skills); i += 1){
+ this->NewSkill((uint16)i, this);
+ }
+}
+
+// TODO(fusion): Probably better to figure out how TCombat and Object work.
+
// Creature Functions
//==============================================================================
// TODO(fusion): This was the first function I attempted to cleanup but soon
diff --git a/src/creature.hh b/src/creature.hh
index a147091..a6f7678 100644
--- a/src/creature.hh
+++ b/src/creature.hh
@@ -17,7 +17,7 @@ struct TCombatEntry{
struct TCombat{
// REGULAR FUNCTIONS
// =========================================================================
- // TODO
+ TCombat(void);
// DATA
// =========================================================================
diff --git a/src/enums.hh b/src/enums.hh
index d4ba042..5124936 100644
--- a/src/enums.hh
+++ b/src/enums.hh
@@ -99,6 +99,27 @@ enum GAMESTATE: int {
GAME_ENDING = 3,
};
+enum INSTANCEATTRIBUTE: int {
+ CONTENT = 0,
+ CHESTQUESTNUMBER = 1,
+ AMOUNT = 2,
+ KEYNUMBER = 3,
+ KEYHOLENUMBER = 4,
+ DOORLEVEL = 5,
+ DOORQUESTNUMBER = 6,
+ DOORQUESTVALUE = 7,
+ CHARGES = 8,
+ TEXTSTRING = 9,
+ EDITOR = 10,
+ CONTAINERLIQUIDTYPE = 11,
+ POOLLIQUIDTYPE = 12,
+ ABSTELEPORTDESTINATION = 13,
+ RESPONSIBLE = 14,
+ REMAININGEXPIRETIME = 15,
+ SAVEDEXPIRETIME = 16,
+ REMAININGUSES = 17,
+};
+
enum KNOWNCREATURESTATE: int {
KNOWNCREATURE_FREE = 0,
KNOWNCREATURE_UPTODATE = 1,
diff --git a/src/main.cc b/src/main.cc
index 1efdf4a..736f2f2 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1,5 +1,6 @@
#include "common.hh"
#include "config.hh"
+#include "map.hh"
#include <signal.h>
#include <sys/time.h>
@@ -222,7 +223,7 @@ static void InitAll(void){
//InitWriter();
//InitReader();
//InitObjects();
- //InitMap();
+ InitMap();
//InitInfo();
//InitMoveUse();
//InitMagic();
@@ -246,7 +247,7 @@ static void ExitAll(void){
//ExitMoveUse();
//ExitInfo();
//ExitHouses();
- //ExitMap(SaveMapOn);
+ ExitMap(SaveMapOn);
//ExitObjects();
//ExitReader();
//ExitWriter();
diff --git a/src/map.cc b/src/map.cc
new file mode 100644
index 0000000..604fd6b
--- /dev/null
+++ b/src/map.cc
@@ -0,0 +1,1418 @@
+#include "map.hh"
+#include "containers.hh"
+
+// NOTE(fusion): This is used by hash table entries and sectors to tell whether
+// they're currently loaded or swapped out to disk.
+enum : uint8 {
+ STATUS_FREE = 0,
+ STATUS_LOADED = 1,
+ STATUS_SWAPPED = 2,
+
+ // TODO(fusion): It seems this is only used with the `NONE` entry in the
+ // hash table. I haven't seen it used **yet** but It may have a purpose
+ // aside from preventing swap outs.
+ STATUS_PERMANENT = 255,
+};
+
+// NOTE(fusion): This is used to determine precedence order of different objects
+// in a tile.
+enum : int {
+ PRIORITY_BANK = 0,
+ PRIORITY_CLIP = 1,
+ PRIORITY_BOTTOM = 2,
+ PRIORITY_TOP = 3,
+ PRIORITY_CREATURE = 4,
+ PRIORITY_OTHER = 5,
+};
+
+static int OBCount;
+static int SectorXMin;
+static int SectorXMax;
+static int SectorYMin;
+static int SectorYMax;
+static int SectorZMin;
+static int SectorZMax;
+static int RefreshedCylinders;
+static int NewbieStartPositionX;
+static int NewbieStartPositionY;
+static int NewbieStartPositionZ;
+static int VeteranStartPositionX;
+static int VeteranStartPositionY;
+static int VeteranStartPositionZ;
+
+static matrix3d<TSector*> *Sector;
+static TObjectBlock **ObjectBlock;
+static TObject *FirstFreeObject;
+static TObject **HashTableData;
+static uint8 *HashTableType;
+static uint32 HashTableSize;
+static uint32 HashTableMask;
+static uint32 HashTableFree;
+static uint32 ObjectCounter;
+
+static vector<TCronEntry> CronEntry(0, 256, 256);
+static int CronHashTable[2047];
+static int CronEntries;
+
+static vector<TDepotInfo> DepotInfo(0, 4, 5);
+static int Depots;
+
+static vector<TMask> Mark(0, 4, 5);
+static int Marks;
+
+static TDynamicWriteBuffer HelpBuffer(0x10000);
+
+// Map Init/Exit and Helpers
+// =============================================================================
+static void SwapObject(TWriteBinaryFile *File, Object Obj, uint32 FileNumber){
+ ASSERT(Obj != NONE);
+
+ // NOTE(fusion): Does it make sense to swap an object that isn't loaded? We
+ // were originally calling `Object::exists` that would swap in the object's
+ // sector if it was swapped out. We should probably have an assertion here.
+ if(HashTableType[Obj.ObjectID & HashTableMask] != STATUS_LOADED){
+ error("SwapObject: Object doesn't exists or is not currently loaded.\n");
+ return;
+ }
+
+ TObject *Entry = HashTableData[Obj.ObjectID & HashTableMask];
+ if(Entry->ObjectID != Obj.ObjectID){
+ error("SwapObject: Übergebenes Objekt existiert nicht.\n");
+ return;
+ }
+
+ File->writeBytes((const uint8*)Entry, sizeof(TObject));
+ if(Entry->Type.getFlag(CONTAINER) || Entry->Type.getFlag(CHEST)){
+ Object Current = Obj.getAttribute(CONTENT);
+ while(Current != NONE){
+ Object Next = Current.getNextObject();
+ SwapObject(File, Current, FileNumber);
+ Current = Next;
+ }
+ }
+
+ PutFreeObjectSlot(Entry);
+ HashTableType[EntryIndex] = STATUS_SWAPPED;
+ HashTableData[EntryIndex] = (TObject*)FileNumber;
+}
+
+static void SwapSector(void){
+ static uint32 FileNumber = 0;
+
+ TSector *Oldest = NULL;
+ int OldestSectorX = 0;
+ int OldestSectorY = 0;
+ int OldestSectorZ = 0;
+ uint32 OldestTimeStamp = RoundNr + 1;
+
+ ASSERT(Sector != NULL);
+ for(int SectorZ = SectorZMin; SectorZ <= SectorZMax; SectorZ += 1)
+ for(int SectorY = SectorYMin; SectorY <= SectorYMax; SectorY += 1)
+ for(int SectorX = SectorXMin; SectorX <= SectorXMax; SectorX += 1){
+ TSector *CurrentSector = *Sector->at(SectorX, SectorY, SectorZ);
+ if(CurrentSector != NULL
+ && CurrentSector->Status == STATUS_LOADED
+ && CurrentSector->TimeStamp < OldestTimeStamp){
+ Oldest = CurrentSector;
+ OldestSectorX = SectorX;
+ OldestSectorY = SectorY;
+ OldestSectorZ = SectorZ;
+ OldestTimeStamp = CurrentSector->TimeStamp;
+ }
+ }
+
+ if(Oldest == NULL){
+ error("FATAL ERROR in SwapSector: Es kann kein Sektor ausgelagert werden.\n");
+ abort();
+ }
+
+ char FileName[4096];
+ do{
+ FileNumber += 1; // NOTE(fusion): Let it wrap naturally.
+ snprintf(FileName, sizeof(FileName), "%s/%010u.swp", SAVEPATH, FileNumber);
+ }while(FileExists(FileName));
+
+ TWriteBinaryFile File;
+ try{
+ File.open(FileName);
+ print(2, "Lagere Sektor %d/%d/%d aus...\n", OldestSectorX, OldestSectorY, OldestSectorZ);
+ File.writeQuad((uint32)OldestSectorX);
+ File.writeQuad((uint32)OldestSectorY);
+ File.writeQuad((uint32)OldestSectorZ);
+ // TODO(fusion): I think tiles are stored in column major order but it doesn't
+ // really matter as long as optimize for sequential access.
+ for(int X = 0; X < 32; X += 1){
+ for(int Y = 0; Y < 32; Y += 1){
+ SwapObject(&File, Oldest->MapCon[X][Y], FileNumber);
+ }
+ }
+ Oldest->Status = STATUS_SWAPPED;
+ File.close();
+ }catch(const char *str){
+ error("FATAL ERROR in SwapSector: Kann Datei \"%s\" nicht anlegen.\n", FileName);
+ error("# Fehler: %s\n", str);
+ abort();
+ }
+}
+
+static void UnswapSector(uint32 FileNumber){
+ char FileName[4096];
+ snprintf(FileName, sizeof(FileName), "%s/%010u.swp", SAVEPATH, FileNumber);
+
+ TReadBinaryFile File;
+ try{
+ File.open(FileName);
+ int SectorX = (int)File.readQuad();
+ int SectorY = (int)File.readQuad();
+ int SectorZ = (int)File.readQuad();
+ print(2, "Lagere Sector %d/%d/%d ein...\n", SectorX, SectorY, SectorZ);
+
+ ASSERT(Sector != NULL);
+ TSector *LoadingSector = *Sector->at(SectorX, SectorY, SectorZ);
+ if(LoadingSector == NULL){
+ error("UnswapSector: Sektor %d/%d/%d existiert nicht.\n", SectorX, SectorY, SectorZ);
+ File.close();
+ return;
+ }
+
+ if(LoadingSector->Status != STATUS_SWAPPED){
+ error("UnswapSector: Sektor %d/%d/%d ist nicht ausgelagert.\n", SectorX, SectorY, SectorZ);
+ File.close();
+ return;
+ }
+
+ int Size = File.getSize();
+ while(File.getPosition() < Size){
+ TObject Entry;
+ File.readBytes((uint8*)&Entry, sizeof(TObject));
+
+ uint32 EntryIndex = Entry.ObjectID & HashTableMask;
+ if(HashTableType[EntryIndex] == STATUS_SWAPPED){
+ // NOTE(fusion): Make sure we only allocate the object if we confirm
+ // its status. The original code would call `readBytes` on the result
+ // from `GetFreeObjectSlot()` directly and would then leak it if the
+ // entry status was not `STATUS_SWAPPED`.
+ TObject *EntryPointer = GetFreeObjectSlot();
+ *EntryPointer = Entry;
+ HashTableData[EntryIndex] = EntryPointer;
+ HashTableType[EntryIndex] = STATUS_LOADED;
+ }else{
+ error("UnswapSector: Objekt %u existiert schon.\n", Entry.ObjectID);
+ }
+ }
+ LoadingSector->Status = STATUS_LOADED;
+ File.close();
+ unlink(FileName);
+ }catch(const char *str){
+ error("FATAL ERROR in UnswapSector: Kann Datei \"%s\" nicht lesen.\n", FileName);
+ error("# Fehler: %s\n", str);
+ abort();
+ }
+}
+
+static void DeleteSwappedSectors(void){
+ DIR *SwapDir = opendir(SAVEPATH);
+ if(SwapDir == NULL){
+ error("DeleteSwappedSectors: Unterverzeichnis %s nicht gefunden\n", SAVEPATH);
+ return;
+ }
+
+ char FilePath[4096];
+ while(dirent *DirEntry = readdir(SwapDir)){
+ if(DirEntry->d_type == DT_REG){
+ // NOTE(fusion): `DirEntry->d_name` will only contain the filename
+ // so we need to assemble the actual file path (relative in this
+ // case) to properly unlink it. Windows has the same behavior with
+ // its `FindFirstFile`/`FindNextFile` API.
+ const char *FileExt = findLast(DirEntry->d_name, '.');
+ if(FileExt != NULL && strcmp(FileExt, ".swp") == 0){
+ snprintf(FilePath, sizeof(FilePath), "%s/%s", SAVEPATH, DirEntry->d_name);
+ unlink(FilePath);
+ }
+ }
+ }
+
+ closedir(SwapDir);
+}
+
+static void LoadObjects(TReadScriptFile *Script, TWriteStream *Stream, bool Skip){
+ int Depth = 1;
+ bool ParseAttribute = false;
+ Script->readSymbol('{');
+ Script->nextToken();
+ while(true){
+ if(!ParseAttribute){
+ if(Script->Token != SPECIAL){
+ int TypeID = Script->getNumber();
+ if(!ObjectTypeExists(TypeID)){
+ Script->error("unknown object type");
+ }
+
+ if(!Skip){
+ Stream->writeWord((uint16)TypeID);
+ }
+
+ ParseAttribute = true;
+ }else{
+ char Special = Script->getSpecial();
+ if(Special == '}'){
+ if(!Skip){
+ Stream->writeWord(0xFFFF);
+ }
+
+ Depth -= 1;
+ if(Depth <= 0){
+ break;
+ }
+ }else if(Special != ','){
+ Script->error("expected comma");
+ }
+ }
+ Script->nextToken();
+ }else{
+ if(Script->Token != SPECIAL){
+ int Attribute = GetInstanceAttributeByName(Script->getIdentifier());
+ if(Attribute == -1){
+ Script->error("unknown attribute");
+ }
+
+ Script->readSymbol('=');
+ if(!Skip){
+ Stream->writeByte((uint8)Attribute);
+ }
+
+ if(Attribute == CONTENT){
+ Script->readSymbol('{');
+ Depth += 1;
+ ParseAttribute = false;
+ }else if(Attribute == TEXTSTRING || Attribute == EDITOR){
+ const char *String = Script->readString();
+ if(!Skip){
+ Stream->writeString(String);
+ }
+ }else{
+ int Number = Script->readNumber();
+ if(!Skip){
+ Stream->writeQuad((uint32)Number);
+ }
+ }
+
+ Script->nextToken();
+ }else{
+ // NOTE(fusion): Attributes are key-value pairs separated by whitespace.
+ // If we find a special token (probably ',' or '}'), then we're done
+ // parsing attributes for the current object.
+ if(!Skip){
+ Stream->writeByte(0xFF);
+ }
+ ParseAttribute = false;
+ }
+ }
+ }
+}
+
+static void LoadObjects(TReadStream *Stream, Object Con){
+ int Depth = 1;
+ Object Obj = NONE;
+ while(true){
+ if(Obj == NONE){
+ int TypeID = (int)Stream->readWord();
+ if(TypeID != 0xFFFF){
+ ObjectCounter += 1;
+ ObjectType ObjType(TypeID);
+
+ if(ObjType.isBodyContainer()){
+ Obj = GetContainerObject(Con, (TypeID - 1));
+ }else{
+ Obj = AppendObject(Con, ObjType);
+ }
+ }else{
+ Obj = Con;
+ Con = Con.getContainer();
+ Depth -= 1;
+ if(Depth <= 0){
+ break;
+ }
+ }
+ }else{
+ int Attribute = (int)Stream->readByte();
+ if(Attribute != 0xFF){
+ if(Attribute == CONTENT){
+ Con = Obj;
+ Obj = NONE;
+ Depth += 1;
+ }else if(Attribute == TEXTSTRING || Attribute == EDITOR){
+ uint32 Value = AddDynamicString(Stream->readString());
+ Obj.setAttribute(Attribute, Value);
+ }else if(Attribute != REMAININGEXPIRETIME){
+ uint32 Value = Stream->readQuad();
+ Obj.setAttribute(Attribute, Value);
+ }else{
+ uint32 Value = Stream->readQuad();
+ if(Value != 0){
+ CronChange(Obj, (int)Value);
+ }
+ }
+ }else{
+ Obj = NONE;
+ }
+ }
+ }
+}
+
+static void InitSector(int SectorX, int SectorY, int SectorZ){
+ ASSERT(Sector);
+ if(*Sector->at(SectorX, SectorY, SectorZ) != NULL){
+ error("InitSector: Sektor %d/%d/%d existiert schon.\n", SectorX, SectorY, SectorZ);
+ return;
+ }
+
+ TSector *NewSector = (TSector*)malloc(sizeof(TSector));
+ for(int X = 0; X < 32; X += 1){
+ for(int Y = 0; Y < 32; Y += 1){
+ Object MapCon = CreateObject();
+ // NOTE(fusion): `Attributes[0]` is probably the object id of the
+ // first object in the container.
+ Access(MapCon)->Attributes[1] = SectorX * 32 + X;
+ Access(MapCon)->Attributes[2] = SectorY * 32 + Y;
+ Access(MapCon)->Attributes[3] = SectorZ;
+ NewSector->MapCon[X][Y] = MapCon;
+ }
+ }
+ NewSector->TimeStamp = RoundNr;
+ NewSector->Status = STATUS_LOADED;
+ NewSector->MapFlags = 0;
+
+ *Sector->at(SectorX, SectorY, SectorZ) = NewSector;
+}
+
+static void LoadSector(const char *FileName, int SectorX, int SectorY, int SectorZ){
+ if(SectorX < SectorXMin || SectorXMax < SectorX
+ || SectorY < SectorYMin || SectorYMax < SectorY
+ || SectorZ < SectorZMin || SectorZMax < SectorZ){
+ return;
+ }
+
+ InitSector(SectorX, SectorY, SectorZ);
+
+ ASSERT(Sector != NULL);
+ TSector *LoadingSector = *Sector->at(SectorX, SectorY, SectorZ);
+ ASSERT(LoadingSector != NULL);
+
+ TReadScriptFile Script;
+ try{
+ Script.open(FileName);
+ print(1, "Lade Sektor %d/%d/%d ...\n", SectorX, SectorY, SectorZ);
+
+ int OffsetX = -1;
+ int OffsetY = -1;
+ while(true){
+ Script.nextToken();
+ if(Script.Token == ENDOFFILE){
+ Script.close();
+ return;
+ }
+
+ if(Script.Token == SPECIAL && Script.getSpecial() == ','){
+ continue;
+ }
+
+ if(Script.Token == BYTES){
+ uint8 *SectorOffset = Script.getBytesequence();
+ OffsetX = (int)SectorOffset[0];
+ OffsetY = (int)SectorOffset[1];
+ Script.readSymbol(':');
+ continue;
+ }
+
+ if(Script.Token != IDENTIFIER){
+ Script.error("next map point expected");
+ }
+
+ if(OffsetX == -1 || OffsetY == -1){
+ Script.error("coordinate expected");
+ }
+
+ const char *Identifier = Script.getIdentifier();
+ if(strcmp(Identifier, "refresh") == 0){
+ LoadingSector->MapFlags |= 1;
+ AccessObject(LoadingSector->MapCon[OffsetX][OffsetY])->Attributes[3] |= 0x100;
+ }else if(strcmp(Identifier, "nologout") == 0){
+ LoadingSector->MapFlags |= 2;
+ AccessObject(LoadingSector->MapCon[OffsetX][OffsetY])->Attributes[3] |= 0x200;
+ }else if(strcmp(Identifier, "protectionzone") == 0){
+ LoadingSector->MapFlags |= 4;
+ AccessObject(LoadingSector->MapCon[OffsetX][OffsetY])->Attributes[3] |= 0x400;
+ }else if(strcmp(Identifier, "content") == 0){
+ Script.readSymbol('=');
+ HelpBuffer.reset();
+ LoadObjects(&Script, &HelpBuffer, false);
+ TReadBuffer ReadBuffer(HelpBuffer);
+ LoadObjects(&ReadBuffer, LoadingSector->MapCon[OffsetX][OffsetY]);
+ }else{
+ Script.error("unknown map flag");
+ }
+ }
+ }catch(const char *str){
+ error("LoadSector: Kann Datei \"%s\" nicht lesen.\n", FileName);
+ error("# Fehler: %s\n", str);
+ throw "Cannot load sector";
+ }
+}
+
+static void LoadMap(void){
+ DIR *MapDir = opendir(MAPPATH);
+ if(MapDir == NULL){
+ error("LoadMap: Unterverzeichnis %s nicht gefunden\n", MAPPATH);
+ throw "Cannot load map";
+ }
+
+ print(1, "Lade Karte ...\n");
+ ObjectCounter = 0;
+
+ char FilePath[4096];
+ while(dirent *DirEntry = readdir(MapDir)){
+ if(DirEntry->d_type == DT_REG){
+ // NOTE(fusion): See note in `DeleteSwappedSectors`.
+ const char *FileExt = findLast(DirEntry->d_name, '.');
+ if(FileExt != NULL && strcmp(FileExt, ".sec") == 0){
+ int SectorX, SectorY, SectorZ;
+ if(sscanf("%d-%d-%d.sec", &SectorX, &SectorY, &SectorZ) == 3){
+ snprintf(FilePath, sizeof(FilePath), "%s/%s", SAVEPATH, DirEntry->d_name);
+ LoadSector(FilePath, SectorX, SectorY, SectorZ);
+ SectorCounter += 1;
+ }
+ }
+ }
+ }
+
+ closedir(MapDir);
+ print(1, "%d Sektoren geladen.\n", SectorCounter);
+ print(1, "%d Objekte geladen.\n", ObjectCounter);
+}
+
+//SaveObjects
+//SaveObjects
+
+void SaveSector(char *FileName, int SectorX, int SectorY, int SectorZ){
+ ASSERT(Sector);
+ TSector *SavingSector = *Sector->at(SectorX, SectorY, SectorZ);
+ if(!SavingSector){
+ return;
+ }
+
+ bool Empty = true;
+ TWriteScriptFile Script;
+ try{
+ Script.open(FileName);
+ print(1, "Speichere Sektor %d/%d/%d ...\n", SectorX, SectorY, SectorZ);
+
+ Script.writeText("# Tibia - graphical Multi-User-Dungeon");
+ Script.writeLn();
+ Script.writeText("# Data for sector ");
+ Script.writeNumber(SectorX);
+ Script.writeText("/");
+ Script.writeNumber(SectorY);
+ Script.writeText("/");
+ Script.writeNumber(SectorZ);
+ Script.writeLn();
+ Script.writeLn();
+
+ for(int X = 0; X < 32; X += 1){
+ for(int Y = 0; Y < 32; Y += 1){
+ Object First = Object(SavingSector->MapCon[X][Y].getAttribute(CONTENT));
+ uint8 Flags = GetMapContainerFlags(SavingSector->MapCon[X][Y]);
+ if(First != NONE || Flags != 0){
+ Script.writeNumber(X);
+ Script.writeText("-");
+ Script.writeNumber(Y);
+ Script.writeText(": ");
+
+ int AttrCount = 0;
+
+ if(Flags & 1){
+ if(AttrCount > 0){
+ Script.writeText(", ");
+ }
+ Script.writeText("Refresh");
+ AttrCount += 1;
+ }
+
+ if(Flags & 2){
+ if(AttrCount > 0){
+ Script.writeText(", ");
+ }
+ Script.writeText("NoLogout");
+ AttrCount += 1;
+ }
+
+ if(Flags & 4){
+ if(AttrCount > 0){
+ Script.writeText(", ");
+ }
+ Script.writeText("ProtectionZone");
+ AttrCount += 1;
+ }
+
+ if(First != NONE){
+ if(AttrCount > 0){
+ Script.writeText(", ");
+ }
+ Script.writeText("Content=");
+ HelpBuffer.reset();
+ SaveObjects(First, &HelpBuffer, false);
+ TReadBuffer ReadBuffer(HelpBuffer);
+ SaveObjects(&ReadBuffer, &Script);
+ AttrCount += 1;
+ }
+
+ Script.writeLn();
+ Empty = false;
+ }
+ }
+ }
+
+ Script.close();
+ if(Empty){
+ error("SaveSector: Sektor %d/%d/%d ist leer.\n", SectorX, SectorY, SectorZ);
+ unlink(FileName);
+ }
+ }catch(const char *str){
+ error("SaveSector: Kann Datei %s nicht schreiben.\n", FileName);
+ error("# Fehler: %s\n", str);
+ }
+}
+
+static void SaveMap(void){
+ // NOTE(fusion): I guess this could happen if we're already saving the map
+ // and a signal causes `exit` to execute cleanup functions registered with
+ // `atexit`, among which is `ExitAll` which may call `SaveMap` throught
+ // `ExitMap`.
+ static bool SavingMap = false;
+ if(SavingMap){
+ error("SaveMap: Karte wird schon gespeichert.\n");
+ return;
+ }
+
+ SavingMap = true;
+ print(1, "Speichere Karte ...\n");
+ ObjectCounter = 0;
+
+ char FileName[4096];
+ for(int SectorZ = SectorZMin; SectorZ <= SectorZMax; SectorZ += 1)
+ for(int SectorY = SectorYMin; SectorY <= SectorYMax; SectorY += 1)
+ for(int SectorX = SectorXMin; SectorX <= SectorXMax; SectorX += 1){
+ snprintf(FileName, sizeof(FileName), "%s/%04d-%04d-%02d.sec",
+ MAPPATH, SectorX, SectorY, SectorZ);
+ SaveSector(FileName, SectorX, SectorY, SectorZ);
+ }
+
+ print(1, "%d Objekte gespeichert.\n", ObjectCounter);
+ SavingMap = false;
+}
+
+static void ResizeHashTable(void){
+ uint32 OldSize = HashTableSize;
+ uint32 NewSize = OldSize * 2;
+ ASSERT(ISPOW2(OldSize));
+ ASSERT(NewSize > OldSize);
+
+ // TODO(fusion): See note below.
+ error("FATAL ERROR in ResizeHashTable: Resizing the object hash table is"
+ " currently disabled. You may increase `Objects` in the map config"
+ " from %d to %d, to achieve the same effect.", OldSize, NewSize);
+ abort();
+
+ error("INFO: HashTabelle zu klein. Größe wird verdoppelt auf %d.\n", NewSize);
+
+ uint32 NewMask = NewSize - 1;
+ TObject **NewData = (TObject**)malloc(NewSize * sizeof(TObject*));
+ uint8 *NewType = (uint8*)malloc(NewSize * sizeof(uint8));
+ memset(NewType, 0, NewSize * sizeof(uint8));
+
+ // TODO(fusion): This rehash loop doesn't make a lot of sense. It wants to
+ // access all existing objects but doing so would cause all sectors to be
+ // swapped in at some time or another. This may be bad for performance but
+ // the real problem is that `UnswapSector` may swap out some other sector
+ // whose objects were already put into `NewType` and `NewData`, causing
+ // multiple object ids to reference the same `TObject`.
+ // Looking at some of the logs included with this executable, it doesn't
+ // look like this function was ever called which explains why it wasn't fixed
+ // earlier.
+ // It would be possible to do this rehashing without swapping anything out,
+ // if we stored ObjectID somewhere (maybe `HashTableData`). Doubling the size
+ // of the table means there are two possible indices for each previous entry,
+ // and we can only determine which one to actually move it with the ObjectID.
+
+ NewType[0] = STATUS_PERMANENT;
+ NewData[0] = HashTableData[0];
+ for(uint32 i = 1; i < NewSize; i += 1){
+ if(HashTableType[i] != STATUS_FREE){
+ if(HashTableType[i] == STATUS_SWAPPED){
+ UnswapSector((uintptr)HashTableData[i]);
+ }
+
+ if(HashTableType[i] == STATUS_LOADED){
+ TObject *Entry = HashTableData[i];
+ NewType[Entry->ObjectID & NewMask] = STATUS_LOADED;
+ NewData[Entry->ObjectID & NewMask] = Entry;
+ }else{
+ error("ResizeHashTable: Fehler beim Reorganisieren der HashTabelle.\n");
+ }
+ }
+ }
+
+ free(HashTableData);
+ free(HashTableType);
+
+ HashTableData = NewData;
+ HashTableType = NewType;
+ HashTableSize = NewSize;
+ HashTableMask = NewMask;
+ HashTableFree += (NewSize - OldSize);
+}
+
+static TObject *GetFreeObjectSlot(void){
+ if(FirstFreeObject == NULL){
+ SwapSector();
+ }
+
+ TObject *Entry = FirstFreeObject;
+ if(Entry == NULL){
+ error("GetFreeObjectSlot: Kein freier Platz mehr.\n");
+ return NULL;
+ }
+
+ // NOTE(fusion): The next object pointer was originally stored in `Entry->NextObject.ObjectID`
+ // which is a problem when compiling in 64 bits mode. For this reason, I've changed it to be
+ // stored at the beggining of `TObject`.
+ FirstFreeObject = *((TObject**)Entry);
+
+ memset(Entry, 0, sizeof(TObject));
+
+ return Entry;
+}
+
+static void PutFreeObjectSlot(TObject *Entry){
+ if(Entry == NULL){
+ error("PutFreeObjectSlot: Entry ist NULL.\n");
+ return;
+ }
+
+ // NOTE(fusion): See note in `GetFreeObjectSlot`, just above.
+ *((TObject**)Entry) = FirstFreeObject;
+ FirstFreeObject = Entry;
+}
+
+static void ReadMapConfig(void){
+ OBCount = 0xA0000;
+ SectorXMin = 1000;
+ SectorXMax = 1015;
+ SectorYMin = 1000;
+ SectorYMax = 1015;
+ SectorZMin = 0;
+ SectorZMax = 15;
+ RefreshedCylinders = 1;
+ NewbieStartPositionX = 0;
+ NewbieStartPositionY = 0;
+ NewbieStartPositionZ = 0;
+ VeteranStartPositionX = 0;
+ VeteranStartPositionY = 0;
+ VeteranStartPositionZ = 0;
+ HashTableSize = 0x100000;
+ Marks = 0;
+ Depots = 0;
+
+ char FileName[4096];
+ snprintf(FileName, sizeof(FileName), "%s/map.dat", DATAPATH);
+
+ TReadScriptFile Script;
+ Script.open(FileName);
+ while(true){
+ Script.nextToken();
+ if(Script.Token == ENDOFFILE){
+ Script.close():
+ break;
+ }
+
+ const char *Identifier = Script.readIdentifier();
+ Script.readSymbol('=');
+
+ if(strcmp(Identifier, "sectorxmin") == 0){
+ SectorXMin = Script.readNumber();
+ }else if(strcmp(Identifier, "sectorxmax") == 0){
+ SectorXMax = Script.readNumber();
+ }else if(strcmp(Identifier, "sectorymin") == 0){
+ SectorYMin = Script.readNumber();
+ }else if(strcmp(Identifier, "sectorymax") == 0){
+ SectorYMax = Script.readNumber();
+ }else if(strcmp(Identifier, "sectorzmin") == 0){
+ SectorZMin = Script.readNumber();
+ }else if(strcmp(Identifier, "sectorzmax") == 0){
+ SectorZMax = Script.readNumber();
+ }else if(strcmp(Identifier, "refreshedcylinders") == 0){
+ RefreshedCylinders = Script.readNumber();
+ }else if(strcmp(Identifier, "objects") == 0){
+ HashTableSize = (uint32)Script.readNumber();
+ }else if(strcmp(Identifier, "cachesize") == 0){
+ OBCount = Script.readNumber();
+ }else if(strcmp(Identifier, "depot") == 0){
+ int DepotIndex = 0;
+ TDepotInfo TempInfo = {};
+ Script.readSymbol('(');
+ DepotIndex = Script.readNumber();
+ Script.readSymbol(',');
+ const char *Town = Script.readString();
+ if(strlen(Town) >= NARRAY(TempInfo.Town)){
+ Script.error("town name too long");
+ }
+ strcpy(TempInfo.Town, Town);
+ Script.readSymbol(',');
+ TempInfo.Size = Script.readNumber();
+ Script.readSymbol(')');
+ *DepotInfo.at(DepotIndex) = TempInfo;
+ }else if(strcmp(Identifier, "mark") == 0){
+ TMark TempMark = {};
+ Script.readSymbol('(');
+ const char *Name = Script.readString();
+ if(strlen(Name) >= NARRAY(TempMark.Name)){
+ Script.error("mark name too long");
+ }
+ strcpy(TempMark.Name, Name);
+ Script.readSymbol(',');
+ Script.readCoordinate(&TempMark.x, &TempMark.y, &TempMark.z);
+ Script.readSymbol(')');
+ *Mark.at(Marks) = TempMark;
+ Marks += 1;
+ }else if(strcmp(Identifier, "newbiestart") == 0){
+ Script.readCoordinate(
+ &NewbieStartPositionX,
+ &NewbieStartPositionY,
+ &NewbieStartPositionZ);
+ }else if(strcmp(Identifier, "veteranstart") == 0){
+ Script.readCoordinate(
+ &VeteranStartPositionX,
+ &VeteranStartPositionY,
+ &VeteranStartPositionZ);
+ }else{
+ // TODO(fusion):
+ //error("Unknown map configuration key \"%s\"", Identifier);
+ }
+ }
+
+ // NOTE(fusion): If each sector is 32 x 32 tiles and the whole world is
+ // 65535 x 65535 tiles, then the maximum number of sectors is 65535 / 32
+ // which is the 2047 used below. We should probably define these contants.
+ // Notice that sectors at the edge of the XY-plane are also considered
+ // invalid, probably to add some buffer to avoid wrapping or other types
+ // of problems.
+
+ if(SectorXMin <= 0){
+ throw "illegal value for SectorXMin";
+ }
+
+ if(SectorXMax >= 2047){
+ throw "illegal value for SectorXMax";
+ }
+
+ if(SectorYMin <= 0){
+ throw "illegal value for SectorYMin";
+ }
+
+ if(SectorYMax >= 2047){
+ throw "illegal value for SectorYMax";
+ }
+
+ if(SectorZMin < 0){
+ throw "illegal value for SectorZMin";
+ }
+
+ if(SectorZMax > 15){
+ throw "illegal value for SectorZMax";
+ }
+
+ if(SectorXMin > SectorXMax){
+ throw "SectorXMin is greater than SectorXMax";
+ }
+
+ if(SectorYMin > SectorYMax){
+ throw "SectorYMin is greater than SectorYMax";
+ }
+
+ if(SectorZMin > SectorZMax){
+ throw "SectorZMin is greater than SectorZMax";
+ }
+
+ // TODO(fusion): Just align up from whatever value we got? And use `ObjectsPerBlock`?
+ if(OBCount % 32768 != 0){
+ throw "CacheSize must be a multiple of 32768";
+ }
+
+ if(OBCount <= 0){
+ throw "illegal value for CacheSize";
+ }
+
+ OBCount /= 32768;
+
+ if(HashTableSize <= 0){
+ throw "illegal value for Objects";
+ }
+
+ if(!ISPOW2(HashTableSize)){
+ throw "Objects must be a power of 2";
+ }
+
+ if(NewbieStartPositionX == 0){
+ throw "no start position for newbies specified";
+ }
+
+ if(VeteranStartPositionX == 0){
+ throw "no start position for veterans specified";
+ }
+}
+
+void InitMap(void){
+ ReadMapConfig();
+
+ Sector = new matrix3d<TSector*>(SectorXMin, SectorXMax,
+ SectorYMin, SectorYMax, SectorZMin, SectorZMax, NULL);
+
+ DeleteSwappedSectors();
+
+ // NOTE(fusion): Object storage is FIXED and determined at startup.
+ ObjectBlock = (TObjectBlock**)malloc(OBCount * sizeof(TObjectBlock*));
+ for(int i = 0; i < OBCount; i += 1){
+ ObjectBlock[i] = (TObjectBlock*)malloc(sizeof(TObjectBlock));
+ }
+
+ // NOTE(fusion): Setup free object list. See note in `GetFreeObjectSlot`.
+ constexpr int ObjectsPerBlock = NARRAY(TObjectBlock::Object);
+ for(int i = 0; i < OBCount; i += 1){
+ for(int j = 0; j < ObjectsPerBlock; j += 1){
+ *((TObject**)&ObjectBlock[i]->Object[j]) = &ObjectBlock[i]->Object[j + 1];
+ }
+
+ if(i < (OBCount - 1)){
+ // NOTE(fusion): Link last entry of this block, with the first entry of the next one.
+ *((TObject**)&ObjectBlock[i]->Object[ObjectsPerBlock - 1]) = &ObjectBlock[i + 1]->Object[0];
+ }else{
+ // NOTE(fusion): End of free object list.
+ *((TObject**)&ObjectBlock[i]->Object[ObjectsPerBlock - 1]) = NULL;
+ }
+ }
+ FirstFreeObject = &ObjectBlock[0]->Object[0];
+
+ // NOTE(fusion): Initialize object hash table.
+ ASSERT(ISPOW2(HashTableSize));
+ HashTableMask = HashTableSize - 1;
+ HashTableData = (TObject**)malloc(HashTableSize * sizeof(TObject*));
+ HashTableType = (uint8*)malloc(HashTableSize * sizeof(uint8));
+ memset(HashTableType, 0, HashTableSize * sizeof(uint8));
+ HashTableFree = HashTableSize - 1;
+ // NOTE(fusion): This is probably reserved for `NONE`.
+ HashTableType[0] = STATUS_PERMANENT;
+ HashTableData[0] = GetFreeObjectSlot();
+
+ // NOTE(fusion): Initialize cron hash table (whatever that is).
+ for(int i = 0; i < NARRAY(CronHashTable); i += 1){
+ CronHashTable[i] = -1;
+ }
+ CronEntries = 0;
+
+ LoadMap();
+}
+
+void ExitMap(bool Save){
+ if(Save){
+ SaveMap();
+ }
+
+ free(HashTableData);
+ free(HashTableType);
+
+ for(int i = 0; i < OBCount; i += 1){
+ free(ObjectBlock[i]);
+ }
+ free(ObjectBlock);
+
+ if(Sector != NULL){
+ for(int SectorZ = SectorZMin; SectorZ <= SectorZMax; SectorZ += 1)
+ for(int SectorY = SectorYMin; SectorY <= SectorYMax; SectorY += 1)
+ for(int SectorX = SectorXMin; SectorX <= SectorXMax; SectorX += 1){
+ TSector *CurrentSector = *Sector->at(SectorX, SectorY, SectorZ);
+ if(CurrentSector != NULL){
+ free(CurrentSector);
+ }
+ }
+ delete Sector;
+ }
+
+ DeleteSwappedSectors();
+}
+
+// TODO(fusion): For some reason this is not a member of `Object`?
+static TObject *AccessObject(Object Obj){
+ if(Obj == NONE){
+ error("AccessObject: Ungültige Objektnummer Null.\n");
+ return HashTableData[0];
+ }
+
+ uint32 Index = Obj.ObjectID
+ if(HashTableType[Index] == STATUS_SWAPPED){
+ UnswapSector((uintptr)HashTableData[Index]);
+ }
+
+ if(HashTableType[Index] == STATUS_LOADED && HashTableData[Index]->ObjectID == Obj.ObjectID){
+ return HashTableData[Index];
+ }else{
+ return HashTableData[0];
+ }
+}
+
+static Object CreateObject(void){
+ static uint32 NextObjectID = 1;
+
+ // NOTE(fusion): Load factor of 1/16.
+ if(HashTableFree < (HashTableSize / 16)){
+ ResizeHashTable();
+ }
+
+ // NOTE(fusion): If we properly manage the load factor and the number of free
+ // entries, we should have no trouble finding an empty table entry here. Use
+ // a bounded loop nevertheless, just to be safe.
+ for(uint32 i = 0; i < HashTableSize; i += 1){
+ if(HashTableType[NextObjectID & HashTableMask] == 0)
+ break;
+ NextObjectID += 1;
+ }
+ ASSERT(HashTableType[NextObjectID & HashTableMask] == 0);
+
+ TObject *Entry = GetFreeObjectSlot();
+ if(Entry == NULL){
+ error("CreateObject: Kann Objekt nicht anlegen.\n");
+ return NONE;
+ }
+
+ Entry->ObjectID = NextObjectID;
+ HashTableData[NextObjectID & HashTableMask] = Entry;
+ HashTableType[NextObjectID & HashTableMask] = STATUS_LOADED;
+ HashTableFree -= 1;
+ IncrementObjectCounter();
+
+ return Object(NextObjectID);
+}
+
+// DestroyObject
+// DeleteObject
+
+// Object
+// =============================================================================
+bool Object::exists(void){
+ if(*this == NONE){
+ return false;
+ }
+
+ uint32 Index = this->ObjectID & HashTableMask;
+ if(HashTableType[Index] == STATUS_SWAPPED){
+ UnswapSector(HashTableData[Index]);
+ }
+
+ return HashTableType[Index] == STATUS_LOADED
+ && HashTableData[Index]->ObjectID == this->ObjectID;
+}
+
+ObjectType Object::getObjectType(void){
+ return AccessObject(*this)->Type;
+}
+
+void Object::setObjectType(ObjectType Type){
+ AccessObject(*this)->Type = Type;
+}
+
+Object Object::getNextObject(void){
+ return AccessObject(*this)->NextObject;
+}
+
+void Object::setNextObject(Object NextObject){
+ AccessObject(*this)->NextObject = NextObject;
+}
+
+Object Object::getContainer(void){
+ return AccessObject(*this)->Container;
+}
+
+void Object::setContainer(Object Container){
+ AccessObject(*this)->Container = Container;
+}
+
+uint32 Object::getCreatureID(void){
+ // TODO(fusion): We call `AccessObject` once in `getObjectType` then again
+ // after checking the TypeID, when we could call it once to check both type
+ // and access `Attributes[1]`.
+
+ if(!this->getObjectType().isCreatureContainer()){
+ error("Object::getCreatureID: Objekt ist keine Kreatur.\n");
+ return 0;
+ }
+
+ return AccessObject(*this)->Attributes[1];
+}
+
+uint32 Object::getAttribute(INSTANCEATTRIBUTE Attribute){
+ ObjectType ObjType = this->getObjectType();
+ int AttributeOffset = ObjType.getAttributeOffset(Attribute);
+ if(AttributeOffset == -1){
+ error("Object::getAttribute: Flag für Attribut %d bei Objekttyp %d nicht gesetzt.\n",
+ Attribute, ObjType.TypeID);
+ return 0;
+ }
+
+ if(AttributeOffset < 0 || AttributeOffset >= NARRAY(TObject::Attributes)){
+ error("Object::getAttribute: Ungültiger Offset %d für Attribut %d bei Objekttyp %d.\n",
+ AttributeOffset, Attribute, ObjType.TypeID);
+ return 0;
+ }
+
+ return AccessObject(*this)->Attributes[AttributeOffset];
+}
+
+void Object::setAttribute(INSTANCEATTRIBUTE Attribute, uint32 Value){
+ ObjectType ObjType = this->getObjectType();
+ int AttributeOffset = ObjType.getAttributeOffset(Attribute);
+ if(AttributeOffset == -1){
+ error("Object::setAttribute: Flag für Attribut %d bei Objekttyp %d nicht gesetzt.\n",
+ Attribute, ObjType.TypeID);
+ return;
+ }
+
+ if(AttributeOffset < 0 || AttributeOffset >= NARRAY(TObject::Attributes)){
+ error("Object::setAttribute: Ungültiger Offset %d für Attribut %d bei Objekttyp %d.\n",
+ AttributeOffset, Attribute, ObjType.TypeID);
+ return;
+ }
+
+ if(Value == 0){
+ if(Attribute == AMOUNT || Attribute == POOLLIQUIDTYPE || Attribute == CHARGES){
+ Value = 1;
+ }else if(Attribute == REMAININGUSES){
+ Value = ObjType.getAttribute(TOTALUSES);
+ }
+ }
+
+ AccessObject(*this)->Attributes[AttributeOffset] = Value;
+}
+
+// Object Functions
+// =============================================================================
+void ChangeObject(Object Obj, ObjectType NewType){
+ if(!Obj.exists()){
+ error("ChangeObject: Übergebenes Objekt existiert nicht.\n");
+ return;
+ }
+
+ uint32 Amount = 0;
+ uint32 SavedExpireTime = 0;
+ int Delay = -1;
+
+ ObjectType OldType = Obj.getObjectType();
+ if(!OldType.isMapContainer()){
+ if(OldType.getFlag(CUMULATIVE)){
+ Amount = Obj.getAttribute(AMOUNT);
+ }
+
+ if(OldType.getFlag(EXPIRE)){
+ SavedExpireTime = CronStop(Obj);
+ if(NewType.getFlag(CUMULATIVE)){
+ Amount = 1;
+ }
+ }
+
+ if(OldType.getFlag(TEXT) && !NewType.getFlag(TEXT)){
+ DeleteDynamicString(Obj.getAttribute(TEXTSTRING));
+ Obj.setAttribute(TEXTSTRING, 0);
+
+ DeleteDynamicString(Obj.getAttribute(EDITOR));
+ Obj.setAttribute(EDITOR, 0);
+ }
+
+ if(OldType.getFlag(EXPIRESTOP)){
+ uint32 Value = Obj.getAttribute(SAVEDEXPIRETIME);
+ if(Value != 0){
+ Delay = (int)Value;
+ }
+ }
+
+ if(OldType.getFlag(MAGICFIELD)){
+ Obj.setAttribute(RESPONSIBLE, 0);
+ }
+ }
+
+ Obj.setObjectType(NewType);
+
+ if(NewType.getFlag(CUMULATIVE)){
+ if(Amount == 0){
+ Amount = 1;
+ }
+ Obj.setAttribute(AMOUNT, Amount);
+ }
+
+ if(NewType.getFlag(RUNE)){
+ if(Obj.getAttribute(CHARGES) == 0){
+ Obj.setAttribute(CHARGES, 1);
+ }
+ }
+
+ if(NewType.getFlag(LIQUIDPOOL)){
+ if(Obj.getAttribute(POOLLIQUIDTYPE) == 0){
+ Obj.setAttribute(POOLLIQUIDTYPE, 1); // LIQUID_TYPE_NONE (?)
+ }
+ }
+
+ if(NewType.getFlag(WEAROUT)){
+ if(Obj.getAttribute(REMAININGUSES) == 0){
+ Obj.setAttribute(REMAININGUSES, NewType.getAttribute(TOTALUSES));
+ }
+ }
+
+ if(NewType.getFlag(EXPIRESTOP)){
+ Obj.setAttribute(SAVEDEXPIRETIME, SavedExpireTime);
+ }
+
+ CronExpire(Obj, Delay);
+}
+
+int GetObjectPriority(Object Obj){
+ if(!Obj.exists()){
+ error("GetObjectPriority: Übergebenes Objekt existiert nicht.\n");
+ return -1;
+ }
+
+ int ObjPriority;
+ ObjectType ObjType = Obj.getObjectType();
+ if(ObjType.getFlag(BANK)){
+ ObjPriority = PRIORITY_BANK;
+ }else if(ObjType.getFlag(CLIP)){
+ ObjPriority = PRIORITY_CLIP;
+ }else if(ObjType.getFlag(BOTTOM)){
+ ObjPriority = PRIORITY_BOTTOM;
+ }else if(ObjType.getFlag(TOP)){
+ ObjPriority = PRIORITY_TOP;
+ }else if(ObjType.isCreatureContainer()){
+ ObjPriority = PRIORITY_CREATURE;
+ }else{
+ ObjPriority = PRIORITY_OTHER;
+ }
+ return ObjPriority;
+}
+
+void PlaceObject(Object Obj, Object Con, bool Append){
+ if(!Obj.exists()){
+ error("PlaceObject: Übergebenes Objekt existiert nicht.\n");
+ return;
+ }
+
+ if(!Con.exists()){
+ error("PlaceObject: Übergebener Container existiert nicht.\n");
+ return;
+ }
+
+ ObjectType ConType = Con.getObjectType();
+ if(!ConType.getFlag(CONTAINER) || !ConType.getFlag(CHEST)){
+ error("PlaceObject: Con (%d) ist kein Container.\n", ConType.TypeID);
+ return;
+ }
+
+ Object Prev = NONE;
+ Object Cur(Con.getAttribute(CONTENT));
+ if(ConType.isMapContainer()){
+ // TODO(fusion): Review. The loop below was a bit rough but it seems that
+ // append is forced for PRIORITY_CREATURE and PRIORITY_OTHER. We should
+ // confirm this whenever the server is up and running. It'll show.
+ int ObjPriority = GetObjectPriority(Obj);
+ Append = Append
+ || ObjPriority == PRIORITY_CREATURE
+ || ObjPriority == PRIORITY_OTHER;
+
+ while(Cur != NONE){
+ int CurPriority = GetObjectPriority(Cur);
+ if(CurPriority == ObjPriority
+ && (ObjPriority == PRIORITY_BANK
+ || ObjPriority == PRIORITY_BOTTOM
+ || ObjPriority == PRIORITY_TOP)){
+ // TODO(fusion): Replace item? I think the client might assert
+ // if there are two of these objects on a single tile.
+ const char *PriorityString = "";
+ if(ObjPriority == PRIORITY_BACK){
+ PriorityString == "BANK";
+ }else if(ObjPriority == PRIORITY_BOTTOM){
+ PriorityString == "BOTTOM";
+ }else if(ObjPriority == PRIORITY_TOP){
+ PriorityString == "TOP";
+ }
+
+ int CoordX, CoordY, CoordZ;
+ GetObjectCoordinates(Con, CoordX, CoordY, CoordZ);
+
+ ObjectType ObjType = Obj.getObjectType();
+ ObjectType CurType = Cur.getObjectType();
+ error("PlaceObject: Zwei %s-Objekte (%d und %d) auf Feld [%d,%d,%d].\n",
+ PriorityString, ObjType.TypeID, CurType.TypeID, CoordX, CoordY, CoordZ);
+ }
+
+ if(Append && CurPriority > ObjPriority) break;
+ if(!Append && CurPriority >= ObjPriority) break;
+
+ Prev = Cur;
+ Cur = Cur.getNextObject();
+ }
+ }else{
+ if(Append){
+ while(Cur != NONE){
+ Prev = Cur;
+ Cur = Cur.getNextObject();
+ }
+ }
+ }
+
+ if(Prev != NONE){
+ Prev.setNextObject(Obj);
+ }else{
+ Con.setAttribute(CONTENT, Obj.ObjectID);
+ }
+ Obj.setNextObject(Cur);
+ Obj.setContainer(Con);
+}
+
+Object AppendObject(Object Con, ObjectType Type){
+ if(!Con.exists()){
+ error("AppendObject: Übergebener Container existiert nicht.\n");
+ return NONE;
+ }
+
+ Object Obj = CreateObject();
+ ChangeObject(Obj, Type);
+ PlaceObject(Obj, Con, true);
+ return Obj;
+}
+
+Object GetFirstContainerObject(Object Con){
+ if(Con == NONE){
+ error("GetFirstContainerObject: Übergebener Container existiert nicht.\n");
+ return NONE;
+ }
+
+ ObjectType ConType = Con.getObjectType(Con);
+ if(!ConType.getFlag(CONTAINER) && !ConType.getFlag(CHEST)){
+ error("GetFirstContainerObject: Con (%d) ist kein Container.\n", ConType.TypeID);
+ return NONE;
+ }
+
+ return Object(Con.getAttribute(CONTENT));
+}
+
+Object GetContainerObject(Object Con, int Index){
+ if(Index < 0){
+ error("GetContainerObject: Ungültige laufende Nummer %d.\n", Index);
+ return NONE;
+ }
+
+ if(!Con.exists()){
+ error("GetContainerObject: Übergebener Container existiert nicht.\n");
+ return NONE;
+ }
+
+ Object Current = GetFirstContainerObject(Con);
+ while(Current != NONE && Index > 0){
+ Current = CurrentObject.getNextObject();
+ }
+
+ return Current;
+}
+
+void GetObjectCoordinates(Object Obj, int *x, int *y, int *z){
+ if(!Obj.exists()){
+ error("GetObjectCoordinates: Übergebenes Objekt existiert nicht.\n");
+ *x = 0;
+ *y = 0;
+ *z = 0;
+ return;
+ }
+
+ // TODO(fusion): I'm not sure I like this approach with calling `AccessObject`
+ // multiple times for the same object. Furthermore, using `Object::getObjectType`
+ // (at least until now) is very weird when we could just get the same information
+ // from the `TObject` which we'll access ANYWAYS.
+
+ while(true){
+ if(Obj.getObjectType().isMapContainer())
+ break;
+ Obj = Obj.getContainer();
+ }
+
+ *x = AccessObject(Obj)->Attributes[1];
+ *y = AccessObject(Obj)->Attributes[2];
+
+ // NOTE(fusion): The first 8 bits of `Attributes[3]` holds the Z coordinate
+ // of a map container. The next 8 bits holds the flags of a map container.
+ *z = AccessObject(Obj)->Attributes[3] & 0xFF;
+
+ return;
+}
+
+uint8 GetMapContainerFlags(Object Obj){
+ if(!Obj.exists() || !Obj.getObjectType().isMapContainer()){
+ error("GetMapContainerFlags: Objekt ist kein MapContainer.\n");
+ return 0;
+ }
+
+ // NOTE(fusion): See note in `GetObjectCoordinates` just above.
+ return (uint8)(AccessObject(Obj)->Attributes[3] >> 8);
+}
+
+Object GetMapContainer(int x, int y, int z){
+ int SectorX = x / 32;
+ int SectorY = y / 32;
+ int SectorZ = z;
+
+ if(SectorX < SectorXMin || SectorXMax < SectorX
+ || SectorY < SectorYMin || SectorYMax < SectorY
+ || SectorZ < SectorZMin || SectorZMax < SectorZ){
+ return NONE;
+ }
+
+ ASSERT(Sector != NULL);
+ TSector *ConSector = *Sector->at(SectorX, SectorY, SectorZ);
+ if(ConSector == NULL){
+ return NONE;
+ }
+
+
+ int OffsetX = x % 32;
+ int OffsetY = y % 32;
+ ConSector->TimeStamp = RoundNr;
+ return ConSector->MapCon[OffsetX][OffsetY];
+}
+
+Object GetMapContainer(Object Obj){
+ if(!Obj.exists()){
+ error("GetMapContainer: Übergebenes Objekt existiert nicht\n")
+ return NONE;
+ }
+
+ while(true){
+ if(Obj.getObjectType().isMapContainer())
+ break;
+ Obj = Obj.getContainer();
+ }
+
+ return Obj;
+}
+
+Object GetFirstObject(int x, int y, int z){
+ Object MapCon = GetMapContainer(x, y, z);
+ if(MapCon != NONE){
+ return Object(MapCon.getAttribute(CONTENT));
+ }else{
+ return NONE;
+ }
+}
diff --git a/src/map.hh b/src/map.hh
index 298d190..590fb41 100644
--- a/src/map.hh
+++ b/src/map.hh
@@ -2,25 +2,76 @@
#define TIBIA_MAP_HH_ 1
#include "common.hh"
-
-// TODO(fusion): I'm not sure whether to put these.
+#include "objects.hh"
struct Object {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ Object(void) { this->ObjectID = 0; }
+ Object(uint32 ObjectID) { this->ObjectID = ObjectID; }
+ bool exists(void);
+
+ ObjectType getObjectType(void);
+ void setObjectType(ObjectType Type);
+
+ Object getNextObject(void);
+ void setNextObject(Object NextObject);
+
+ Object getContainer(void);
+ void setContainer(Object Con);
+
+ uint32 getCreatureID(void);
+ //void setCreatureID(uint32 CreatureID); //??
+
+ uint32 getAttribute(INSTANCEATTRIBUTE Attribute);
+ void setAttribute(INSTANCEATTRIBUTE Attribute, uint32 Value);
+
+ // DATA
+ // =========================================================================
uint32 ObjectID;
};
-constexpr Object NONE = {};
+constexpr Object NONE;
-struct ObjectType {
- int TypeID;
+struct TObject {
+ uint32 ObjectID;
+ Object NextObject;
+ Object Container;
+ ObjectType Type;
+ uint32 Attributes[4];
};
-struct TObjectType {
- char *Name;
- char *Description;
- uint8 Flags[9];
- uint32 Attributes[62];
- int AttributeOffsets[18];
+struct TObjectBlock {
+ TObject Object[32768];
};
-#endif //TIBIA_MAP_HH_ \ No newline at end of file
+struct TSector {
+ Object MapCon[32][32];
+ uint32 TimeStamp;
+ uint8 Status;
+ uint8 MapFlags;
+};
+
+struct TDepotInfo {
+ char Town[20];
+ int Size;
+};
+
+struct TMark {
+ char Name[20];
+ int x;
+ int y;
+ int z;
+};
+
+struct TCronEntry {
+ Object Obj;
+ uint32 RoundNr;
+ int Previous;
+ int Next;
+};
+
+void InitMap(void);
+void ExitMap(bool Save);
+
+#endif //TIBIA_MAP_HH_
diff --git a/src/objects.cc b/src/objects.cc
new file mode 100644
index 0000000..0119088
--- /dev/null
+++ b/src/objects.cc
@@ -0,0 +1,196 @@
+#include "objects.hh"
+
+static vector<TObjectType> ObjectTypes(0, 5000, 1000);
+static ObjectType SpecialObjects[49];
+
+static FLAG TypeAttributeFlags[62] = {
+ BANK, // WAYPOINTS
+ CONTAINER, // CAPACITY
+ CHANGEUSE, // CHANGETARGET
+ KEYDOOR, // KEYDOORTARGET
+ NAMEDOOR, // NAMEDOORTARGET
+ LEVELDOOR, // LEVELDOORTARGET
+ QUESTDOOR, // QUESTDOORTARGET
+ FOOD, // NUTRITION
+ INFORMATION, // INFORMATIONTYPE
+ TEXT, // FONTSIZE
+ WRITE, // MAXLENGTH
+ WRITEONCE, // MAXLENGTHONCE
+ LIQUIDSOURCE, // SOURCELIQUIDTYPE
+ TELEPORTABSOLUTE, // ABSTELEPORTEFFECT
+ TELEPORTRELATIVE, // RELTELEPORTDISPLACEMENT
+ TELEPORTRELATIVE, // RELTELEPORTEFFECT
+ AVOID, // AVOIDDAMAGETYPES
+ RESTRICTLEVEL, // MINIMUMLEVEL
+ RESTRICTPROFESSION, // PROFESSIONS
+ TAKE, // WEIGHT
+ ROTATE, // ROTATETARGET
+ DESTROY, // DESTROYTARGET
+ CLOTHES, // BODYPOSITION
+ SKILLBOOST, // SKILLNUMBER
+ SKILLBOOST, // SKILLMODIFICATION
+ PROTECTION, // PROTECTIONDAMAGETYPES
+ PROTECTION, // DAMAGEREDUCTION
+ LIGHT, // BRIGHTNESS
+ LIGHT, // LIGHTCOLOR
+ CORPSE, // CORPSETYPE
+ EXPIRE, // TOTALEXPIRETIME
+ EXPIRE, // EXPIRETARGET
+ WEAROUT, // TOTALUSES
+ WEAROUT, // WEAROUTTARGET
+ WEAPON, // WEAPONTYPE
+ WEAPON, // WEAPONATTACKVALUE
+ WEAPON, // WEAPONDEFENDVALUE
+ SHIELD, // SHIELDDEFENDVALUE
+ BOW, // BOWRANGE
+ BOW, // BOWAMMOTYPE
+ THROW, // THROWRANGE
+ THROW, // THROWATTACKVALUE
+ THROW, // THROWDEFENDVALUE
+ THROW, // THROWMISSILE
+ THROW, // THROWSPECIALEFFECT
+ THROW, // THROWEFFECTSTRENGTH
+ THROW, // THROWFRAGILITY
+ WAND, // WANDRANGE
+ WAND, // WANDMANACONSUMPTION
+ WAND, // WANDATTACKSTRENGTH
+ WAND, // WANDATTACKVARIATION
+ WAND, // WANDDAMAGETYPE
+ WAND, // WANDMISSILE
+ AMMO, // AMMOTYPE
+ AMMO, // AMMOATTACKVALUE
+ AMMO, // AMMOMISSILE
+ AMMO, // AMMOSPECIALEFFECT
+ AMMO, // AMMOEFFECTSTRENGTH
+ ARMOR, // ARMORVALUE
+ HEIGHT, // ELEVATION
+ DISGUISE, // DISGUISETARGET
+ BANK, // MEANING
+};
+
+static FLAG InstanceAttributeFlags[18] = {
+ CONTAINER // CONTENT
+ CHEST // CHESTQUESTNUMBER
+ CUMULATIVE // AMOUNT
+ KEY // KEYNUMBER
+ KEYDOOR // KEYHOLENUMBER
+ LEVELDOOR // DOORLEVEL
+ QUESTDOOR // DOORQUESTNUMBER
+ QUESTDOOR // DOORQUESTVALUE
+ RUNE // CHARGES
+ TEXT // TEXTSTRING
+ TEXT // EDITOR
+ LIQUIDCONTAINER // CONTAINERLIQUIDTYPE
+ LIQUIDPOOL // POOLLIQUIDTYPE
+ TELEPORTABSOLUTE // ABSTELEPORTDESTINATION
+ MAGICFIELD // RESPONSIBLE
+ EXPIRE // REMAININGEXPIRETIME
+ EXPIRESTOP // SAVEDEXPIRETIME
+ WEAROUT // REMAININGUSES
+};
+
+static const char InstanceAttributeNames[18][30] = {
+ "Content", // CONTENT
+ "ChestQuestNumber", // CHESTQUESTNUMBER
+ "Amount", // AMOUNT
+ "KeyNumber", // KEYNUMBER
+ "KeyholeNumber", // KEYHOLENUMBER
+ "Level", // DOORLEVEL
+ "DoorQuestNumber", // DOORQUESTNUMBER
+ "DoorQuestValue", // DOORQUESTVALUE
+ "Charges", // CHARGES
+ "String", // TEXTSTRING
+ "Editor", // EDITOR
+ "ContainerLiquidType", // CONTAINERLIQUIDTYPE
+ "PoolLiquidType", // POOLLIQUIDTYPE
+ "AbsTeleportDestination", // ABSTELEPORTDESTINATION
+ "Responsible", // RESPONSIBLE
+ "RemainingExpireTime", // REMAININGEXPIRETIME
+ "SavedExpireTime", // SAVEDEXPIRETIME
+ "RemainingUses", // REMAININGUSES
+};
+
+// ObjectType
+// =============================================================================
+void ObjectType::setTypeID(int TypeID){
+ if(TypeID < ObjectTypes.min || ObjectTypes.max < TypeID){
+ error("ObjectType::setTypeID: Ungültiger Typ %d.\n", TypeID);
+ TypeID = 0;
+ }
+
+ this->TypeID = TypeID;
+}
+
+bool ObjectType::getFlag(FLAG Flag){
+ TObjectType *Type = ObjectTypes.at(this->TypeID);
+ int FlagIndex = (int)(Flag / 8);
+ uint8 FlagMask = (uint8)(1 << (Flag % 8));
+ return (Type->Flags[FlagIndex] & FlagMask) != 0;
+}
+
+uint32 ObjectType::getAttribute(TYPEATTRIBUTE Attribute){
+ if(!this->getFlag(TypeAttributeFlags[Attribute])){
+ error("ObjectType::getAttribute: Typ %d hat kein Flag %d für Attribut %d.\n",
+ this->TypeID, TypeAttributeFlags[Attribute], Attribute);
+ return 0;
+ }
+
+ TObjectType *Type = ObjectTypes.at(this->TypeID);
+ return Type->Attributes[Attribute];
+}
+
+int ObjectType::getAttributeOffset(INSTANCEATTRIBUTE Attribute){
+ if(!this->getFlag(InstanceAttributeFlags[Attribute])){
+ if(Attribute != CONTENT || !this->getFlag(CHEST)){
+ return -1;
+ }
+ }
+
+ TObjectType *Type = ObjectTypes.at(this->TypeID);
+ return Type->AttributeOffsets[Attribute];
+}
+
+const char *ObjectType::getName(int Count){
+ if(this->TypeID == 99){
+ error("ObjectType::getName: Der Kreaturtyp hat keinen Namen.\n");
+ return NULL;
+ }
+
+ // TODO(fusion): This is yet another rabbit hole. I'm not sure why we have
+ // the object name copied to the stack when `Plural` returns its own static
+ // buffer.
+#if 0
+ char ObjectName[50];
+ TObjectType *Type = ObjectTypes.at(this->TypeID);
+ if(Type->Name != NULL){
+ strcpy(ObjectName, Type->Name);
+ }else{
+ ObjectName[0] = 0;
+ }
+ return Plural(ObjectName, Count);
+#endif
+
+ return "Unnamed";
+}
+
+const char *ObjectType::getDescription(void){
+ TObjectType *Type = ObjectTypes.at(this->TypeID);
+ return Type->Description;
+}
+
+// Object Type Related Functions
+// =============================================================================
+int GetInstanceAttributeByName(const char *Name){
+ int Result = -1;
+ for(int i = 0; i < NARRAY(InstanceAttributeNames); i += 1){
+ if(stricmp(InstanceAttributeNames[i], Name) == 0){
+ Result = i;
+ break;
+ }
+ }
+ return Result;
+}
+
+bool ObjectTypeExists(int TypeID){
+ return ObjectTypes.min <= TypeID && TypeID <= ObjectTypes.max;
+}
diff --git a/src/objects.hh b/src/objects.hh
new file mode 100644
index 0000000..3cbc401
--- /dev/null
+++ b/src/objects.hh
@@ -0,0 +1,73 @@
+#ifndef TIBIA_OBJECTS_HH_
+#define TIBIA_OBJECTS_HH_ 1
+
+#include "common.hh"
+#include "enums.hh"
+
+enum : int{
+ TYPEID_MAP_CONTAINER = 0,
+ TYPEID_HEAD_CONTAINER = 1,
+ TYPEID_NECK_CONTAINER = 2,
+ TYPEID_BACKPACK_CONTAINER = 3,
+ TYPEID_TORSO_CONTAINER = 4,
+ TYPEID_RIGHTHAND_CONTAINER = 5,
+ TYPEID_LEFTHAND_CONTAINER = 6,
+ TYPEID_LEGS_CONTAINER = 7,
+ TYPEID_FEET_CONTAINER = 8,
+ TYPEID_FINGER_CONTAINER = 9,
+ TYPEID_AMMO_CONTAINER = 10,
+ TYPEID_CREATURE_CONTAINER = 99,
+};
+
+struct ObjectType {
+ // REGULAR FUNCTIONS
+ // =========================================================================
+ ObjectType(void) { this->setTypeID(0); }
+ ObjectType(int TypeID) { this->setTypeID(TypeID); }
+ void setTypeID(int TypeID);
+ bool getFlag(FLAG Flag);
+ uint32 getAttribute(TYPEATTRIBUTE Attribute);
+ int getAttributeOffset(INSTANCEATTRIBUTE Attribute);
+ const char *getName(int Count);
+ const char *getDescription(void);
+
+ bool isMapContainer(void) const {
+ return this->TypeID == TYPEID_MAP_CONTAINER;
+ }
+
+ bool isBodyContainer(void) const {
+ return this->TypeID == TYPEID_HEAD_CONTAINER
+ || this->TypeID == TYPEID_NECK_CONTAINER
+ || this->TypeID == TYPEID_BACKPACK_CONTAINER
+ || this->TypeID == TYPEID_TORSO_CONTAINER
+ || this->TypeID == TYPEID_RIGHTHAND_CONTAINER
+ || this->TypeID == TYPEID_LEFTHAND_CONTAINER
+ || this->TypeID == TYPEID_LEGS_CONTAINER
+ || this->TypeID == TYPEID_FEET_CONTAINER
+ || this->TypeID == TYPEID_FINGER_CONTAINER
+ || this->TypeID == TYPEID_AMMO_CONTAINER;
+ }
+
+ bool isCreatureContainer(void) const {
+ return this->TypeID == TYPEID_CREATURE_CONTAINER;
+ }
+
+ // DATA
+ // =========================================================================
+ int TypeID;
+};
+
+struct TObjectType {
+ char *Name;
+ char *Description;
+ uint8 Flags[9];
+ uint32 Attributes[62];
+ int AttributeOffsets[18];
+};
+
+int GetInstanceAttributeByName(const char *Name);
+bool ObjectTypeExists(int TypeID);
+//void InitObjects(void);
+//void ExitObjects(void);
+
+#endif //TIBIA_OBJECTS_HH_
diff --git a/src/script.hh b/src/script.hh
index 16e66fe..59df86d 100644
--- a/src/script.hh
+++ b/src/script.hh
@@ -57,7 +57,7 @@ struct TReadScriptFile {
return this->getSpecial();
}
- void TReadScriptFile::readSymbol(char Symbol){
+ void readSymbol(char Symbol){
if(this->readSpecial() != Symbol){
this->error("symbol mismatch");
}