aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--TODO.md5
-rw-r--r--reference/game.c3032
-rw-r--r--src/common.hh1
-rw-r--r--src/communication.cc4
-rw-r--r--src/connections.hh13
-rw-r--r--src/cr.hh5
-rw-r--r--src/info.cc6
-rw-r--r--src/operate.cc4
-rw-r--r--src/receiving.cc1818
-rw-r--r--src/sending.cc31
-rw-r--r--src/stubs.hh4
12 files changed, 1879 insertions, 3050 deletions
diff --git a/Makefile b/Makefile
index 357ae64..9294314 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ endif
HEADERS = $(SRCDIR)/common.hh $(SRCDIR)/communication.hh $(SRCDIR)/config.hh $(SRCDIR)/connections.hh $(SRCDIR)/containers.hh $(SRCDIR)/cr.hh $(SRCDIR)/crypto.hh $(SRCDIR)/enums.hh $(SRCDIR)/info.hh $(SRCDIR)/magic.hh $(SRCDIR)/map.hh $(SRCDIR)/moveuse.hh $(SRCDIR)/objects.hh $(SRCDIR)/operate.hh $(SRCDIR)/query.hh $(SRCDIR)/script.hh $(SRCDIR)/stubs.hh $(SRCDIR)/threads.hh
-$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/communication.obj $(BUILDDIR)/config.obj $(BUILDDIR)/connections.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/crypto.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/script.obj $(BUILDDIR)/sending.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/threads.obj $(BUILDDIR)/time.obj $(BUILDDIR)/utils.obj
+$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/communication.obj $(BUILDDIR)/config.obj $(BUILDDIR)/connections.obj $(BUILDDIR)/cract.obj $(BUILDDIR)/crcombat.obj $(BUILDDIR)/crmain.obj $(BUILDDIR)/crplayer.obj $(BUILDDIR)/crskill.obj $(BUILDDIR)/crypto.obj $(BUILDDIR)/info.obj $(BUILDDIR)/magic.obj $(BUILDDIR)/main.obj $(BUILDDIR)/map.obj $(BUILDDIR)/moveuse.obj $(BUILDDIR)/objects.obj $(BUILDDIR)/operate.obj $(BUILDDIR)/query.obj $(BUILDDIR)/receiving.obj $(BUILDDIR)/script.obj $(BUILDDIR)/sending.obj $(BUILDDIR)/shm.obj $(BUILDDIR)/strings.obj $(BUILDDIR)/threads.obj $(BUILDDIR)/time.obj $(BUILDDIR)/utils.obj
@echo $(CC) $(CFLAGS) $(LFLAGS) -o $@ $^
$(BUILDDIR)/communication.obj: $(SRCDIR)/communication.cc $(HEADERS)
@@ -86,6 +86,10 @@ $(BUILDDIR)/query.obj: $(SRCDIR)/query.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
+$(BUILDDIR)/receiving.obj: $(SRCDIR)/receiving.cc $(HEADERS)
+ @mkdir -p $(@D)
+ $(CC) -c $(CFLAGS) -o $@ $<
+
$(BUILDDIR)/script.obj: $(SRCDIR)/script.cc $(HEADERS)
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
diff --git a/TODO.md b/TODO.md
index 19e483f..c389567 100644
--- a/TODO.md
+++ b/TODO.md
@@ -8,6 +8,11 @@
- WRITER.CC
- DBFUNCS.CC
+- Include `x == 0xFFFF` inside `CheckVisibility`?
+- The map container uses type id zero but it seems to also be used as a "no type"
+ id which makes me want to add some `isNone()`, `isNull()`, `isVoid()` check to
+ `ObjectType` to be used as an alias when pertinent.
+
## Stack allocations
Any functions that use `alloca` or some other form of dynamic stack allocations will cause decompiled functions to be an absolute mess. It usually shows up in the decompiled code as both a size computation like `-(VAR + CONST & 0xfffffff0)`, followed by some assignment. It doesn't make total sense without looking at the disassembly. I've encountered ~30 such computations and expect the functions containing them to be amongt the most challenging/annoying to be properly decompiled.
diff --git a/reference/game.c b/reference/game.c
index 723efb5..06d70d8 100644
--- a/reference/game.c
+++ b/reference/game.c
@@ -26790,3038 +26790,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority
return;
}
-
-
-bool CommandAllowed(TConnection *Connection,ushort Command)
-
-{
- CONNECTIONSTATE CVar1;
-
- if (Connection == (TConnection *)0x0) {
- error("CommandAllowed: Connection ist NULL.\n");
- }
- else {
- CVar1 = Connection->State;
- if (CVar1 == CONNECTION_GAME) {
- return 1 < (ushort)(Command - 10);
- }
- if ((3 < (int)CVar1) && ((int)CVar1 < 7)) {
- if ((Command != 0xe6) && (((Command != 0xe8 && (Command != 0x1e)) && (Command != 0x14)))
- ) {
- return false;
- }
- return true;
- }
- error(&DAT_08109f80,CVar1,(uint)Command);
- }
- return false;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-bool CheckSpecialCoordinates(void)
-
-{
- bool bVar1;
- int in_stack_00000008;
- int in_stack_0000000c;
- int in_stack_00000010;
- char in_stack_00000014;
-
- if (in_stack_00000008 == 0xffff) {
- bVar1 = in_stack_00000014 != '\0';
- if (in_stack_0000000c != 0) {
- if ((in_stack_0000000c - 0xbU < 0x35) || (0x4f < in_stack_0000000c)) {
- print();
- bVar1 = false;
- }
- else {
- bVar1 = true;
- }
- }
- }
- else {
- bVar1 = IsOnMap(in_stack_00000008,in_stack_0000000c,in_stack_00000010);
- }
- return bVar1;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: posz
-
-bool CheckVisibility(int Command,TConnection *Connection,int x,int y,int z)
-
-{
- bool bVar1;
- int local_1c;
- int posx;
- int posy;
- int posz;
-
- if (Connection == (TConnection *)0x0) {
- error("CheckVisibility: Connection ist NULL.\n");
- }
- else {
- bVar1 = TConnection::IsVisible(Connection,x,y,z);
- if (bVar1) {
- return true;
- }
- TConnection::GetPosition(Connection,&local_1c,&posx,&posy);
- print();
- }
- return false;
-}
-
-
-
-bool CheckObjectType(int Command,int TypeID)
-
-{
- bool bVar1;
-
- bVar1 = ObjectTypeExists(TypeID);
- if (!bVar1) {
- print();
- }
- return bVar1;
-}
-
-
-
-ObjectType GetObjectType(ushort TypeID)
-
-{
- bool bVar1;
- uint TypeID_00;
- undefined2 in_stack_00000006;
- ushort in_stack_00000008;
-
- TypeID_00 = (uint)in_stack_00000008;
- bVar1 = ObjectTypeExists(TypeID_00);
- if (!bVar1) {
- print();
- TypeID_00 = 0;
- }
- ObjectType::setTypeID(_TypeID,TypeID_00);
- return (ObjectType)(int)_TypeID;
-}
-
-
-
-void CGoDirection(TConnection *Connection,int dx,int dy)
-
-{
- bool bVar1;
- RESULT r;
- TPlayer *this;
- TPlayer *pl;
- int local_48;
- int x;
- int y;
- int z;
- TToDoEntry TD;
-
- if (Connection == (TConnection *)0x0) {
- error("CGoDirection: Connection ist NULL.\n");
- }
- else {
- TConnection::GetPosition(Connection,&local_48,&x,&y);
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- // try { // try from 080d6a74 to 080d6abb has its CatchHandler @ 080d6ae0
- bVar1 = TCreature::ToDoClear(&this->super_TCreature);
- if (bVar1) {
- SendSnapback(Connection);
- }
- z = 1;
- TD.field_1.Go.x = dy + x;
- TD.Code = dx + local_48;
- TD.field_1.Go.y = y;
- TCreature::ToDoAdd(&this->super_TCreature,(TToDoEntry *)&z);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- return;
-}
-
-
-
-void CGoPath(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- uint uVar2;
- TPlayer *this;
- uint uVar3;
- int Steps;
- int local_50;
- int i;
- TPlayer *pl;
- int x;
- int y;
- int z;
- TToDoEntry TD;
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080d6c37 to 080d6c3b has its CatchHandler @ 080d6c86
- error("CGoPath: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d6b42 to 080d6b6c has its CatchHandler @ 080d6c86
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- TConnection::GetPosition(Connection,(int *)&pl,&x,&y);
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- // try { // try from 080d6b77 to 080d6c27 has its CatchHandler @ 080d6c3e
- bVar1 = TCreature::ToDoClear(&this->super_TCreature);
- if (bVar1) {
- SendSnapback(Connection);
- }
- local_50 = 0;
- if ((uVar2 & 0xff) != 0) {
- do {
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- switch(uVar3 & 0xff) {
- default:
- goto switchD_080d6ba0_caseD_0;
- case 1:
- pl = (TPlayer *)((int)&(pl->super_TCreature)._vptr_TCreature + 1);
- goto LAB_080d6baa;
- case 2:
- pl = (TPlayer *)((int)&(pl->super_TCreature)._vptr_TCreature + 1);
- break;
- case 3:
- break;
- case 4:
- pl = (TPlayer *)((int)pl[-1].AddresseesTimes + 0x4f);
- break;
- case 5:
- pl = (TPlayer *)((int)pl[-1].AddresseesTimes + 0x4f);
- goto LAB_080d6baa;
- case 6:
- pl = (TPlayer *)((int)pl[-1].AddresseesTimes + 0x4f);
- case 7:
- goto switchD_080d6ba0_caseD_7;
- case 8:
- pl = (TPlayer *)((int)&(pl->super_TCreature)._vptr_TCreature + 1);
- goto switchD_080d6ba0_caseD_7;
- }
- x = x + -1;
-LAB_080d6baa:
- z = 1;
- TD.Code = (ToDoType)pl;
- TD.field_1.Go.x = x;
- TD.field_1.Go.y = y;
- TCreature::ToDoAdd(&this->super_TCreature,(TToDoEntry *)&z);
-switchD_080d6ba0_caseD_0:
- local_50 = local_50 + 1;
- } while (local_50 < (int)(uVar2 & 0xff));
- }
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- return;
-switchD_080d6ba0_caseD_7:
- x = x + 1;
- goto LAB_080d6baa;
-}
-
-
-
-void CStop(TConnection *Connection)
-
-{
- TPlayer *this;
-
- if (Connection == (TConnection *)0x0) {
- error("CGoStop: Connection ist NULL.\n");
- return;
- }
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- TCreature::ToDoStop(&this->super_TCreature);
- return;
- }
- return;
-}
-
-
-
-void CLookAtPoint(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- ulong CreatureID_00;
- bool bVar1;
- TPlayer *pl;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- TPlayer *pTVar5;
- ObjectType *Type;
- ObjectType *z;
- int x;
- ulong CreatureID;
- int y;
- int posx;
- int posy;
- int posz;
- Object local_2c;
- Object Obj;
-
- if (Connection == (TConnection *)0x0) {
- error("CLookAtPoint: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d6d05 to 080d6df2 has its CatchHandler @ 080d6ee6
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- z = (ObjectType *)(uVar4 & 0xff);
- bVar1 = CheckSpecialCoordinates();
- if (bVar1) {
- if ((uVar2 == 0xffff) ||
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,(int)z), bVar1)) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 != (TPlayer *)0x0) {
- CreatureID_00 = (pTVar5->super_TCreature).ID;
- ObjectType::setTypeID((ObjectType *)&posz,0);
- Type = (ObjectType *)0xffffffff;
- if (uVar2 == 0xffff) {
- Type = z;
- }
- GetObject((ulong)&local_2c,CreatureID_00,uVar2,uVar3 & 0xffff,(int)z,Type);
- bVar1 = Object::exists(&local_2c);
- if (bVar1) {
- posz = local_2c.ObjectID;
- // try { // try from 080d6e20 to 080d6e24 has its CatchHandler @ 080d6ea1
- Look(CreatureID_00,(Object *)&posz);
- }
- }
- }
- else {
- // try { // try from 080d6e3f to 080d6e9b has its CatchHandler @ 080d6ee6
- TConnection::GetPosition(Connection,&y,&posx,&posy);
- print();
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: posz
-
-void CRefreshField(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- uint uVar3;
- TConnection *Connection_00;
- int x_00;
- int x;
- int y;
- int posx;
- int posy;
- int posz;
-
- if (Connection == (TConnection *)0x0) {
- error("CRefreshField: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d6f22 to 080d700e has its CatchHandler @ 080d7014
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- Connection_00 = (TConnection *)(uVar3 & 0xffff);
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- bVar1 = IsOnMap(uVar2,(int)Connection_00,uVar3 & 0xff);
- if (bVar1) {
- bVar1 = TConnection::IsVisible(Connection,uVar2,(int)Connection_00,uVar3 & 0xff);
- if (bVar1) {
- SendFieldData(Connection_00,x_00,(int)Connection,uVar2);
- }
- else {
- TConnection::GetPosition(Connection,&y,&posx,&posy);
- print();
- }
- }
- }
- return;
-}
-
-
-
-void CTalk(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- int GamemasterID;
- uint uVar2;
- TPlayer *this;
- char *pcVar3;
- ulong uVar4;
- TConnection *this_00;
- TPlayer *pTVar5;
- TCreature *pTVar6;
- int iVar7;
- uint uVar8;
- int Mode;
- TPlayer *pl;
- int Channel;
- char Text [256];
- char Addressee [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CTalk: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d7055 to 080d713e has its CatchHandler @ 080d76f6
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar2 = uVar2 & 0xff;
- if ((((((7 < uVar2 - 1) && (uVar2 != 0xb)) && (uVar2 != 0xf)) &&
- ((uVar2 != 10 && (uVar2 != 0xe)))) && (uVar2 != 9)) && (uVar2 != 0xd)) {
-LAB_080d708d:
- print();
- return;
- }
- Text[0xfc] = '\0';
- pl = (TPlayer *)0x0;
- if ((((uVar2 == 4) || (uVar2 == 7)) || ((uVar2 == 0xb || (uVar2 == 0xf)))) &&
- ((*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,Text + 0xfc,0x1e),
- Text[0xfc] == '\0')) goto LAB_080d7126;
- if (((uVar2 == 5) || (uVar2 == 10)) || (uVar2 == 0xe)) {
- uVar8 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- pl = (TPlayer *)(uVar8 & 0xffff);
- iVar7 = GetNumberOfChannels();
- if (iVar7 <= (int)pl) goto LAB_080d708d;
- sprintf(Text + 0xfc,"%d",pl);
- }
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&Channel,0x100);
- if (((char)Channel == '\0') ||
- (this = TConnection::GetPlayer(Connection), this == (TPlayer *)0x0)) goto LAB_080d7126;
- pcVar3 = strchr((char *)&Channel,10);
- if (pcVar3 != (char *)0x0) {
- error("CTalk: %s verwendet Newlines (%d,%s)\n",(this->super_TCreature).Name,uVar2,&Channel);
- return;
- }
- if ((uVar2 == 7) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,READ_GAMEMASTER_CHANNEL), !bVar1)) {
- uVar2 = 4;
- }
- if ((uVar2 == 9) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,GAMEMASTER_BROADCAST), !bVar1)) {
- uVar2 = 1;
- }
- if ((uVar2 == 10) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,GAMEMASTER_BROADCAST), !bVar1)) {
- uVar2 = 5;
- }
- if ((uVar2 == 0xb) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,GAMEMASTER_BROADCAST), !bVar1)) {
- uVar2 = 4;
- }
- if ((uVar2 == 0xd) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,ANONYMOUS_BROADCAST), !bVar1)) {
- uVar2 = 1;
- }
- if ((uVar2 == 0xe) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,ANONYMOUS_BROADCAST), !bVar1)) {
- uVar2 = 5;
- }
- if ((uVar2 == 0xf) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,ANONYMOUS_BROADCAST), !bVar1)) {
- uVar2 = 4;
- }
- if ((uVar2 == 3) &&
- (iVar7 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0]), iVar7 < 2)) {
- pcVar3 = "You may not yell as long as you are on level 1.";
- goto LAB_080d731f;
- }
- if (uVar2 == 5) {
- iVar7 = TSkill::Get((this->super_TCreature).super_TSkillBase.Skills[0]);
- if (iVar7 < 2) {
- pcVar3 = "You may not speak into channels as long as you are on level 1.";
- goto LAB_080d731f;
- }
-LAB_080d7444:
- if (pl == (TPlayer *)0x3) {
-LAB_080d7126:
- print();
- return;
- }
- }
- else if ((uVar2 == 10) || (uVar2 == 0xe)) goto LAB_080d7444;
- if ((((uVar2 == 5) || (uVar2 == 10)) || (uVar2 == 0xe)) &&
- (bVar1 = ChannelSubscribed((int)pl,(this->super_TCreature).ID), !bVar1)) {
- Text[0xfc] = '\0';
- uVar2 = 1;
- }
- if (((uVar2 == 5) && (pl == (TPlayer *)0x7)) &&
- (bVar1 = CheckRight((this->super_TCreature).ID,HIGHLIGHT_HELP_CHANNEL), bVar1)) {
- this->TutorActivities = this->TutorActivities + 1;
- print();
- uVar2 = 0xc;
- }
- if (uVar2 == 8) {
- if (this->Request == 0) {
- return;
- }
- if (this->RequestProcessingGamemaster == 0) {
- pcVar3 = "Please wait until your request is answered.";
- goto LAB_080d731f;
- }
- pTVar6 = GetCreature(this->RequestProcessingGamemaster);
- if (pTVar6 == (TCreature *)0x0) {
- SendCloseRequest(Connection);
- this->Request = 0;
- return;
- }
- strcpy(Text + 0xfc,pTVar6->Name);
- }
- if (uVar2 != 6) {
- // try { // try from 080d7226 to 080d7238 has its CatchHandler @ 080d76a6
- TCreature::ToDoTalk(&this->super_TCreature);
- TCreature::ToDoStart(&this->super_TCreature);
- return;
- }
- if (this->Request == 0) {
- if ((char)Channel == '\0') {
- return;
- }
- // try { // try from 080d7268 to 080d76a0 has its CatchHandler @ 080d76f6
- uVar4 = AddDynamicString((char *)&Channel);
- this->Request = uVar4;
- this->RequestTimestamp = RoundNr;
- this->RequestProcessingGamemaster = 0;
- this_00 = GetFirstConnection();
- if (this_00 == (TConnection *)0x0) {
- return;
- }
- do {
- if (((this_00->State - CONNECTION_LOGIN < 4) &&
- (pTVar5 = TConnection::GetPlayer(this_00), pTVar5 != (TPlayer *)0x0)) &&
- (bVar1 = ChannelSubscribed(3,(pTVar5->super_TCreature).ID), bVar1)) {
- SendTalk(this_00,0,(this->super_TCreature).Name,6,(char *)&Channel,0);
- }
- this_00 = GetNextConnection();
- } while (this_00 != (TConnection *)0x0);
- return;
- }
- pcVar3 = "You have already submitted a request. Please wait until it is answered.";
-LAB_080d731f:
- SendMessage(Connection,0x17,pcVar3);
- return;
-}
-
-
-
-void CGetChannels(TConnection *Connection)
-
-{
- if (Connection != (TConnection *)0x0) {
- SendChannels(Connection);
- return;
- }
- error("CGetChannels: Connection ist NULL.\n");
- return;
-}
-
-
-
-void CJoinChannel(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- TPlayer *pl;
- uint uVar2;
- int iVar3;
- TPlayer *pTVar4;
- int Channel;
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080d77c7 to 080d77cb has its CatchHandler @ 080d7816
- error("CJoinChannel: ist NULL.\n");
- }
- else {
- // try { // try from 080d774b to 080d776b has its CatchHandler @ 080d7816
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- iVar3 = GetNumberOfChannels();
- if ((int)uVar2 < iVar3) {
- pTVar4 = TConnection::GetPlayer(Connection);
- if (pTVar4 != (TPlayer *)0x0) {
- // try { // try from 080d777d to 080d77b6 has its CatchHandler @ 080d77ce
- bVar1 = JoinChannel(uVar2,(pTVar4->super_TCreature).ID);
- if (uVar2 == 3) {
- SendOpenRequestQueue(Connection);
- SendExistingRequests(Connection);
- }
- else if (bVar1) {
- SendOpenOwnChannel(Connection,uVar2);
- }
- else {
- SendOpenChannel(Connection,uVar2);
- }
- }
- }
- }
- return;
-}
-
-
-
-void CLeaveChannel(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *pl;
- uint uVar1;
- int iVar2;
- TPlayer *pTVar3;
- int Channel;
-
- if (Connection == (TConnection *)0x0) {
- error("CLeaveChannel: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d784b to 080d789b has its CatchHandler @ 080d78a0
- uVar1 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- iVar2 = GetNumberOfChannels();
- if ((int)(uVar1 & 0xffff) < iVar2) {
- pTVar3 = TConnection::GetPlayer(Connection);
- if (pTVar3 != (TPlayer *)0x0) {
- LeaveChannel(uVar1 & 0xffff,(pTVar3->super_TCreature).ID,true);
- }
- }
- }
- return;
-}
-
-
-
-void CPrivateChannel(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- ulong uVar1;
- TPlayer *pTVar2;
- char *Name_00;
- ulong OppID;
- char local_3c [4];
- char Name [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CPrivateChannel: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d78f1 to 080d7972 has its CatchHandler @ 080d7975
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_3c,0x1e);
- if (local_3c[0] != '\0') {
- uVar1 = GetCharacterID(local_3c);
- if (uVar1 == 0) {
- SendResult(Connection,PLAYERNOTEXISTING);
- }
- else {
- pTVar2 = TConnection::GetPlayer(Connection);
- if (uVar1 == (pTVar2->super_TCreature).ID) {
- SendMessage(Connection,0x17,
- "You cannot set up a private message channel with yourself.");
- }
- else {
- Name_00 = GetCharacterName(local_3c);
- SendPrivateChannel(Connection,Name_00);
- }
- }
- }
- }
- return;
-}
-
-
-
-void CProcessRequest(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- int iVar3;
- TPlayer *pl;
- char *Text;
- TPlayer *local_40;
- TPlayer *Opp;
- char Name [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CProcessRequest: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d79b0 to 080d7a9d has its CatchHandler @ 080d7aa3
- pTVar2 = TConnection::GetPlayer(Connection);
- if (((pTVar2 != (TPlayer *)0x0) &&
- (bVar1 = ChannelAvailable(3,(pTVar2->super_TCreature).ID), bVar1)) &&
- ((*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&Opp,0x1e), (char)Opp != '\0'
- )) {
- iVar3 = IdentifyPlayer((char *)&Opp,true,true,&local_40);
- if (iVar3 == 0) {
- if ((local_40->Request != 0) && (local_40->RequestProcessingGamemaster == 0)) {
- local_40->RequestProcessingGamemaster = (pTVar2->super_TCreature).ID;
- DeleteGamemasterRequest((local_40->super_TCreature).Name);
- return;
- }
- Text = "Request has already been processed.";
- }
- else {
- Text = "Player is not online any more.";
- }
- SendMessage(Connection,0x17,Text);
- SendFinishRequest(Connection,"Name");
- }
- }
- return;
-}
-
-
-
-void CRemoveRequest(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- int iVar3;
- TPlayer *pl;
- TPlayer *local_40;
- TPlayer *Opp;
- char Name [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CRemoveRequest: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d7ae0 to 080d7bdc has its CatchHandler @ 080d7be2
- pTVar2 = TConnection::GetPlayer(Connection);
- if (((pTVar2 != (TPlayer *)0x0) &&
- (bVar1 = ChannelAvailable(3,(pTVar2->super_TCreature).ID), bVar1)) &&
- ((*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&Opp,0x1e), (char)Opp != '\0'
- )) {
- iVar3 = IdentifyPlayer((char *)&Opp,true,true,&local_40);
- if (iVar3 == 0) {
- if (local_40->Request != 0) {
- if (local_40->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest((local_40->super_TCreature).Name);
- }
- else if (local_40->RequestProcessingGamemaster != (pTVar2->super_TCreature).ID)
- {
- return;
- }
- SendCloseRequest((local_40->super_TCreature).Connection);
- local_40->Request = 0;
- }
- }
- else {
- SendMessage(Connection,0x17,"Player is not online any more.");
- SendFinishRequest(Connection,"Name");
- }
- }
- }
- return;
-}
-
-
-
-void CCancelRequest(TConnection *Connection)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- TPlayer *pTVar3;
- TPlayer *pl;
-
- if (Connection != (TConnection *)0x0) {
- pTVar2 = TConnection::GetPlayer(Connection);
- if (pTVar2 != (TPlayer *)0x0) {
- bVar1 = ChannelAvailable(3,(pTVar2->super_TCreature).ID);
- if ((bVar1) && (pTVar2->Request != 0)) {
- if (pTVar2->RequestProcessingGamemaster == 0) {
- DeleteGamemasterRequest((pTVar2->super_TCreature).Name);
- }
- else {
- pTVar3 = GetPlayer(pTVar2->RequestProcessingGamemaster);
- if (pTVar3 != (TPlayer *)0x0) {
- SendFinishRequest((pTVar3->super_TCreature).Connection,
- (pTVar2->super_TCreature).Name);
- }
- }
- pTVar2->Request = 0;
- }
- }
- return;
- }
- error("CCancelRequest: Connection ist NULL.\n");
- return;
-}
-
-
-
-void CRotate(TConnection *Connection,int Direction)
-
-{
- RESULT r;
- TPlayer *this;
- TPlayer *pl;
-
- if (Connection != (TConnection *)0x0) {
- if ((uint)Direction < 4) {
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- // try { // try from 080d7cf5 to 080d7d01 has its CatchHandler @ 080d7d20
- TCreature::ToDoRotate(&this->super_TCreature,Direction);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- return;
- }
- error("CRotate: Connection ist NULL.\n");
- return;
-}
-
-
-
-void CBugReport(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- uint *puVar1;
- char cVar2;
- int iVar3;
- char *pcVar4;
- time_t *ptVar5;
- size_t sVar6;
- uint *puVar7;
- uint *puVar8;
- uint uVar9;
- uint uVar10;
- int LineStart;
- bool bVar11;
- int iVar12;
- int iVar13;
- int iVar14;
- int iVar15;
- int iVar16;
- size_t local_48c;
- int LastSpace;
- int i;
- int local_47c;
- int posx;
- int posy;
- int posz;
- time_t Time;
- char Line [80];
- char Text [1024];
-
- if (Connection == (TConnection *)0x0) {
- error("CBugReport: Connection ist NULL.\n");
- return;
- }
- puVar1 = (uint *)(Line + 0x4c);
- // try { // try from 080d7d91 to 080d811b has its CatchHandler @ 080d8121
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,puVar1,0x400);
- while( true ) {
- puVar8 = puVar1;
- if (Line[0x4c] == '\0') {
- return;
- }
- do {
- puVar7 = puVar8;
- uVar9 = *puVar7 + 0xfefefeff & ~*puVar7;
- uVar10 = uVar9 & 0x80808080;
- puVar8 = puVar7 + 1;
- } while (uVar10 == 0);
- bVar11 = (uVar9 & 0x8080) == 0;
- if (bVar11) {
- uVar10 = uVar10 >> 0x10;
- }
- if (bVar11) {
- puVar8 = (uint *)((int)puVar7 + 6);
- }
- iVar3 = isprint((int)*(char *)((int)puVar8 +
- (int)(Line + (-(int)puVar1 -
- (uint)CARRY1((byte)uVar10,(byte)uVar10)) + 0x48))
- );
- puVar8 = puVar1;
- if (iVar3 != 0) break;
- do {
- puVar7 = puVar8;
- uVar9 = *puVar7 + 0xfefefeff & ~*puVar7;
- uVar10 = uVar9 & 0x80808080;
- puVar8 = puVar7 + 1;
- } while (uVar10 == 0);
- bVar11 = (uVar9 & 0x8080) == 0;
- if (bVar11) {
- uVar10 = uVar10 >> 0x10;
- }
- if (bVar11) {
- puVar8 = (uint *)((int)puVar7 + 6);
- }
- *(char *)((int)puVar8 +
- (int)(Line + (-(int)puVar1 - (uint)CARRY1((byte)uVar10,(byte)uVar10)) + 0x48)) =
- '\0';
- }
- if (Line[0x4c] == '\0') {
- return;
- }
- time(&posz);
- TConnection::GetPosition(Connection,&local_47c,&posx,&posy);
- pcVar4 = ctime(&posz);
- iVar13 = Connection->TerminalVersion;
- iVar12 = Connection->TerminalType;
- ptVar5 = (time_t *)TConnection::GetName(Connection);
- Log("bugreport","%s - %d/%d - [%d,%d,%d] - %s",ptVar5,iVar12,iVar13,local_47c,posx,posy,pcVar4);
- iVar3 = 0;
- iVar14 = local_47c;
- iVar15 = posx;
- iVar16 = posy;
-LAB_080d7f12:
- do {
- if (Line[iVar3 + 0x4c] == '\0') {
- Log("bugreport",
- "---------------------------------------------------------------------------\n",
- ptVar5,iVar12,iVar13,iVar14,iVar15,iVar16,pcVar4);
- SendMessage(Connection,0x15,"Comment sent.");
- return;
- }
- local_48c = 0xffffffff;
- LastSpace = 0;
- while (cVar2 = Line[LastSpace + iVar3 + -0x1c + 0x68], cVar2 != '\0') {
- if (0x4a < LastSpace) {
- if (local_48c == 0xffffffff) {
- strncpy((char *)&Time,(char *)(iVar3 + (int)puVar1),0x4a);
- ptVar5 = &Time;
- Line[0x46] = '-';
- Line[0x47] = '\0';
- Log("bugreport","%s\n",ptVar5,iVar12,iVar13,iVar14,iVar15,iVar16,pcVar4);
- iVar3 = iVar3 + 0x4a;
- }
- else {
- strncpy((char *)&Time,(char *)(iVar3 + (int)puVar1),local_48c);
- Line[local_48c - 4] = '\0';
- ptVar5 = &Time;
- Log("bugreport","%s\n",ptVar5);
- if (Line[local_48c + iVar3 + -0x1c + 0x68] == ' ') {
- iVar3 = iVar3 + 1;
- }
- iVar3 = iVar3 + local_48c;
- }
- goto LAB_080d7f12;
- }
- if (cVar2 == '\n') {
- strncpy((char *)&Time,(char *)(iVar3 + (int)puVar1),LastSpace);
- ptVar5 = &Time;
- Line[LastSpace + -4] = '\0';
- Log("bugreport","%s\n",ptVar5);
- iVar3 = LastSpace + 1 + iVar3;
- goto LAB_080d7f12;
- }
- bVar11 = isSpace((int)cVar2);
- sVar6 = LastSpace;
- if (!bVar11) {
- sVar6 = local_48c;
- }
- LastSpace = LastSpace + 1;
- local_48c = sVar6;
- }
- ptVar5 = (time_t *)(iVar3 + (int)puVar1);
- Log("bugreport","%s\n",ptVar5,iVar12,iVar13,iVar14,iVar15,iVar16,pcVar4);
- iVar3 = iVar3 + LastSpace;
- } while( true );
-}
-
-
-
-void CErrorFileEntry(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- char cVar1;
- int iVar2;
- bool bVar3;
- char *pcVar4;
- char *pcVar5;
- int iVar6;
- time_t *__s;
- size_t __n;
- int LastSpace;
- size_t __n_00;
- time_t *ptVar7;
- int local_b0c;
- int posx;
- int posy;
- int posz;
- time_t Time;
- char Line [80];
- char Comment [513];
- time_t local_89c;
- char Stack [2049];
- time_t local_8c;
- char Date [27];
- undefined1 local_6c [4];
- char Title [65];
-
- if (Connection == (TConnection *)0x0) {
- error("CErrorFileEntry: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d8174 to 080d851e has its CatchHandler @ 080d8521
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_6c,0x41);
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&local_8c,0x1b);
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&local_89c,0x801);
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,Line + 0x4c,0x201);
- if (((char)local_89c != '\0') || (Line[0x4c] != '\0')) {
- time(&posz);
- TConnection::GetPosition(Connection,&local_b0c,&posx,&posy);
- pcVar4 = ctime(&posz);
- iVar6 = Connection->TerminalVersion;
- iVar2 = Connection->TerminalType;
- pcVar5 = TConnection::GetName(Connection);
- Log("client-error","%s - %d/%d - [%d,%d,%d] - %s",pcVar5,iVar2,iVar6,local_b0c,posx,posy
- ,pcVar4);
- Log("client-error","%s\n",local_6c);
- ptVar7 = &local_8c;
- Log("client-error","%s\n",ptVar7);
- Log("client-error","\n");
- __s = &local_89c;
- while( true ) {
- pcVar4 = strchr((char *)__s,10);
- if (pcVar4 == (char *)0x0) break;
- *pcVar4 = '\0';
- if ((char)*__s != '\0') {
- Log("client-error","%s\n",__s);
- ptVar7 = __s;
- }
- __s = (time_t *)(pcVar4 + 1);
- }
- if ((char)*__s != '\0') {
- Log("client-error","%s\n",__s);
- ptVar7 = __s;
- }
- if (((char)local_89c != '\0') && (Line[0x4c] != '\0')) {
- Log("client-error","\n",ptVar7);
- }
- iVar6 = 0;
-LAB_080d8335:
- if (Line[iVar6 + 0x4c] != '\0') {
- __n = 0;
- __n_00 = 0xffffffff;
- while (cVar1 = Line[__n + iVar6 + -0x1c + 0x68], cVar1 != '\0') {
- if (0x4a < (int)__n) {
- if (__n_00 == 0xffffffff) {
- ptVar7 = &Time;
- strncpy((char *)&Time,Line + iVar6 + 0x4c,0x4a);
- Line[0x46] = '-';
- Line[0x47] = '\0';
- Log("client-error","%s\n",ptVar7);
- iVar6 = iVar6 + 0x4a;
- }
- else {
- ptVar7 = &Time;
- strncpy((char *)&Time,Line + iVar6 + 0x4c,__n_00);
- Line[__n_00 - 4] = '\0';
- Log("client-error","%s\n",ptVar7);
- if (Line[__n_00 + iVar6 + -0x1c + 0x68] == ' ') {
- iVar6 = iVar6 + 1;
- }
- iVar6 = iVar6 + __n_00;
- }
- goto LAB_080d8335;
- }
- if (cVar1 == '\n') {
- strncpy((char *)&Time,Line + iVar6 + 0x4c,__n);
- ptVar7 = &Time;
- Line[__n - 4] = '\0';
- Log("client-error","%s\n",ptVar7);
- iVar6 = __n + 1 + iVar6;
- goto LAB_080d8335;
- }
- bVar3 = isSpace((int)cVar1);
- if (bVar3) {
- __n_00 = __n;
- }
- __n = __n + 1;
- }
- ptVar7 = (time_t *)(Line + iVar6 + 0x4c);
- Log("client-error","%s\n",ptVar7);
- iVar6 = iVar6 + __n;
- goto LAB_080d8335;
- }
- Log("client-error",
- "---------------------------------------------------------------------------\n",
- ptVar7);
- }
- }
- return;
-}
-
-
-
-void CMoveObject(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- int iVar6;
- uint uVar7;
- uint uVar8;
- TPlayer *this;
- int sx;
- uint uVar9;
- uint uVar10;
- uint uVar11;
- undefined4 uVar12;
- TPlayer *pl;
- uchar Count;
- int zz;
- int zy;
- int zx;
- uchar RNum;
- int sz;
- int sy;
- int posx;
- int posy;
- int posz;
- int posx_1;
- int posy_1;
- int posz_1;
- ObjectType local_2c;
- ObjectType Type;
-
- if (Connection == (TConnection *)0x0) {
- error("CMoveObject: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d8565 to 080d870d has its CatchHandler @ 080d88c6
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- zx._3_1_ = (uchar)iVar6;
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- uVar7 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar7 = uVar7 & 0xffff;
- uVar8 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar8 = uVar8 & 0xff;
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- if (uVar2 != 0xffff) {
- zx._3_1_ = '\x01';
- }
- bVar1 = CheckSpecialCoordinates();
- if (!bVar1) {
- return;
- }
- if ((uVar2 != 0xffff) &&
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,uVar4 & 0xff), !bVar1)) {
- TConnection::GetPosition(Connection,&posz,&posx_1,&posy_1);
- print();
- return;
- }
- uVar12 = 1;
- uVar9 = uVar5;
- uVar10 = uVar7;
- uVar11 = uVar8;
- bVar1 = CheckSpecialCoordinates();
- if (!bVar1) {
- return;
- }
- if (uVar5 == 0xffff) goto LAB_080d86c1;
- if (Connection == (TConnection *)0x0) {
- error("CheckVisibility: Connection ist NULL.\n",uVar9,uVar10,uVar11,uVar12);
-LAB_080d87dd:
- bVar1 = false;
- }
- else {
- bVar1 = TConnection::IsVisible(Connection,uVar5,uVar7,uVar8);
- if (!bVar1) {
- // try { // try from 080d8792 to 080d886b has its CatchHandler @ 080d88c6
- TConnection::GetPosition(Connection,&sy,&posx,&posy);
- print();
- goto LAB_080d87dd;
- }
- bVar1 = true;
- }
- if (!bVar1) {
- return;
- }
-LAB_080d86c1:
- ObjectType::setTypeID((ObjectType *)&posz_1,0);
- if ((local_2c.TypeID != posz_1) &&
- (((bVar1 = ObjectType::getFlag(&local_2c,CUMULATIVE), !bVar1 || ((uchar)iVar6 != '\0')) &&
- (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)))) {
- // try { // try from 080d871f to 080d8774 has its CatchHandler @ 080d8871
- ObjectType::setTypeID((ObjectType *)&posz_1,local_2c.TypeID);
- TCreature::ToDoMove(&this->super_TCreature,uVar2,uVar3 & 0xffff,uVar4 & 0xff,
- (ObjectType *)&posz_1,zx._3_1_,uVar5,uVar7,uVar8,(uchar)iVar6);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- return;
-}
-
-
-
-void CTradeObject(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- int iVar6;
- ulong TradePartner_00;
- TPlayer *this;
- ulong TradePartner;
- TPlayer *pl;
- uchar RNum;
- int z;
- int y;
- int x;
- int posx;
- int posy;
- int posz;
- int local_2c;
- ObjectType Type;
-
- if (Connection == (TConnection *)0x0) {
- error("CTradeObject: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d8905 to 080d89fc has its CatchHandler @ 080d8b26
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- pl._3_1_ = (uchar)iVar6;
- TradePartner_00 = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- if (uVar2 != 0xffff) {
- pl._3_1_ = '\x01';
- }
- bVar1 = CheckSpecialCoordinates();
- if (bVar1) {
- if ((uVar2 == 0xffff) ||
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,uVar4 & 0xff), bVar1)
- ) {
- ObjectType::setTypeID((ObjectType *)&posz,0);
- if ((local_2c != posz) &&
- (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)) {
- // try { // try from 080d8a0e to 080d8a4d has its CatchHandler @ 080d8ad1
- ObjectType::setTypeID((ObjectType *)&posz,local_2c);
- TCreature::ToDoTrade
- (&this->super_TCreature,uVar2,uVar3 & 0xffff,uVar4 & 0xff,
- (ObjectType *)&posz,pl._3_1_,TradePartner_00);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- else {
- // try { // try from 080d8a68 to 080d8acb has its CatchHandler @ 080d8b26
- TConnection::GetPosition(Connection,&x,&posx,&posy);
- print();
- }
- }
- }
- return;
-}
-
-
-
-void CInspectTrade(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- uint uVar2;
- TPlayer *pTVar3;
- int Side;
- TPlayer *pl;
- Object local_2c;
- Object Obj;
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080d8bf7 to 080d8bfb has its CatchHandler @ 080d8c40
- error("CInspectTrade: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d8b62 to 080d8bb0 has its CatchHandler @ 080d8c40
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- pTVar3 = TConnection::GetPlayer(Connection);
- if (pTVar3 != (TPlayer *)0x0) {
- TPlayer::InspectTrade((TPlayer *)&local_2c,SUB41(pTVar3,0),(uint)((uVar2 & 0xff) == 0));
- bVar1 = Object::exists(&local_2c);
- if (bVar1) {
- pl = (TPlayer *)local_2c.ObjectID;
- // try { // try from 080d8be6 to 080d8bea has its CatchHandler @ 080d8bfe
- Look((pTVar3->super_TCreature).ID,(Object *)&pl);
- }
- }
- }
- return;
-}
-
-
-
-void CAcceptTrade(TConnection *Connection)
-
-{
- TPlayer *this;
-
- if (Connection == (TConnection *)0x0) {
- error("CAcceptTrade: Connection ist NULL.\n");
- return;
- }
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- TPlayer::AcceptTrade(this);
- return;
- }
- return;
-}
-
-
-
-void CRejectTrade(TConnection *Connection)
-
-{
- TPlayer *this;
-
- if (Connection == (TConnection *)0x0) {
- error("CRejectTrade: Connection ist NULL.\n");
- return;
- }
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- TPlayer::RejectTrade(this);
- return;
- }
- return;
-}
-
-
-
-void CUseObject(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- int iVar6;
- int iVar7;
- TPlayer *this;
- int x;
- TPlayer *pl;
- uchar Dummy;
- uchar RNum;
- int z;
- int y;
- int posx;
- int posy;
- int posz;
- ObjectType local_3c [4];
- ObjectType local_2c;
- ObjectType Type;
-
- if (Connection == (TConnection *)0x0) {
- error("CUseObject: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d8cf5 to 080d8e0a has its CatchHandler @ 080d8f86
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- iVar7 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- bVar1 = CheckSpecialCoordinates();
- if (bVar1) {
- if ((uVar2 == 0xffff) ||
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,uVar4 & 0xff), bVar1)
- ) {
- ObjectType::setTypeID(local_3c,0);
- if ((((local_2c.TypeID != local_3c[0].TypeID) &&
- (bVar1 = ObjectType::getFlag(&local_2c,MULTIUSE), !bVar1)) &&
- ((bVar1 = ObjectType::getFlag(&local_2c,CONTAINER), !bVar1 ||
- ((byte)iVar7 < 0x10)))) &&
- (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)) {
- // try { // try from 080d8e1d to 080d8eae has its CatchHandler @ 080d8f31
- TCreature::ToDoWait(&this->super_TCreature,100);
- ObjectType::setTypeID(local_3c,0);
- ObjectType::setTypeID((ObjectType *)&posz,local_2c.TypeID);
- TCreature::ToDoUse(&this->super_TCreature,'\x01',uVar2,uVar3 & 0xffff,
- uVar4 & 0xff,(ObjectType *)&posz,(uchar)iVar6,(byte)iVar7,0,0
- ,0,local_3c,'\0');
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- else {
- // try { // try from 080d8ecc to 080d8f2b has its CatchHandler @ 080d8f86
- TConnection::GetPosition(Connection,&y,&posx,&posy);
- print();
- }
- }
- }
- return;
-}
-
-
-
-void CUseTwoObjects(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- int iVar6;
- uint uVar7;
- uint uVar8;
- uint uVar9;
- int iVar10;
- TPlayer *this;
- int x1;
- uint uVar11;
- uint uVar12;
- undefined4 uVar13;
- TPlayer *pl;
- uchar RNum2;
- int z2;
- int y2;
- int x2;
- uchar RNum1;
- int z1;
- int y1;
- int posx;
- int posy;
- int posz;
- int posx_1;
- int posy_1;
- int posz_1;
- ObjectType local_4c [4];
- int local_3c;
- ObjectType Type2;
- ObjectType local_2c;
- ObjectType Type1;
-
- if (Connection == (TConnection *)0x0) {
- error("CUseTwoObjects: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d8fc5 to 080d91a8 has its CatchHandler @ 080d93c0
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- uVar7 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar7 = uVar7 & 0xffff;
- uVar8 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar8 = uVar8 & 0xff;
- uVar9 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar9 = uVar9 & 0xffff;
- GetObjectType((ushort)&local_3c);
- iVar10 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar9);
- bVar1 = CheckSpecialCoordinates();
- if (!bVar1) {
- return;
- }
- if ((uVar2 != 0xffff) &&
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,uVar4 & 0xff), !bVar1)) {
- TConnection::GetPosition(Connection,&posz,&posx_1,&posy_1);
- print();
- return;
- }
- ObjectType::setTypeID(local_4c,0);
- if (local_2c.TypeID == local_4c[0].TypeID) {
- return;
- }
- bVar1 = ObjectType::getFlag(&local_2c,MULTIUSE);
- if (!bVar1) {
- return;
- }
- uVar13 = 0;
- uVar9 = uVar5;
- uVar11 = uVar7;
- uVar12 = uVar8;
- bVar1 = CheckSpecialCoordinates();
- if (!bVar1) {
- return;
- }
- if (uVar5 == 0xffff) goto LAB_080d9182;
- if (Connection == (TConnection *)0x0) {
- error("CheckVisibility: Connection ist NULL.\n",uVar9,uVar11,uVar12,uVar13);
-LAB_080d92d0:
- bVar1 = false;
- }
- else {
- bVar1 = TConnection::IsVisible(Connection,uVar5,uVar7,uVar8);
- if (!bVar1) {
- // try { // try from 080d927f to 080d935b has its CatchHandler @ 080d93c0
- TConnection::GetPosition(Connection,&y1,&posx,&posy);
- print();
- goto LAB_080d92d0;
- }
- bVar1 = true;
- }
- if (!bVar1) {
- return;
- }
-LAB_080d9182:
- ObjectType::setTypeID(local_4c,0);
- if ((local_3c != local_4c[0].TypeID) &&
- (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)) {
- // try { // try from 080d91c2 to 080d9261 has its CatchHandler @ 080d9361
- TCreature::ToDoWait(&this->super_TCreature,100);
- ObjectType::setTypeID(local_4c,local_3c);
- ObjectType::setTypeID((ObjectType *)&posz_1,local_2c.TypeID);
- TCreature::ToDoUse(&this->super_TCreature,'\x02',uVar2,uVar3 & 0xffff,uVar4 & 0xff,
- (ObjectType *)&posz_1,(uchar)iVar6,'\0',uVar5,uVar7,uVar8,local_4c,
- (uchar)iVar10);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- return;
-}
-
-
-
-void CUseOnCreature(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- uint uVar6;
- ulong id;
- TCreature *pTVar7;
- TPlayer *this;
- undefined4 uVar8;
- RESULT r;
- uint uVar9;
- undefined4 uVar10;
- TPlayer *pl;
- uchar RNum;
- int z;
- int y;
- int x;
- int posx;
- int posy;
- int posz;
- int posx_1;
- int posy_1;
- int posz_1;
- Object local_5c [4];
- Object local_4c;
- Object Obj2;
- Object local_3c;
- Object Obj1;
- ulong local_2c;
- ObjectType Type;
-
- if (Connection == (TConnection *)0x0) {
- error("CUseOnCreature: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d93f5 to 080d9655 has its CatchHandler @ 080d9826
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar3 = uVar3 & 0xffff;
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar4 = uVar4 & 0xff;
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- uVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- id = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- uVar10 = 0;
- uVar5 = uVar3;
- uVar9 = uVar4;
- bVar1 = CheckSpecialCoordinates();
- if (!bVar1) {
- return;
- }
- if ((uVar2 != 0xffff) &&
- (uVar5 = uVar3, uVar9 = uVar4, bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3,uVar4),
- !bVar1)) {
- TConnection::GetPosition(Connection,&posz,&posx_1,&posy_1);
- print();
- return;
- }
- uVar8 = 0;
- ObjectType::setTypeID((ObjectType *)&local_3c,0);
- if (local_2c == local_3c.ObjectID) {
- return;
- }
- pTVar7 = GetCreature(id);
- if (pTVar7 == (TCreature *)0x0) {
- return;
- }
- if (Connection == (TConnection *)0x0) {
- error("CheckVisibility: Connection ist NULL.\n",uVar8,uVar5,uVar9,uVar10);
-LAB_080d9726:
- bVar1 = false;
- }
- else {
- bVar1 = TConnection::IsVisible(Connection,pTVar7->posx,pTVar7->posy,pTVar7->posz);
- if (!bVar1) {
- // try { // try from 080d96d8 to 080d97be has its CatchHandler @ 080d9826
- TConnection::GetPosition(Connection,&x,&posx,&posy);
- print();
- goto LAB_080d9726;
- }
- bVar1 = true;
- }
- if (!bVar1) {
- return;
- }
- if (pTVar7->Type == PLAYER) {
- return;
- }
- this = TConnection::GetPlayer(Connection);
- if (this == (TPlayer *)0x0) {
- return;
- }
- uVar5 = (this->super_TCreature).posx - pTVar7->posx;
- if (0x7fffffff < uVar5) {
- uVar5 = -uVar5;
- }
- if ((int)uVar5 < Connection->TerminalOffsetX) {
- uVar5 = (this->super_TCreature).posy - pTVar7->posy;
- if (0x7fffffff < uVar5) {
- uVar5 = -uVar5;
- }
- if ((int)uVar5 < Connection->TerminalOffsetY) {
- ObjectType::setTypeID((ObjectType *)&local_4c,local_2c);
- GetObject((ulong)&local_3c,(this->super_TCreature).ID,uVar2,uVar3,uVar4,
- (ObjectType *)(uVar6 & 0xff));
- local_4c.ObjectID = (pTVar7->CrObject).ObjectID;
- bVar1 = Object::exists(&local_3c);
- if ((bVar1) && (bVar1 = Object::exists(&local_4c), bVar1)) {
- // try { // try from 080d9678 to 080d96ba has its CatchHandler @ 080d97c4
- TCreature::ToDoWait(&this->super_TCreature,100);
- local_5c[0].ObjectID = local_4c.ObjectID;
- posz_1 = local_3c.ObjectID;
- TCreature::ToDoUse(&this->super_TCreature,'\x02',(Object *)&posz_1,local_5c);
- TCreature::ToDoStart(&this->super_TCreature);
- return;
- }
- r = NOTACCESSIBLE;
- goto LAB_080d95cc;
- }
- }
- r = OUTOFRANGE;
-LAB_080d95cc:
- SendResult(Connection,r);
- return;
-}
-
-
-
-void CTurnObject(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- uint uVar5;
- int iVar6;
- TPlayer *this;
- TPlayer *pl;
- int z;
- int y;
- int x;
- int posx;
- int posy;
- int posz;
- int local_2c;
- ObjectType Type;
-
- if (Connection == (TConnection *)0x0) {
- error("CTurnObject: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d9865 to 080d9944 has its CatchHandler @ 080d9a76
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar5 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar5 = uVar5 & 0xffff;
- GetObjectType((ushort)&local_2c);
- iVar6 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer,uVar5);
- bVar1 = CheckSpecialCoordinates();
- if (bVar1) {
- if ((uVar2 == 0xffff) ||
- (bVar1 = TConnection::IsVisible(Connection,uVar2,uVar3 & 0xffff,uVar4 & 0xff), bVar1)
- ) {
- ObjectType::setTypeID((ObjectType *)&posz,0);
- if ((local_2c != posz) &&
- (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)) {
- // try { // try from 080d9957 to 080d99a0 has its CatchHandler @ 080d9a21
- TCreature::ToDoWait(&this->super_TCreature,100);
- ObjectType::setTypeID((ObjectType *)&posz,local_2c);
- TCreature::ToDoTurn(&this->super_TCreature,uVar2,uVar3 & 0xffff,uVar4 & 0xff,
- (ObjectType *)&posz,(uchar)iVar6);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- else {
- // try { // try from 080d99bb to 080d9a1b has its CatchHandler @ 080d9a76
- TConnection::GetPosition(Connection,&x,&posx,&posy);
- print();
- }
- }
- }
- return;
-}
-
-
-
-void CCloseContainer(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- uint uVar1;
- TPlayer *this;
- TPlayer *pl;
- int Window;
- Object local_1c [4];
-
- if (Connection == (TConnection *)0x0) {
- error("CCloseContainer: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d9aab to 080d9b02 has its CatchHandler @ 080d9b05
- uVar1 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar1 = uVar1 & 0xff;
- if (uVar1 < 0x10) {
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- local_1c[0].ObjectID = NONE.ObjectID;
- TPlayer::SetOpenContainer(this,uVar1,local_1c);
- SendCloseContainer(Connection,uVar1);
- }
- }
- }
- return;
-}
-
-
-
-void CUpContainer(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- uint uVar2;
- TPlayer *this;
- int Window;
- TPlayer *pl;
- Object local_4c [4];
- _func_int_varargs **local_3c;
- _func_int_varargs **local_2c;
- Object Con;
-
- if (Connection == (TConnection *)0x0) {
- error("CUpContainer: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d9b42 to 080d9c5b has its CatchHandler @ 080d9c61
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar2 = uVar2 & 0xff;
- if ((uVar2 < 0x10) && (this = TConnection::GetPlayer(Connection), this != (TPlayer *)0x0)) {
- TPlayer::GetOpenContainer((TPlayer *)&local_2c,(int)this);
- local_3c = (_func_int_varargs **)NONE.ObjectID;
- if (local_2c != (_func_int_varargs **)NONE.ObjectID) {
- Object::getContainer(local_4c);
- local_2c = (_func_int_varargs **)local_4c[0].ObjectID;
- local_3c = (_func_int_varargs **)local_4c[0].ObjectID;
- Object::getObjectType(local_4c);
- if ((_func_int_varargs **)local_4c[0].ObjectID != (_func_int_varargs **)0x0) {
- Object::getObjectType(local_4c);
- bVar1 = false;
- if ((0 < (int)local_4c[0].ObjectID) && ((int)local_4c[0].ObjectID < 0xb)) {
- bVar1 = true;
- }
- if (!bVar1) {
- local_4c[0].ObjectID = (ulong)local_2c;
- TPlayer::SetOpenContainer(this,uVar2,local_4c);
- SendContainer(Connection,uVar2);
- return;
- }
- }
- local_4c[0].ObjectID = NONE.ObjectID;
- TPlayer::SetOpenContainer(this,uVar2,local_4c);
- SendCloseContainer(Connection,uVar2);
- }
- }
- }
- return;
-}
-
-
-
-void CRefreshContainer(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- uint uVar1;
- TPlayer *Window_00;
- int Window;
- _func_int_varargs **local_1c;
- Object Con;
-
- if (Connection == (TConnection *)0x0) {
- error("CRefreshContainer: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080d9c9b to 080d9cfb has its CatchHandler @ 080d9d00
- uVar1 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- if ((uVar1 & 0xff) < 0x10) {
- Window_00 = TConnection::GetPlayer(Connection);
- if (Window_00 != (TPlayer *)0x0) {
- TPlayer::GetOpenContainer((TPlayer *)&local_1c,(int)Window_00);
- if (local_1c != (_func_int_varargs **)NONE.ObjectID) {
- SendContainer(Connection,uVar1 & 0xff);
- }
- }
- }
- }
- return;
-}
-
-
-
-void CGetOutfit(TConnection *Connection)
-
-{
- bool bVar1;
- TPlayer *pl;
- TPlayer *pTVar2;
-
- if (Connection == (TConnection *)0x0) {
- error("CGetOutfit: Connection ist NULL.\n");
- return;
- }
- pTVar2 = TConnection::GetPlayer(Connection);
- if (pTVar2 != (TPlayer *)0x0) {
- bVar1 = CheckRight((pTVar2->super_TCreature).ID,GAMEMASTER_OUTFIT);
- if (!bVar1) {
- SendOutfit(Connection);
- return;
- }
- SendMessage(Connection,0x17,"You may not change your outfit.");
- }
- return;
-}
-
-
-
-void CSetOutfit(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *pTVar1;
- uint uVar2;
- int iVar3;
- TOutfit *pTVar4;
- int OutfitID;
- TOutfit *pTVar5;
- bool bVar6;
- TPlayer *pl;
- TOutfit NewOutfit;
- undefined4 local_18;
- uchar Colors [4];
-
- if (Connection == (TConnection *)0x0) {
- error("CSetOutfit: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d9dc0 to 080d9f8e has its CatchHandler @ 080d9f94
- pTVar1 = TConnection::GetPlayer(Connection);
- if (pTVar1 == (TPlayer *)0x0) {
- return;
- }
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[2])(Buffer);
- uVar2 = uVar2 & 0xffff;
- (*(Buffer->super_TReadStream)._vptr_TReadStream[5])(Buffer,&local_18,4);
- iVar3 = (pTVar1->super_TCreature).Sex;
- if (iVar3 == 1) {
- bVar6 = false;
- if ((0x7f < uVar2) && (uVar2 < 0x87)) {
- bVar6 = true;
- }
- if (bVar6) {
- bVar6 = CheckRight((pTVar1->super_TCreature).ID,PREMIUM_ACCOUNT);
- if (bVar6) {
- iVar3 = (pTVar1->super_TCreature).Sex;
- }
- else {
- if (0x83 < uVar2) goto LAB_080d9f0c;
- iVar3 = (pTVar1->super_TCreature).Sex;
- }
- goto LAB_080d9e00;
- }
-LAB_080d9f0c:
- print();
- }
- else {
-LAB_080d9e00:
- if (iVar3 == 2) {
- bVar6 = false;
- if ((0x87 < uVar2) && (uVar2 < 0x8f)) {
- bVar6 = true;
- }
- if ((!bVar6) ||
- ((bVar6 = CheckRight((pTVar1->super_TCreature).ID,PREMIUM_ACCOUNT), !bVar6 &&
- (0x8b < uVar2)))) goto LAB_080d9f0c;
- }
- if (((((byte)local_18 < 0x85) && (local_18._1_1_ < 0x85)) && (local_18._2_1_ < 0x85)) &&
- (local_18._3_1_ < 0x85)) {
- iVar3 = 8;
- pTVar4 = &(pTVar1->super_TCreature).OrgOutfit;
- bVar6 = pTVar4 == (TOutfit *)0x0;
- pTVar5 = &(pTVar1->super_TCreature).Outfit;
- do {
- if (iVar3 == 0) break;
- iVar3 = iVar3 + -1;
- bVar6 = (char)pTVar4->OutfitID == (char)pTVar5->OutfitID;
- pTVar4 = (TOutfit *)((int)&pTVar4->OutfitID + 1);
- pTVar5 = (TOutfit *)((int)&pTVar5->OutfitID + 1);
- } while (bVar6);
- if (bVar6) {
- (pTVar1->super_TCreature).Outfit.OutfitID = uVar2;
- *(undefined4 *)&(pTVar1->super_TCreature).Outfit.field_1.ObjectType = local_18;
- AnnounceChangedCreature((pTVar1->super_TCreature).ID,3);
- }
- (pTVar1->super_TCreature).OrgOutfit.OutfitID = uVar2;
- *(undefined4 *)&(pTVar1->super_TCreature).OrgOutfit.field_1.ObjectType = local_18;
- }
- else {
- print();
- }
- }
- return;
-}
-
-
-
-void CEditText(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- ulong uVar2;
- TPlayer *pTVar3;
- TPlayer *pl;
- uint uVar4;
- uint uVar5;
- uint *puVar6;
- uint *puVar7;
- RESULT r_00;
- uint local_103c;
- char Text [4096];
- Object local_2c;
- Object Obj;
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080da177 to 080da17b has its CatchHandler @ 080da1c6
- error("CEditText: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080d9fd8 to 080da136 has its CatchHandler @ 080da1c6
- local_2c.ObjectID = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- bVar1 = Object::exists(&local_2c);
- if (bVar1) {
- Object::getObjectType((Object *)(Text + 0xffc));
- bVar1 = ObjectType::getFlag((ObjectType *)(Text + 0xffc),WRITE);
- if (!bVar1) {
- Object::getObjectType((Object *)(Text + 0xffc));
- bVar1 = ObjectType::getFlag((ObjectType *)(Text + 0xffc),WRITEONCE);
- if ((!bVar1) || (uVar2 = Object::getAttribute(&local_2c,TEXTSTRING), uVar2 != 0))
- goto LAB_080da050;
- }
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&local_103c,0x1000);
- puVar7 = &local_103c;
- do {
- puVar6 = puVar7;
- uVar4 = *puVar6 + 0xfefefeff & ~*puVar6;
- uVar5 = uVar4 & 0x80808080;
- puVar7 = puVar6 + 1;
- } while (uVar5 == 0);
- bVar1 = (uVar4 & 0x8080) == 0;
- if (bVar1) {
- uVar5 = uVar5 >> 0x10;
- }
- if (bVar1) {
- puVar7 = (uint *)((int)puVar6 + 6);
- }
- Object::getObjectType((Object *)(Text + 0xffc));
- bVar1 = ObjectType::getFlag((ObjectType *)(Text + 0xffc),WRITE);
- Object::getObjectType((Object *)(Text + 0xffc));
- uVar2 = ObjectType::getAttribute((ObjectType *)(Text + 0xffc),!bVar1 + MAXLENGTH);
- if ((int)puVar7 + ((-3 - (uint)CARRY1((byte)uVar5,(byte)uVar5)) - (int)&local_103c) < uVar2)
- {
- pTVar3 = TConnection::GetPlayer(Connection);
- if (pTVar3 == (TPlayer *)0x0) {
- return;
- }
- Text[0xffc] = (undefined1)local_2c.ObjectID;
- Text[0xffd] = local_2c.ObjectID._1_1_;
- Text[0xffe] = local_2c.ObjectID._2_1_;
- Text[0xfff] = local_2c.ObjectID._3_1_;
- // try { // try from 080da161 to 080da165 has its CatchHandler @ 080da181
- EditText((pTVar3->super_TCreature).ID,(Object *)(Text + 0xffc),(char *)&local_103c);
- return;
- }
- r_00 = NOROOM;
- }
- else {
-LAB_080da050:
- r_00 = NOTACCESSIBLE;
- }
- SendResult(Connection,r_00);
- return;
-}
-
-
-
-void CEditList(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- RESULT r;
- uint uVar2;
- ulong uVar3;
- TPlayer *pl;
- uint uVar4;
- ulong ID;
- Object OStack_104c;
- uchar Type;
- ulong local_103c;
- Object local_102c;
- Object Door;
- char local_101c [4];
- char Text [4096];
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080da3a7 to 080da3ab has its CatchHandler @ 080da3f6
- error("CEditList: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da205 to 080da241 has its CatchHandler @ 080da3f6
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_101c,0x1000);
- local_102c.ObjectID = 0;
- pl = TConnection::GetPlayer(Connection);
- if (pl != (TPlayer *)0x0) {
- uVar4 = uVar2 & 0xff;
- if (uVar4 == 2) {
- ChangeSubowners((ushort)uVar3,pl,local_101c);
- }
- else {
- if (uVar4 < 3) {
- if (uVar4 == 1) {
- ChangeGuests((ushort)uVar3,pl,local_101c);
- return;
- }
- }
- else if (uVar4 == 3) {
- OStack_104c.ObjectID = uVar3;
- local_103c = uVar3;
- local_102c.ObjectID = uVar3;
- bVar1 = Object::exists(&local_102c);
- if (bVar1) {
- Object::getObjectType(&stack0xffffefb4);
- bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffefb4,NAMEDOOR);
- if (bVar1) {
- Object::getObjectType(&stack0xffffefb4);
- bVar1 = ObjectType::getFlag((ObjectType *)&stack0xffffefb4,TEXT);
- if (bVar1) {
- OStack_104c.ObjectID = local_102c.ObjectID;
- ChangeNameDoor(&stack0xffffefb4,pl,local_101c);
- return;
- }
- }
- }
- SendResult(Connection,NOTACCESSIBLE);
- return;
- }
- // try { // try from 080da272 to 080da398 has its CatchHandler @ 080da3b1
- error("CEditList: Unbekannter Typ %d.\n",uVar2 & 0xff);
- }
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: ChaseMode
-
-void CSetTactics(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TCombat *this;
- bool bVar1;
- uint uVar2;
- uint uVar3;
- uint uVar4;
- TPlayer *pTVar5;
- TPlayer *pl;
- int AttackMode;
- int ChaseMode;
-
- if (Connection == (TConnection *)0x0) {
- error("CSetTactics: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da432 to 080da51b has its CatchHandler @ 080da521
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- bVar1 = false;
- if (((uVar2 & 0xff) != 0) && ((uVar2 & 0xff) < 4)) {
- bVar1 = true;
- }
- if (((bVar1) && ((uVar3 & 0xff) < 2)) && ((uVar4 & 0xff) < 2)) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 != (TPlayer *)0x0) {
- this = &(pTVar5->super_TCreature).Combat;
- TCombat::SetAttackMode(this,(uchar)uVar2);
- TCombat::SetChaseMode(this,(uchar)uVar3);
- TCombat::SetSecureMode(this,(uchar)uVar4);
- }
- }
- else {
- print();
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: pl
-
-void CAttack(TConnection *Connection,TReadBuffer *Buffer,bool Follow)
-
-{
- ulong CreatureID;
- TPlayer *this;
- ulong dfd;
- TPlayer *pl;
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080da5c7 to 080da5cb has its CatchHandler @ 080da620
- error("CAttack: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da560 to 080da573 has its CatchHandler @ 080da620
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- dfd = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- // try { // try from 080da58a to 080da5a4 has its CatchHandler @ 080da5d0
- TCombat::SetAttackDest(&(this->super_TCreature).Combat,dfd,Follow);
- TCreature::ToDoAttack(&this->super_TCreature);
- TCreature::ToDoStart(&this->super_TCreature);
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: posz
-
-void CInviteToParty(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- TCreature *guest;
- TPlayer *pTVar2;
- ulong id;
- TCreature *pTVar3;
- TPlayer *pl;
- int local_1c;
- int posx;
- int posy;
- int posz;
-
- if (Connection == (TConnection *)0x0) {
- error("CInviteToParty: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da650 to 080da74b has its CatchHandler @ 080da751
- pTVar2 = TConnection::GetPlayer(Connection);
- if (pTVar2 != (TPlayer *)0x0) {
- id = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- pTVar3 = GetCreature(id);
- if (pTVar3 != (TCreature *)0x0) {
- bVar1 = TConnection::IsVisible(Connection,pTVar3->posx,pTVar3->posy,pTVar3->posz);
- if (bVar1) {
- InviteToParty((pTVar2->super_TCreature).ID,id);
- }
- else {
- TConnection::GetPosition(Connection,&local_1c,&posx,&posy);
- print();
- }
- }
- }
- }
- return;
-}
-
-
-
-void CJoinParty(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *pTVar1;
- ulong Host;
- TPlayer *pl;
-
- if (Connection == (TConnection *)0x0) {
- error("CJoinParty: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da789 to 080da7c3 has its CatchHandler @ 080da7c6
- pTVar1 = TConnection::GetPlayer(Connection);
- if (pTVar1 != (TPlayer *)0x0) {
- Host = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- JoinParty((pTVar1->super_TCreature).ID,Host);
- }
- }
- return;
-}
-
-
-
-void CRevokeInvitation(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *this;
- ulong Guest;
- ulong uVar1;
- TPlayer *pl;
-
- if (Connection == (TConnection *)0x0) {
- error("CRevokeInvitation: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da7f9 to 080da86b has its CatchHandler @ 080da870
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- Guest = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- uVar1 = TPlayer::GetPartyLeader(this,false);
- if (uVar1 == 0) {
- print();
- }
- else {
- RevokeInvitation((this->super_TCreature).ID,Guest);
- }
- }
- }
- return;
-}
-
-
-
-void CPassLeadership(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *this;
- ulong NewLeader;
- ulong uVar1;
- TPlayer *pl;
-
- if (Connection == (TConnection *)0x0) {
- error("CPassLeadership: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080da8a9 to 080da91b has its CatchHandler @ 080da920
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- NewLeader = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- uVar1 = TPlayer::GetPartyLeader(this,false);
- if (uVar1 == 0) {
- print();
- }
- else {
- PassLeadership((this->super_TCreature).ID,NewLeader);
- }
- }
- }
- return;
-}
-
-
-
-void CLeaveParty(TConnection *Connection)
-
-{
- TPlayer *this;
- ulong uVar1;
- TPlayer *pl;
-
- if (Connection != (TConnection *)0x0) {
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- uVar1 = TPlayer::GetPartyLeader(this,false);
- if (uVar1 == 0) {
- print();
- }
- else {
- LeaveParty((this->super_TCreature).ID,false);
- }
- }
- return;
- }
- error("CLeaveParty: Connection ist NULL.\n");
- return;
-}
-
-
-
-void COpenChannel(TConnection *Connection)
-
-{
- TPlayer *pl;
- TPlayer *pTVar1;
-
- if (Connection != (TConnection *)0x0) {
- pTVar1 = TConnection::GetPlayer(Connection);
- if (pTVar1 != (TPlayer *)0x0) {
- // try { // try from 080da9e8 to 080da9ec has its CatchHandler @ 080daa10
- OpenChannel((pTVar1->super_TCreature).ID);
- }
- return;
- }
- error("COpenChannel: Connection ist NULL.\n");
- return;
-}
-
-
-
-void CInviteToChannel(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- RESULT r;
- TPlayer *pTVar1;
- TPlayer *pl;
- char local_3c [4];
- char PlayerName [30];
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080daadb to 080daadf has its CatchHandler @ 080dab20
- error("CInviteToChannel: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080daa6c to 080daaa7 has its CatchHandler @ 080dab20
- pTVar1 = TConnection::GetPlayer(Connection);
- if (pTVar1 != (TPlayer *)0x0) {
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_3c,0x1e);
- if (local_3c[0] == '\0') {
- print();
- }
- else {
- // try { // try from 080daacd to 080daad1 has its CatchHandler @ 080daae2
- InviteToChannel((pTVar1->super_TCreature).ID,local_3c);
- }
- }
- }
- return;
-}
-
-
-
-void CExcludeFromChannel(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- RESULT r;
- TPlayer *pTVar1;
- TPlayer *pl;
- char local_3c [4];
- char PlayerName [30];
-
- if (Connection == (TConnection *)0x0) {
- // try { // try from 080dab97 to 080dab9b has its CatchHandler @ 080dabe0
- error("CExcludeFromChannel: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080dab49 to 080dab6d has its CatchHandler @ 080dabe0
- pTVar1 = TConnection::GetPlayer(Connection);
- if (pTVar1 != (TPlayer *)0x0) {
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_3c,0x1e);
- // try { // try from 080dab7b to 080dab7f has its CatchHandler @ 080dab9e
- ExcludeFromChannel((pTVar1->super_TCreature).ID,local_3c);
- }
- }
- return;
-}
-
-
-
-void CCancel(TConnection *Connection)
-
-{
- bool bVar1;
- TPlayer *this;
- TPlayer *pl;
-
- if (Connection == (TConnection *)0x0) {
- error("CCancel: Connection ist NULL.\n");
- return;
- }
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- // try { // try from 080dac22 to 080dac2e has its CatchHandler @ 080dac75
- TCombat::StopAttack(&(this->super_TCreature).Combat,0);
- bVar1 = TCreature::ToDoClear(&this->super_TCreature);
- if (bVar1) {
- // try { // try from 080dac47 to 080dac4b has its CatchHandler @ 080dac75
- SendSnapback(Connection);
- }
- TCreature::ToDoYield(&this->super_TCreature);
- return;
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Name
-
-void CAddBuddy(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *pl;
- TPlayer *this;
- char local_2c [4];
- char Name [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CAddBuddy: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080dacba to 080dacfb has its CatchHandler @ 080dad00
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_2c,0x1e);
- if (local_2c[0] != '\0') {
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- TPlayer::AddBuddy(this,local_2c);
- }
- }
- }
- return;
-}
-
-
-
-void CRemoveBuddy(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- TPlayer *pl;
- ulong CharacterID_00;
- TPlayer *this;
- ulong CharacterID;
-
- if (Connection == (TConnection *)0x0) {
- error("CRemoveBuddy: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080dad3b to 080dad6d has its CatchHandler @ 080dad70
- CharacterID_00 = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- this = TConnection::GetPlayer(Connection);
- if (this != (TPlayer *)0x0) {
- TPlayer::RemoveBuddy(this,CharacterID_00);
- }
- }
- return;
-}
-
-
-
-void CRuleViolation(TConnection *Connection,TReadBuffer *Buffer)
-
-{
- bool bVar1;
- ulong CriminalID;
- TPlayer *cr;
- uint uVar2;
- uint uVar3;
- ulong StatementID_00;
- int iVar4;
- ulong uVar5;
- TPlayer *Gamemaster;
- bool IPBanishment;
- char *pcVar6;
- char *local_128;
- char *IPAddress;
- ulong StatementID;
- int Action;
- int Reason;
- int NumberOfStatements;
- vector<> *ReportedStatements;
- TPlayer *Criminal;
- char Comment [200];
- char local_3c [4];
- char Name [30];
-
- if (Connection == (TConnection *)0x0) {
- error("CRuleViolation: Connection ist NULL.\n");
- return;
- }
- // try { // try from 080dadb3 to 080db14e has its CatchHandler @ 080db154
- cr = TConnection::GetPlayer(Connection);
- if (cr == (TPlayer *)0x0) {
- return;
- }
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,local_3c,0x1e);
- Trim(local_3c);
- uVar2 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar2 = uVar2 & 0xff;
- uVar3 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- uVar3 = uVar3 & 0xff;
- (*(Buffer->super_TReadStream)._vptr_TReadStream[4])(Buffer,&Criminal,200);
- StatementID_00 = (*(Buffer->super_TReadStream)._vptr_TReadStream[3])(Buffer);
- iVar4 = (*(Buffer->super_TReadStream)._vptr_TReadStream[1])(Buffer);
- IPBanishment = (char)iVar4 != '\0';
- bVar1 = CheckBanishmentRight((cr->super_TCreature).ID,uVar2,uVar3);
- if ((!bVar1) ||
- ((IPBanishment && (bVar1 = CheckRight((cr->super_TCreature).ID,IP_BANISHMENT), !bVar1)))) {
- pcVar6 = "You have no authorization for this action.";
- goto LAB_080daf27;
- }
- if ((char)Criminal == '\0') {
- pcVar6 = "Please provide a comment for this report.";
- goto LAB_080daf27;
- }
- if ((uVar3 == 6) && (StatementID_00 == 0)) {
- pcVar6 = "Please provide a statement for this rule violation.";
- goto LAB_080daf27;
- }
- local_128 = (char *)0x0;
- ReportedStatements = (vector<> *)0x0;
- bVar1 = CheckRight((cr->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- iVar4 = IdentifyPlayer(local_3c,false,!bVar1,(TPlayer **)&ReportedStatements);
- if (iVar4 == 0) {
- bVar1 = CheckRight(*(ulong *)(ReportedStatements[1].init.Text + 0xac),NO_BANISHMENT);
- if (!bVar1) {
- strcpy(local_3c,ReportedStatements[1].init.Text + 0xb8);
- local_128 = ReportedStatements[2].init.Text + 0xf1;
- goto LAB_080daf8c;
- }
- if (((uVar3 == 1) || (uVar3 == 3)) || (uVar3 == 5)) {
- pcVar6 = "This name has already been approved.";
- goto LAB_080daf27;
- }
- if (uVar3 != 6) {
- pcVar6 = "You may not report a god or gamemaster.";
- goto LAB_080daf27;
- }
- }
- else {
- uVar5 = GetCharacterID(local_3c);
- if (uVar5 == 0) {
- SendResult(Connection,PLAYERNOTEXISTING);
- return;
- }
- pcVar6 = GetCharacterName(local_3c);
- strcpy(local_3c,pcVar6);
- if (IPBanishment) {
- SendMessage(Connection,0x17,"Player is not online. No IP address was banished.");
- IPBanishment = false;
- }
-LAB_080daf8c:
- Reason = 0;
- bVar1 = false;
- NumberOfStatements = 0;
- if ((0x1a < uVar2 + 0x12) && (uVar2 + 0x12 < 0x2e)) {
- bVar1 = true;
- }
- if (((!bVar1) && (uVar2 != 0x1d)) || (StatementID_00 == 0)) {
-LAB_080dafc4:
- PunishmentOrder(&cr->super_TCreature,local_3c,local_128,uVar2,uVar3,(char *)&Criminal,
- Reason,(vector<> *)NumberOfStatements,StatementID_00,IPBanishment);
- return;
- }
- uVar5 = 0;
- if (uVar3 != 6) {
- uVar5 = (cr->super_TCreature).ID;
- }
- iVar4 = GetCommunicationContext
- (uVar5,StatementID_00,&Reason,(vector<> **)&NumberOfStatements);
- if (iVar4 == 1) {
- pcVar6 = "Statement is unknown. Perhaps it is too old?";
- goto LAB_080daf27;
- }
- if (iVar4 != 2) goto LAB_080dafc4;
- }
- pcVar6 = "Statement has already been reported.";
-LAB_080daf27:
- SendMessage(Connection,0x17,pcVar6);
- return;
-}
-
-
-
-void CQuitGame(TConnection *Connection)
-
-{
- TPlayer *this;
- int iVar1;
- TPlayer *pl;
- char *Text;
-
- this = TConnection::GetPlayer(Connection);
- if (this == (TPlayer *)0x0) goto LAB_080db1b8;
- iVar1 = TCreature::LogoutPossible(&this->super_TCreature);
- if (iVar1 == 1) {
- Text = "You may not logout during or immediately after a fight!";
-LAB_080db1e2:
- SendMessage(Connection,0x17,Text);
- return;
- }
- if (iVar1 < 2) {
- if (iVar1 != 0) goto LAB_080db1a4;
- }
- else {
- if (iVar1 == 2) {
- Text = "You may not logout here!";
- goto LAB_080db1e2;
- }
-LAB_080db1a4:
- error(&DAT_0810b2e0);
- }
- TCreature::ToDoClear(&this->super_TCreature);
-LAB_080db1b8:
- TConnection::Logout(Connection,0,true);
- return;
-}
-
-
-
-void ReceiveData(TConnection *Connection)
-
-{
- byte bVar1;
- bool bVar2;
- int Length;
- int iVar3;
- ulong uVar4;
- TPlayer *pTVar5;
- TPlayer *pl;
- int Command;
- uint uVar6;
- char *pcVar7;
- int dx;
- undefined1 local_2c [4];
- TReadBuffer Buffer;
-
- if (Connection == (TConnection *)0x0) {
- pcVar7 = "ReceiveData: Connection ist NULL.\n";
-LAB_080db8fa:
- error(pcVar7);
- return;
- }
- uVar6 = Connection->InDataSize;
- if ((int)uVar6 < 1) {
- pcVar7 = "ReceiveData: Keine Daten vorhanden.\n";
- goto LAB_080db8fa;
- }
- if (0x7fe < (int)uVar6) {
- pcVar7 = &DAT_0810b360;
-LAB_080db24a:
- error(pcVar7,uVar6);
- return;
- }
- TReadBuffer::TReadBuffer((TReadBuffer *)local_2c,Connection->InData + 2,uVar6);
- // try { // try from 080db279 to 080db27d has its CatchHandler @ 080db910
- bVar1 = TReadBuffer::readByte((TReadBuffer *)local_2c);
- uVar6 = (uint)bVar1;
- if (Connection->State == CONNECTION_LOGIN) {
- if (uVar6 == 0xb) {
- bVar2 = TConnection::JoinGame(Connection,(TReadBuffer *)local_2c);
- if (bVar2) {
- return;
- }
- Log("game","Einloggen gescheitert.\n");
- SendResult(Connection,LOGINERROR);
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 == (TPlayer *)0x0) {
- error("ReceiveData: Einloggen gescheitert und keine Kreatur bekannt.\n");
- }
- else {
- DecrementIsOnlineOrder((pTVar5->super_TCreature).ID);
- }
- TConnection::Disconnect(Connection);
- return;
- }
- pcVar7 = "ReceiveData: Falsches Login-Kommando %d.\n";
- goto LAB_080db24a;
- }
- bVar2 = CommandAllowed(Connection,(ushort)bVar1);
- if (!bVar2) {
- return;
- }
- TConnection::ResetTimer(Connection,uVar6);
- switch(uVar6) {
- case 0x14:
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 != (TPlayer *)0x0) {
- iVar3 = TCreature::LogoutPossible(&pTVar5->super_TCreature);
- if (iVar3 == 1) {
- pcVar7 = "You may not logout during or immediately after a fight!";
-LAB_080db32b:
- SendMessage(Connection,0x17,pcVar7);
- return;
- }
- if (iVar3 < 2) {
- if (iVar3 != 0) goto LAB_080db2f2;
- }
- else {
- if (iVar3 == 2) {
- pcVar7 = "You may not logout here!";
- goto LAB_080db32b;
- }
-LAB_080db2f2:
- error(&DAT_0810b2e0);
- }
- TCreature::ToDoClear(&pTVar5->super_TCreature);
- }
- TConnection::Logout(Connection,0,true);
- break;
- default:
- // try { // try from 080db834 to 080db86b has its CatchHandler @ 080db982
- print();
- break;
- case 0x1e:
- break;
- case 100:
- // try { // try from 080db2c6 to 080db587 has its CatchHandler @ 080db982
- CGoPath(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x65:
- iVar3 = -1;
- goto LAB_080db358;
- case 0x66:
- iVar3 = 0;
- goto LAB_080db375;
- case 0x67:
- iVar3 = 1;
-LAB_080db358:
- dx = 0;
- goto LAB_080db360;
- case 0x68:
- iVar3 = 0;
- goto LAB_080db391;
- case 0x69:
- if (Connection != (TConnection *)0x0) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 == (TPlayer *)0x0) {
- return;
- }
- TCreature::ToDoStop(&pTVar5->super_TCreature);
- return;
- }
- pcVar7 = "CGoStop: Connection ist NULL.\n";
- goto LAB_080db3c3;
- case 0x6a:
- iVar3 = -1;
- goto LAB_080db375;
- case 0x6b:
- iVar3 = 1;
-LAB_080db375:
- dx = 1;
-LAB_080db360:
- CGoDirection(Connection,dx,iVar3);
- break;
- case 0x6c:
- iVar3 = 1;
- goto LAB_080db391;
- case 0x6d:
- iVar3 = -1;
-LAB_080db391:
- dx = -1;
- goto LAB_080db360;
- case 0x6f:
- iVar3 = 0;
- goto LAB_080db3fd;
- case 0x70:
- iVar3 = 1;
- goto LAB_080db3fd;
- case 0x71:
- iVar3 = 2;
- goto LAB_080db3fd;
- case 0x72:
- iVar3 = 3;
-LAB_080db3fd:
- CRotate(Connection,iVar3);
- break;
- case 0x78:
- CMoveObject(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x7d:
- CTradeObject(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x7e:
- CInspectTrade(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x7f:
- if (Connection != (TConnection *)0x0) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 == (TPlayer *)0x0) {
- return;
- }
- TPlayer::AcceptTrade(pTVar5);
- return;
- }
- pcVar7 = "CAcceptTrade: Connection ist NULL.\n";
- goto LAB_080db3c3;
- case 0x80:
- if (Connection != (TConnection *)0x0) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 == (TPlayer *)0x0) {
- return;
- }
- TPlayer::RejectTrade(pTVar5);
- return;
- }
- pcVar7 = "CRejectTrade: Connection ist NULL.\n";
- goto LAB_080db3c3;
- case 0x82:
- CUseObject(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x83:
- CUseTwoObjects(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x84:
- CUseOnCreature(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x85:
- CTurnObject(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x87:
- CCloseContainer(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x88:
- CUpContainer(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x89:
- CEditText(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x8a:
- CEditList(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x8c:
- CLookAtPoint(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x96:
- CTalk(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x97:
- if (Connection != (TConnection *)0x0) {
- SendChannels(Connection);
- return;
- }
- pcVar7 = "CGetChannels: Connection ist NULL.\n";
- goto LAB_080db3c3;
- case 0x98:
- CJoinChannel(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x99:
- if (Connection == (TConnection *)0x0) {
- error("CLeaveChannel: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080db597 to 080db5eb has its CatchHandler @ 080db946
- uVar6 = (**(_func_int_varargs **)((int)local_2c + 8))((TReadBuffer *)local_2c);
- iVar3 = GetNumberOfChannels();
- if (((int)(uVar6 & 0xffff) < iVar3) &&
- (pTVar5 = TConnection::GetPlayer(Connection), pTVar5 != (TPlayer *)0x0)) {
- LeaveChannel(uVar6 & 0xffff,(pTVar5->super_TCreature).ID,true);
- }
- }
- break;
- case 0x9a:
- // try { // try from 080db5f8 to 080db670 has its CatchHandler @ 080db982
- CPrivateChannel(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x9b:
- CProcessRequest(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x9c:
- CRemoveRequest(Connection,(TReadBuffer *)local_2c);
- break;
- case 0x9d:
- CCancelRequest(Connection);
- break;
- case 0xa0:
- CSetTactics(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xa1:
- bVar2 = false;
- goto LAB_080db64a;
- case 0xa2:
- bVar2 = true;
-LAB_080db64a:
- CAttack(Connection,(TReadBuffer *)local_2c,bVar2);
- break;
- case 0xa3:
- CInviteToParty(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xa4:
- if (Connection == (TConnection *)0x0) {
- error("CJoinParty: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080db67d to 080db6bb has its CatchHandler @ 080db980
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 != (TPlayer *)0x0) {
- uVar4 = (**(_func_int_varargs **)((int)local_2c + 0xc))((TReadBuffer *)local_2c);
- JoinParty((pTVar5->super_TCreature).ID,uVar4);
- }
- }
- break;
- case 0xa5:
- // try { // try from 080db6c8 to 080db7d4 has its CatchHandler @ 080db982
- CRevokeInvitation(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xa6:
- CPassLeadership(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xa7:
- if (Connection != (TConnection *)0x0) {
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 == (TPlayer *)0x0) {
- return;
- }
- uVar4 = TPlayer::GetPartyLeader(pTVar5,false);
- if (uVar4 == 0) {
- print();
- return;
- }
- LeaveParty((pTVar5->super_TCreature).ID,false);
- return;
- }
- pcVar7 = "CLeaveParty: Connection ist NULL.\n";
-LAB_080db3c3:
- error(pcVar7);
- break;
- case 0xaa:
- COpenChannel(Connection);
- break;
- case 0xab:
- CInviteToChannel(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xac:
- CExcludeFromChannel(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xbe:
- CCancel(Connection);
- break;
- case 0xc9:
- CRefreshField(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xca:
- CRefreshContainer(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xd2:
- CGetOutfit(Connection);
- break;
- case 0xd3:
- CSetOutfit(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xdc:
- CAddBuddy(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xdd:
- if (Connection == (TConnection *)0x0) {
- error("CRemoveBuddy: Connection ist NULL.\n");
- }
- else {
- // try { // try from 080db7e4 to 080db81b has its CatchHandler @ 080db946
- uVar4 = (**(_func_int_varargs **)((int)local_2c + 0xc))((TReadBuffer *)local_2c);
- pTVar5 = TConnection::GetPlayer(Connection);
- if (pTVar5 != (TPlayer *)0x0) {
- TPlayer::RemoveBuddy(pTVar5,uVar4);
- }
- }
- break;
- case 0xe6:
- CBugReport(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xe7:
- CRuleViolation(Connection,(TReadBuffer *)local_2c);
- break;
- case 0xe8:
- CErrorFileEntry(Connection,(TReadBuffer *)local_2c);
- }
- return;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-void ReceiveData(void)
-
-{
- TConnection *Connection_00;
- pid_t __pid;
- TConnection *Connection;
-
- Connection_00 = GetFirstConnection();
- while (Connection_00 != (TConnection *)0x0) {
- if ((Connection_00->State - CONNECTION_LOGIN < 4) && (Connection_00->WaitingForACK != false)
- ) {
- ReceiveData(Connection_00);
- Connection_00->WaitingForACK = false;
- if (Connection_00->State - CONNECTION_LOGIN < 4) {
- __pid = TConnection::GetPID(Connection_00);
- kill(__pid,10);
- }
- }
- Connection_00 = GetNextConnection();
- }
- return;
-}
-
-
-
// WARNING: Unknown calling convention -- yet parameter storage is locked
void _GLOBAL__I__Z14CommandAllowedP11TConnectiont(void)
diff --git a/src/common.hh b/src/common.hh
index e0bfb81..8aef0fd 100644
--- a/src/common.hh
+++ b/src/common.hh
@@ -1,6 +1,7 @@
#ifndef TIBIA_COMMON_HH_
#define TIBIA_COMMON_HH_ 1
+#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <stddef.h>
diff --git a/src/communication.cc b/src/communication.cc
index 71a05d3..799cd42 100644
--- a/src/communication.cc
+++ b/src/communication.cc
@@ -920,7 +920,7 @@ bool HandleLogin(TConnection *Connection){
TReadBuffer InputBuffer(Connection->InData, Connection->InDataSize);
try{
uint8 Command = InputBuffer.readByte();
- if(Command != 10){
+ if(Command != CL_CMD_LOGIN_REQUEST){
print(3, "Ungültiges Init-Kommando %d.\n", Command);
return false;
}
@@ -1104,7 +1104,7 @@ bool HandleLogin(TConnection *Connection){
TWriteBuffer WriteBuffer(Connection->InData + 2,
sizeof(Connection->InData) - 2);
try{
- WriteBuffer.writeByte(11);
+ WriteBuffer.writeByte(CL_CMD_LOGIN);
WriteBuffer.writeWord((int)TerminalType);
WriteBuffer.writeWord((int)TerminalVersion);
WriteBuffer.writeQuad(Slot->CharacterID);
diff --git a/src/connections.hh b/src/connections.hh
index 17cf7df..d4f0755 100644
--- a/src/connections.hh
+++ b/src/connections.hh
@@ -10,11 +10,11 @@ struct TConnection;
struct TPlayer;
enum ClientCommand: int {
- CL_CMD_LOGIN = 10,
- CL_CMD_LOGIN_TREATED = 11,
+ CL_CMD_LOGIN_REQUEST = 10,
+ CL_CMD_LOGIN = 11,
CL_CMD_LOGOUT = 20,
CL_CMD_PING = 30,
- CL_CMD_GO = 100,
+ CL_CMD_GO_PATH = 100,
CL_CMD_GO_NORTH = 101,
CL_CMD_GO_EAST = 102,
CL_CMD_GO_SOUTH = 103,
@@ -121,7 +121,7 @@ enum ServerCommand: int {
SV_CMD_CHANNELS = 171,
SV_CMD_OPEN_CHANNEL = 172,
SV_CMD_PRIVATE_CHANNEL = 173,
- SV_CMD_OPEN_REQUEST = 174,
+ SV_CMD_OPEN_REQUEST_QUEUE = 174,
SV_CMD_DELETE_REQUEST = 175,
SV_CMD_FINISH_REQUEST = 176,
SV_CMD_CLOSE_REQUEST = 177,
@@ -288,7 +288,7 @@ void SendTalk(TConnection *Connection, uint32 StatementID,
void SendChannels(TConnection *Connection);
void SendOpenChannel(TConnection *Connection, int Channel);
void SendPrivateChannel(TConnection *Connection, const char *Name);
-void SendOpenRequest(TConnection *Connection);
+void SendOpenRequestQueue(TConnection *Connection);
void SendDeleteRequest(TConnection *Connection, const char *Name);
void SendFinishRequest(TConnection *Connection, const char *Name);
void SendCloseRequest(TConnection *Connection);
@@ -300,11 +300,14 @@ void SendOutfit(TConnection *Connection);
void SendBuddyData(TConnection *Connection, uint32 CharacterID, const char *Name, bool Online);
void SendBuddyStatus(TConnection *Connection, uint32 CharacterID, bool Online);
void BroadcastMessage(int Mode, const char *Text, ...) ATTR_PRINTF(2, 3);
+void CreateGamemasterRequest(const char *Name, const char *Text);
void DeleteGamemasterRequest(const char *Name);
void InitSending(void);
void ExitSending(void);
// receiving.cc
+void ReceiveData(TConnection *Connection);
+void ReceiveData(void);
void InitReceiving(void);
void ExitReceiving(void);
diff --git a/src/cr.hh b/src/cr.hh
index a971b3b..f36f7bf 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -18,6 +18,11 @@ struct TOutfit{
uint8 Colors[4];
uint32 PackedData;
};
+
+ constexpr bool operator==(const TOutfit &Other) const {
+ return this->OutfitID == Other.OutfitID
+ && this->PackedData == Other.PackedData;
+ }
};
struct TSkillData {
diff --git a/src/info.cc b/src/info.cc
index 0461356..8f520cf 100644
--- a/src/info.cc
+++ b/src/info.cc
@@ -399,9 +399,7 @@ Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Ty
error("GetObject: Ungültiger ContainerCode x=%d,y=%d,z=%d,RNum=%d,Type=%d.\n",
x, y, z, RNum, Type.TypeID);
}
- }else if(RNum == -1){
- Obj = GetTopObject(x, y, z, false);
- }else{
+ }else if(RNum != -1){
Obj = GetFirstObject(x, y, z);
while(Obj != NONE){
if(Obj.getObjectType().getDisguise() == Type){
@@ -409,6 +407,8 @@ Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Ty
}
Obj = Obj.getNextObject();
}
+ }else{
+ Obj = GetTopObject(x, y, z, false);
}
// NOTE(fusion): `Type` can be a map container (TypeID = 0) as a wildcard for
diff --git a/src/operate.cc b/src/operate.cc
index e019d36..6fb7f20 100644
--- a/src/operate.cc
+++ b/src/operate.cc
@@ -2634,8 +2634,8 @@ void EditText(uint32 CreatureID, Object Obj, const char *Text){
int TextLength = (int)strlen(Text);
int MaxLength = (ObjType.getFlag(WRITE)
- ? ObjType.getAttribute(MAXLENGTH)
- : ObjType.getAttribute(MAXLENGTHONCE));
+ ? (int)ObjType.getAttribute(MAXLENGTH)
+ : (int)ObjType.getAttribute(MAXLENGTHONCE));
if(TextLength >= MaxLength){
throw TOOLONG;
}
diff --git a/src/receiving.cc b/src/receiving.cc
new file mode 100644
index 0000000..1c6ee00
--- /dev/null
+++ b/src/receiving.cc
@@ -0,0 +1,1818 @@
+#include "connections.hh"
+#include "info.hh"
+
+#include "stubs.hh"
+
+#include <signal.h>
+
+bool CommandAllowed(TConnection *Connection, int Command){
+ if(Connection == NULL){
+ error("CommandAllowed: Connection ist NULL.\n");
+ return false;
+ }
+
+ if(Connection->State == CONNECTION_GAME){
+ return Command != CL_CMD_LOGIN_REQUEST
+ && Command != CL_CMD_LOGIN;
+ }else if(Connection->State == CONNECTION_DEAD || Connection->State == CONNECTION_LOGOUT){
+ return Command == CL_CMD_LOGOUT
+ || Command == CL_CMD_PING
+ || Command == CL_CMD_BUG_REPORT
+ || Command == CL_CMD_ERROR_FILE_ENTRY;
+ }else{
+ error("CommandAllowed: Ungültiger Verbindungsstatus %d bei Kommando %d.\n",
+ Connection->State, Command);
+ return false;
+ }
+}
+
+bool CheckSpecialCoordinates(int Command, int x, int y, int z, bool AllowInventoryAny){
+ if(x == 0xFFFF){ // SPECIAL_COORDINATE ?
+ if(y == INVENTORY_ANY){
+ return AllowInventoryAny;
+ }else if((y >= INVENTORY_FIRST && y <= INVENTORY_LAST)
+ || (y >= CONTAINER_FIRST && y <= CONTAINER_LAST)){
+ return true;
+ }else{
+ print(3, "CheckSpecialCoordinates: Ungültige Koordinaten"
+ " [%d,%d,%d] bei Kommando %d.\n", x, y, z, Command);
+ return false;
+ }
+ }else{
+ return IsOnMap(x, y, z);
+ }
+}
+
+bool CheckVisibility(int Command, TConnection *Connection, int x, int y, int z){
+ if(Connection == NULL){
+ error("CheckVisibility: Connection ist NULL.\n");
+ return false;
+ }
+
+ bool Result = Connection->IsVisible(x, y, z);
+ if(!Result){
+ int PlayerX, PlayerY, PlayerZ;
+ Connection->GetPosition(&PlayerX, &PlayerY, &PlayerZ);
+ print(3, "CheckVisibility: Feld [%d,%d,%d] ist von [%d,%d,%d]"
+ " aus nicht sichtbar bei Kommando %d.\n",
+ x, y, z, PlayerX, PlayerY, PlayerZ, Command);
+ }
+ return Result;
+}
+
+bool CheckObjectType(int Command, int TypeID){
+ bool Result = ObjectTypeExists(TypeID);
+ if(!Result){
+ print(3, "CheckObjectType: Ungültiger Objekttyp %d bei Kommando %d.\n",
+ TypeID, Command);
+ }
+ return Result;
+}
+
+ObjectType GetObjectType(int Command, int TypeID){
+ // TODO(fusion): Isn't this already done by `ObjectType::setTypeID` ?
+ ObjectType ObjType(0);
+ if(CheckObjectType(Command, TypeID)){
+ ObjType.setTypeID(TypeID);
+ }
+ return ObjType;
+}
+
+void CQuitGame(TConnection *Connection, TReadBuffer *Buffer){
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ Connection->Logout(0, true);
+ return;
+ }
+
+ switch(Player->LogoutPossible()){
+ case 0:{
+ Player->ToDoClear();
+ Connection->Logout(0, true);
+ break;
+ }
+
+ case 1:{
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not logout during or immediately after a fight!");
+ break;
+ }
+ case 2:{
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not logout here!");
+ break;
+ }
+
+ default:{
+ // TODO(fusion): The original function would also logout the player
+ // on this case which feels weird, specially when you can't have any
+ // other result from `LogoutPossible`.
+ error("CQuitGame: Ungültiger Rückgabewert von LogoutPossible.\n");
+ break;
+ }
+ }
+}
+
+void CPing(TConnection *Connection, TReadBuffer *Buffer){
+ // NOTE(fusion): Its a no-op because it's already encoded in `Connection::TimeStamp`.
+}
+
+void CGoPath(TConnection *Connection, TReadBuffer *Buffer){
+ // TODO(fusion): Sometimes we check, sometimes we don't. It should always be
+ // valid since these functions are all called from within `ReceiveData` which
+ // also checks it.
+ if(Connection == NULL){
+ error("CGoPath: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ if(Player->ToDoClear()){
+ SendSnapback(Connection);
+ }
+
+ int Steps = (int)Buffer->readByte();
+ TToDoEntry TD = {};
+ TD.Code = TDGo;
+ TD.Go.x = Player->posx;
+ TD.Go.y = Player->posy;
+ TD.Go.z = Player->posz;
+ try{
+ for(int i = 0; i < Steps; i += 1){
+ // NOTE(fusion): For whatever reason these directions are not the same
+ // we use internally.
+ switch(Buffer->readByte()){
+ case 1: TD.Go.x += 1; break; // EAST
+ case 2: TD.Go.x += 1; TD.Go.y -= 1; break; // NORTHEAST
+ case 3: TD.Go.y -= 1; break; // NORTH
+ case 4: TD.Go.x -= 1; TD.Go.y -= 1; break; // NORTHWEST
+ case 5: TD.Go.x -= 1; break; // WEST
+ case 6: TD.Go.x -= 1; TD.Go.y += 1; break; // SOUTHWEST
+ case 7: TD.Go.y += 1; break; // SOUTH
+ case 8: TD.Go.x += 1; TD.Go.y += 1; break; // SOUTHEAST
+ default:{
+ continue;
+ }
+ }
+
+ Player->ToDoAdd(TD);
+ }
+
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+}
+
+void CGoDirection(TConnection *Connection, int OffsetX, int OffsetY){
+ if(Connection == NULL){
+ error("CGoDirection: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ try{
+ if(Player->ToDoClear()){
+ SendSnapback(Connection);
+ }
+
+ TToDoEntry TD = {};
+ TD.Code = TDGo;
+ TD.Go.x = Player->posx + OffsetX;
+ TD.Go.y = Player->posy + OffsetY;
+ TD.Go.z = Player->posz;
+ Player->ToDoAdd(TD);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+}
+
+void CGoStop(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CGoStop: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player != NULL){
+ Player->ToDoStop();
+ }
+}
+
+void CRotate(TConnection *Connection, int Direction){
+ if(Connection == NULL){
+ error("CRotate: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ try{
+ Player->ToDoRotate(Direction);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+}
+
+void CMoveObject(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CMoveObject: Connection ist NULL.\n");
+ return;
+ }
+
+ // TODO(fusion): I'm just following the convention being used. There is a
+ // comment in `ReceiveData` but the fact that there is only one command in
+ // a packet makes it unnecessary to "consume" all command's parameters.
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int OrigX = Buffer->readWord();
+ int OrigY = Buffer->readWord();
+ int OrigZ = Buffer->readByte();
+ int TypeID = Buffer->readWord();
+ uint8 RNum = Buffer->readByte();
+ int DestX = Buffer->readWord();
+ int DestY = Buffer->readWord();
+ int DestZ = Buffer->readByte();
+ uint8 Count = Buffer->readByte();
+
+ ObjectType Type = GetObjectType(CL_CMD_MOVE_OBJECT, TypeID);
+ if(Type.isMapContainer() || (Type.getFlag(CUMULATIVE) && Count == 0)){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_MOVE_OBJECT, OrigX, OrigY, OrigZ, false)
+ || !CheckSpecialCoordinates(CL_CMD_MOVE_OBJECT, DestX, DestY, DestZ, true)){
+ return;
+ }
+
+ if((OrigX != 0xFFFF && !CheckVisibility(CL_CMD_MOVE_OBJECT, Connection, OrigX, OrigY, OrigZ))
+ || (DestX != 0xFFFF && !CheckVisibility(CL_CMD_MOVE_OBJECT, Connection, DestX, DestY, DestZ))){
+ return;
+ }
+
+ // TODO(fusion): `RNum` usage in this context will only be used inside
+ // `GetObject` for indexing containers. For some reason I thought the
+ // Z coordinate was also used for that. Perhaps they're set to the same
+ // value.
+ if(OrigX != 0xFFFF){
+ RNum = 1;
+ }
+
+ try{
+ Player->ToDoMove(OrigX, OrigY, OrigZ, Type, RNum, DestX, DestY, DestZ, Count);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ if(r != NOERROR){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+ }
+}
+
+void CTradeObject(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CTradeObject: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX = Buffer->readWord();
+ int ObjY = Buffer->readWord();
+ int ObjZ = Buffer->readByte();
+ int TypeID = Buffer->readWord();
+ uint8 RNum = Buffer->readByte();
+ uint32 TradePartner = Buffer->readQuad();
+
+ ObjectType Type = GetObjectType(CL_CMD_TRADE_OBJECT, TypeID);
+ if(Type.isMapContainer()){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_TRADE_OBJECT, ObjX, ObjY, ObjZ, false)){
+ return;
+ }
+
+ if(ObjX != 0xFFFF && !CheckVisibility(CL_CMD_TRADE_OBJECT, Connection, ObjX, ObjY, ObjZ)){
+ return;
+ }
+
+ // TODO(fusion): Same as `CMoveObject`.
+ if(ObjX != 0xFFFF){
+ RNum = 1;
+ }
+
+ try{
+ Player->ToDoTrade(ObjX, ObjY, ObjZ, Type, RNum, TradePartner);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ if(r != NOERROR){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+ }
+}
+
+void CInspectTrade(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CInspectTrade: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ bool OwnOffer = (Buffer->readByte() == 0);
+ int Position = Buffer->readByte();
+ Object Obj = Player->InspectTrade(OwnOffer, Position);
+ if(Obj.exists()){
+ try{
+ Look(Player->ID, Obj);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+ }
+}
+
+void CAcceptTrade(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CAcceptTrade: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player != NULL){
+ Player->AcceptTrade();
+ }
+}
+
+void CRejectTrade(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRejectTrade: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player != NULL){
+ Player->RejectTrade();
+ }
+}
+
+void CUseObject(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CUseObject: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX = Buffer->readWord();
+ int ObjY = Buffer->readWord();
+ int ObjZ = Buffer->readByte();
+ int TypeID = Buffer->readWord();
+ uint8 RNum = Buffer->readByte();
+ uint8 Dummy = Buffer->readByte();
+
+ ObjectType Type = GetObjectType(CL_CMD_USE_OBJECT, TypeID);
+ if(Type.isMapContainer() || Type.getFlag(MULTIUSE)){
+ return;
+ }
+
+ if(Type.getFlag(CONTAINER) && Dummy >= NARRAY(TPlayer::OpenContainer)){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_USE_OBJECT, ObjX, ObjY, ObjZ, false)){
+ return;
+ }
+
+ if(ObjX != 0xFFFF && !CheckVisibility(CL_CMD_USE_OBJECT, Connection, ObjX, ObjY, ObjZ)){
+ return;
+ }
+
+ try{
+ Player->ToDoWait(100);
+ Player->ToDoUse(1, ObjX, ObjY, ObjZ, Type, RNum, Dummy, 0, 0, 0, 0, 0);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoClear();
+ Player->ToDoYield();
+ }
+}
+
+void CUseTwoObjects(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CUseTwoObjects: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX1 = Buffer->readWord();
+ int ObjY1 = Buffer->readWord();
+ int ObjZ1 = Buffer->readByte();
+ int TypeID1 = Buffer->readWord();
+ uint8 RNum1 = Buffer->readByte();
+ int ObjX2 = Buffer->readWord();
+ int ObjY2 = Buffer->readWord();
+ int ObjZ2 = Buffer->readByte();
+ int TypeID2 = Buffer->readWord();
+ uint8 RNum2 = Buffer->readByte();
+
+ ObjectType Type1 = GetObjectType(CL_CMD_USE_TWO_OBJECTS, TypeID1);
+ ObjectType Type2 = GetObjectType(CL_CMD_USE_TWO_OBJECTS, TypeID2);
+ if(Type1.isMapContainer() || Type2.isMapContainer() || !Type1.getFlag(MULTIUSE)){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_USE_TWO_OBJECTS, ObjX1, ObjY1, ObjZ1, false)
+ || !CheckSpecialCoordinates(CL_CMD_USE_TWO_OBJECTS, ObjX2, ObjY2, ObjZ2, false)){
+ return;
+ }
+
+ if((ObjX1 != 0xFFFF && !CheckVisibility(CL_CMD_USE_TWO_OBJECTS, Connection, ObjX1, ObjY1, ObjZ1))
+ || (ObjX2 != 0xFFFF && !CheckVisibility(CL_CMD_USE_TWO_OBJECTS, Connection, ObjX2, ObjY2, ObjZ2))){
+ return;
+ }
+
+ try{
+ Player->ToDoWait(100);
+ Player->ToDoUse(2, ObjX1, ObjY1, ObjZ1, Type1, RNum1, 0,
+ ObjX2, ObjY2, ObjZ2, Type2, RNum2);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoClear();
+ Player->ToDoYield();
+ }
+}
+
+void CUseOnCreature(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CUseOnCreature: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX = Buffer->readWord();
+ int ObjY = Buffer->readWord();
+ int ObjZ = Buffer->readByte();
+ int TypeID = Buffer->readWord();
+ uint8 RNum = Buffer->readByte();
+ uint32 TargetID = Buffer->readQuad();
+
+ // TODO(fusion): Check `Type.getFlag(MULTIUSE)`?
+ ObjectType Type = GetObjectType(CL_CMD_USE_ON_CREATURE, TypeID);
+ if(Type.isMapContainer()){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_USE_ON_CREATURE, ObjX, ObjY, ObjZ, false)){
+ return;
+ }
+
+ if(ObjX != 0xFFFF && !CheckVisibility(CL_CMD_USE_ON_CREATURE, Connection, ObjX, ObjY, ObjZ)){
+ return;
+ }
+
+ TCreature *Target = GetCreature(TargetID);
+ if(Target == NULL || Target->Type == PLAYER){
+ return;
+ }
+
+ if(!CheckVisibility(CL_CMD_USE_ON_CREATURE, Connection,
+ Target->posx, Target->posy, Target->posz)){
+ return;
+ }
+
+ // TODO(fusion): Isn't this already checked with `CheckVisibility`? It also
+ // checks against the terminal offset which is not a distance semantically.
+ int DistanceX = std::abs(Target->posx - Player->posx);
+ int DistanceY = std::abs(Target->posy - Player->posy);
+ if(DistanceX >= Connection->TerminalOffsetX
+ || DistanceY >= Connection->TerminalOffsetY){
+ SendResult(Connection, OUTOFRANGE);
+ return;
+ }
+
+ Object Obj = GetObject(Player->ID, ObjX, ObjY, ObjZ, RNum, Type);
+ if(!Obj.exists() || !Target->CrObject.exists()){
+ SendResult(Connection, NOTACCESSIBLE);
+ return;
+ }
+
+ try{
+ Player->ToDoWait(100);
+ Player->ToDoUse(2, Obj, Target->CrObject);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoClear();
+ Player->ToDoYield();
+ }
+}
+
+void CTurnObject(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CTurnObject: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX = Buffer->readWord();
+ int ObjY = Buffer->readWord();
+ int ObjZ = Buffer->readByte();
+ int TypeID = Buffer->readWord();
+ uint8 RNum = Buffer->readByte();
+
+ // TODO(fusion): Check `Type.getFlag(ROTATE)`?
+ ObjectType Type = GetObjectType(CL_CMD_TURN_OBJECT, TypeID);
+ if(Type.isMapContainer()){
+ return;
+ }
+
+ if(!CheckSpecialCoordinates(CL_CMD_TURN_OBJECT, ObjX, ObjY, ObjZ, false)){
+ return;
+ }
+
+ if(ObjX != 0xFFFF && !CheckVisibility(CL_CMD_TURN_OBJECT, Connection, ObjX, ObjY, ObjZ)){
+ return;
+ }
+
+ try{
+ Player->ToDoWait(100);
+ Player->ToDoTurn(ObjX, ObjY, ObjZ, Type, RNum);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoClear();
+ Player->ToDoYield();
+ }
+}
+
+void CCloseContainer(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CCloseContainer: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ContainerNr = Buffer->readByte();
+ if(ContainerNr < NARRAY(TPlayer::OpenContainer)){
+ Player->SetOpenContainer(ContainerNr, NONE);
+ SendCloseContainer(Connection, ContainerNr);
+ }
+}
+
+void CUpContainer(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CUpContainer: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ContainerNr = Buffer->readByte();
+ if(ContainerNr < NARRAY(TPlayer::OpenContainer)){
+ Object Con = Player->GetOpenContainer(ContainerNr);
+ if(Con != NONE){
+ Object Up = Con.getContainer();
+ ObjectType UpType = Up.getObjectType();
+ if(!UpType.isMapContainer() && !UpType.isBodyContainer()){
+ Player->SetOpenContainer(ContainerNr, Up);
+ SendContainer(Connection, ContainerNr);
+ }else{
+ Player->SetOpenContainer(ContainerNr, NONE);
+ SendCloseContainer(Connection, ContainerNr);
+ }
+ }
+ }
+}
+
+void CEditText(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CEditText: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ Object Obj = Buffer->readQuad();
+ if(!Obj.exists()){
+ SendResult(Connection, NOTACCESSIBLE);
+ return;
+ }
+
+ ObjectType ObjType = Obj.getObjectType();
+ if(!ObjType.getFlag(WRITE)
+ && (!ObjType.getFlag(WRITEONCE) || Obj.getAttribute(TEXTSTRING) != 0)){
+ SendResult(Connection, NOTACCESSIBLE);
+ return;
+ }
+
+ char Text[4096];
+ Buffer->readString(Text, sizeof(Text));
+ int TextLength = (int)strlen(Text);
+ int MaxLength = (ObjType.getFlag(WRITE)
+ ? (int)ObjType.getAttribute(MAXLENGTH)
+ : (int)ObjType.getAttribute(MAXLENGTHONCE));
+ if(TextLength >= MaxLength){
+ SendResult(Connection, NOROOM);
+ return;
+ }
+
+ try{
+ EditText(Player->ID, Obj, Text);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+}
+
+void CEditList(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CEditList: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ char Text[4096];
+ int Type = Buffer->readByte();
+ uint32 ID = Buffer->readQuad();
+ Buffer->readString(Text, sizeof(Text));
+ if(Type == GUESTLIST){
+ ChangeGuests((uint16)ID, Player, Text);
+ }else if(Type == SUBOWNERLIST){
+ ChangeSubowners((uint16)ID, Player, Text);
+ }else if(Type == DOORLIST){
+ Object Door = ID;
+ if(!Door.exists()){
+ SendResult(Connection, NOTACCESSIBLE);
+ return;
+ }
+
+ ObjectType DoorType = Door.getObjectType();
+ if(!DoorType.getFlag(NAMEDOOR) || !DoorType.getFlag(TEXT)){
+ SendResult(Connection, NOTACCESSIBLE);
+ return;
+ }
+
+ ChangeNameDoor(Door, Player, Text);
+ }else{
+ error("CEditList: Unbekannter Typ %d.\n", Type);
+ }
+}
+
+void CLookAtPoint(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CLookAtPoint: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ObjX = Buffer->readWord();
+ int ObjY = Buffer->readWord();
+ int ObjZ = Buffer->readByte();
+ if(!CheckSpecialCoordinates(CL_CMD_LOOK_AT_POINT, ObjX, ObjY, ObjZ, false)){
+ return;
+ }
+
+ if(ObjX != 0xFFFF && !CheckVisibility(CL_CMD_LOOK_AT_POINT, Connection, ObjX, ObjY, ObjZ)){
+ return;
+ }
+
+ int RNum = (ObjX == 0xFFFF ? ObjZ : -1);
+ Object Obj = GetObject(Player->ID, ObjX, ObjY, ObjZ, RNum, 0);
+ if(Obj.exists()){
+ try{
+ Look(Player->ID, Obj);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+ }
+}
+
+void CTalk(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CTalk: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ print(3, "CTalk: Der Verbindung ist kein Spieler zugeordnet.\n");
+ return;
+ }
+
+ int Mode = Buffer->readByte();
+ if(Mode != TALK_SAY
+ && Mode != TALK_WHISPER
+ && Mode != TALK_YELL
+ && Mode != TALK_PRIVATE_MESSAGE
+ && Mode != TALK_CHANNEL_CALL
+ && Mode != TALK_GAMEMASTER_REQUEST
+ && Mode != TALK_GAMEMASTER_ANSWER
+ && Mode != TALK_PLAYER_ANSWER
+ && Mode != TALK_GAMEMASTER_BROADCAST
+ && Mode != TALK_GAMEMASTER_CHANNELCALL
+ && Mode != TALK_GAMEMASTER_MESSAGE
+ && Mode != TALK_ANONYMOUS_BROADCAST
+ && Mode != TALK_ANONYMOUS_CHANNELCALL
+ && Mode != TALK_ANONYMOUS_MESSAGE){
+ print(3, "CTalk: Unbekannter Sprechmodus %d.\n", Mode);
+ return;
+ }
+
+ char Addressee[30] = {};
+ if(Mode == TALK_PRIVATE_MESSAGE
+ || Mode == TALK_GAMEMASTER_ANSWER
+ || Mode == TALK_GAMEMASTER_MESSAGE
+ || Mode == TALK_ANONYMOUS_MESSAGE){
+ Buffer->readString(Addressee, sizeof(Addressee));
+ if(Addressee[0] == 0){
+ print(3, "CTalk: Adressat nicht angegeben.\n");
+ return;
+ }
+ }
+
+ int Channel = 0;
+ if(Mode == TALK_CHANNEL_CALL
+ || Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Mode == TALK_ANONYMOUS_CHANNELCALL){
+ Channel = Buffer->readWord();
+ if(Channel >= GetNumberOfChannels()){
+ print(3, "CTalk: Ungültiger Kanal %d.\n", Channel);
+ return;
+ }
+
+ snprintf(Addressee, sizeof(Addressee), "%d", Channel);
+ }
+
+ char Text[256];
+ Buffer->readString(Text, sizeof(Text));
+ if(Text[0] == 0){
+ print(3, "CTalk: Kein Text.\n");
+ return;
+ }
+
+ if(findFirst(Text, '\n') != NULL){
+ error("CTalk: %s verwendet Newlines (%d,%s)\n", Player->Name, Mode, Text);
+ return;
+ }
+
+ if(Mode == TALK_GAMEMASTER_ANSWER && !CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL)){
+ Mode = TALK_PRIVATE_MESSAGE;
+ }else if(Mode == TALK_GAMEMASTER_BROADCAST && !CheckRight(Player->ID, GAMEMASTER_BROADCAST)){
+ Mode = TALK_SAY;
+ }else if(Mode == TALK_GAMEMASTER_CHANNELCALL && !CheckRight(Player->ID, GAMEMASTER_BROADCAST)){
+ Mode = TALK_CHANNEL_CALL;
+ }else if(Mode == TALK_GAMEMASTER_MESSAGE && !CheckRight(Player->ID, GAMEMASTER_BROADCAST)){
+ Mode = TALK_PRIVATE_MESSAGE;
+ }else if(Mode == TALK_ANONYMOUS_BROADCAST && !CheckRight(Player->ID, ANONYMOUS_BROADCAST)){
+ Mode = TALK_SAY;
+ }else if(Mode == TALK_ANONYMOUS_CHANNELCALL && !CheckRight(Player->ID, ANONYMOUS_BROADCAST)){
+ Mode = TALK_CHANNEL_CALL;
+ }else if(Mode == TALK_ANONYMOUS_MESSAGE && !CheckRight(Player->ID, ANONYMOUS_BROADCAST)){
+ Mode = TALK_PRIVATE_MESSAGE;
+ }
+
+ if(Mode == TALK_YELL && Player->Skills[SKILL_LEVEL]->Get() <= 1){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not yell as long as you are on level 1.");
+ return;
+ }
+
+ if(Mode == TALK_CHANNEL_CALL && Player->Skills[SKILL_LEVEL]->Get() <= 1){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not speak into channels as long as you are on level 1.");
+ return;
+ }
+
+ if(Mode == TALK_CHANNEL_CALL
+ || Mode == TALK_GAMEMASTER_CHANNELCALL
+ || Mode == TALK_ANONYMOUS_CHANNELCALL){
+ if(Channel == CHANNEL_RULEVIOLATIONS){
+ print(3, "ChannelCall für GM-Request-Queue.\n");
+ return;
+ }
+
+ if(!ChannelSubscribed(Channel, Player->ID)){
+ Addressee[0] = 0;
+ Mode = TALK_SAY;
+ }
+ }
+
+ if(Mode == TALK_CHANNEL_CALL && Channel == CHANNEL_HELP
+ && CheckRight(Player->ID, HIGHLIGHT_HELP_CHANNEL)){
+ Mode = TALK_HIGHLIGHT_CHANNELCALL;
+ Player->TutorActivities += 1;
+ print(3, "Aktvitätspunkt für %s.\n", Player->Name);
+ }
+
+ if(Mode == TALK_PLAYER_ANSWER){
+ if(Player->Request == 0){
+ return;
+ }
+
+ if(Player->RequestProcessingGamemaster == 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Please wait until your request is answered.");
+ return;
+ }
+
+ TPlayer *Gamemaster = GetPlayer(Player->RequestProcessingGamemaster);
+ if(Gamemaster == NULL){
+ SendCloseRequest(Connection);
+ Player->Request = 0;
+ return;
+ }
+
+ strcpy(Addressee, Gamemaster->Name);
+ }
+
+ if(Mode == TALK_GAMEMASTER_REQUEST){
+ if(Player->Request != 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You have already submitted a request."
+ " Please wait until it is answered.");
+ return;
+ }
+
+ Player->Request = AddDynamicString(Text);
+ Player->RequestTimestamp = RoundNr;
+ Player->RequestProcessingGamemaster = 0;
+ CreateGamemasterRequest(Player->Name, Text);
+ }else{
+ try{
+ Player->ToDoTalk(Mode, Addressee, Text, true);
+ Player->ToDoStart();
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+ }
+}
+
+void CGetChannels(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CGetChannels: Connection ist NULL.\n");
+ return;
+ }
+
+ SendChannels(Connection);
+}
+
+void CJoinChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CJoinChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int Channel = Buffer->readWord();
+ if(Channel < GetNumberOfChannels()){
+ try{
+ bool OwnChannel = JoinChannel(Channel, Player->ID);
+ if(Channel == CHANNEL_RULEVIOLATIONS){
+ SendOpenRequestQueue(Connection);
+ SendExistingRequests(Connection);
+ }else if(OwnChannel){
+ SendOpenOwnChannel(Connection, Channel);
+ }else{
+ SendOpenChannel(Connection, Channel);
+ }
+ }catch(RESULT r){
+ print(3, "Spieler darf Kanal nicht hören.\n");
+ }
+ }
+}
+
+void CLeaveChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CLeaveChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int Channel = Buffer->readWord();
+ if(Channel < GetNumberOfChannels()){
+ LeaveChannel(Channel, Player->ID, true);
+ }
+}
+
+void CPrivateChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CPrivateChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] == 0){
+ return;
+ }
+
+ uint32 CharacterID = GetCharacterID(Name);
+ if(CharacterID == 0){
+ SendResult(Connection, PLAYERNOTEXISTING);
+ return;
+ }
+
+ if(CharacterID == Player->ID){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You cannot set up a private message channel with yourself.");
+ return;
+ }
+
+ SendPrivateChannel(Connection, GetCharacterName(Name));
+}
+
+void CProcessRequest(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CProcessRequest: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL || !ChannelAvailable(CHANNEL_RULEVIOLATIONS, Player->ID)){
+ return;
+ }
+
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] == 0){
+ return;
+ }
+
+ TPlayer *Other;
+ if(IdentifyPlayer(Name, true, true, &Other) != 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Player is not online any more.");
+ SendFinishRequest(Connection, Name);
+ return;
+ }
+
+ if(Other->Request == 0 || Other->RequestProcessingGamemaster != 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Request has already been processed.");
+ SendFinishRequest(Connection, Name);
+ return;
+ }
+
+ Other->RequestProcessingGamemaster = Player->ID;
+ DeleteGamemasterRequest(Other->Name);
+}
+
+void CRemoveRequest(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRemoveRequest: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL || !ChannelAvailable(CHANNEL_RULEVIOLATIONS, Player->ID)){
+ return;
+ }
+
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] == 0){
+ return;
+ }
+
+ TPlayer *Other;
+ if(IdentifyPlayer(Name, true, true, &Other) != 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Player is not online any more.");
+ SendFinishRequest(Connection, Name);
+ return;
+ }
+
+ if(Other->Request != 0){
+ if(Other->RequestProcessingGamemaster == Player->ID){
+ Other->Request = 0;
+ SendCloseRequest(Other->Connection);
+ }else if(Other->RequestProcessingGamemaster == 0){
+ DeleteGamemasterRequest(Other->Name);
+ }
+ }
+}
+
+void CCancelRequest(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CCancelRequest: Connection ist NULL.\n");
+ return;
+ }
+
+ // TODO(fusion): Does this mean regular players can't cancel their requests?
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL || !ChannelAvailable(CHANNEL_RULEVIOLATIONS, Player->ID)){
+ return;
+ }
+
+ if(Player->Request != 0){
+ Player->Request = 0;
+ if(Player->RequestProcessingGamemaster != 0){
+ TPlayer *Gamemaster = GetPlayer(Player->RequestProcessingGamemaster);
+ if(Gamemaster != NULL){
+ SendFinishRequest(Gamemaster->Connection, Player->Name);
+ }
+ }else{
+ DeleteGamemasterRequest(Player->Name);
+ }
+ }
+}
+
+void CSetTactics(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CSetTactics: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int AttackMode = Buffer->readByte();
+ int ChaseMode = Buffer->readByte();
+ int SecureMode = Buffer->readByte();
+
+ if(AttackMode != ATTACK_MODE_OFFENSIVE
+ && AttackMode != ATTACK_MODE_BALANCED
+ && AttackMode != ATTACK_MODE_DEFENSIVE){
+ print(3, "CSetTactics: Ungültiger Angriffsmodus %d.\n", AttackMode);
+ return;
+ }
+
+ if(ChaseMode != CHASE_MODE_NONE
+ && ChaseMode != CHASE_MODE_CLOSE){
+ print(3, "CSetTactics: Ungültiger Verfolgungsmodus %d.\n", ChaseMode);
+ return;
+ }
+
+ if(SecureMode != SECURE_MODE_DISABLED
+ && SecureMode != SECURE_MODE_ENABLED){
+ print(3, "CSetTactics: Ungültiger Sicherheitsmodus %d.\n", SecureMode);
+ return;
+ }
+
+ Player->Combat.SetAttackMode((uint8)AttackMode);
+ Player->Combat.SetChaseMode((uint8)ChaseMode);
+ Player->Combat.SetSecureMode((uint8)SecureMode);
+}
+
+void CAttack(TConnection *Connection, TReadBuffer *Buffer, bool Follow){
+ if(Connection == NULL){
+ error("CAttack: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ uint32 TargetID = Buffer->readQuad();
+ try{
+ Player->Combat.SetAttackDest(TargetID, Follow);
+ Player->ToDoAttack();
+ Player->ToDoStart();
+ }catch(RESULT r){
+ if(r != NOERROR){
+ SendResult(Connection, r);
+ Player->ToDoYield();
+ }
+ }
+}
+
+void CInviteToParty(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CInviteToParty: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ uint32 GuestID = Buffer->readQuad();
+ TCreature *Guest = GetCreature(GuestID);
+ if(Guest == NULL){
+ return;
+ }
+
+ if(!CheckVisibility(CL_CMD_INVITE_TO_PARTY, Connection,
+ Guest->posx, Guest->posy, Guest->posz)){
+ return;
+ }
+
+ InviteToParty(Player->ID, GuestID);
+}
+
+void CJoinParty(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CJoinParty: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ uint32 HostID = Buffer->readQuad();
+ JoinParty(Player->ID, HostID);
+}
+
+void CRevokeInvitation(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRevokeInvitation: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ if(Player->GetPartyLeader(false) == 0){
+ print(3, "Spieler ist kein Mitglied einer Jagdgruppe.\n");
+ return;
+ }
+
+ uint32 GuestID = Buffer->readQuad();
+ RevokeInvitation(Player->ID, GuestID);
+}
+
+void CPassLeadership(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CPassLeadership: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ if(Player->GetPartyLeader(false) == 0){
+ print(3, "Spieler ist kein Mitglied einer Jagdgruppe.\n");
+ return;
+ }
+
+ uint32 NewLeaderID = Buffer->readQuad();
+ PassLeadership(Player->ID, NewLeaderID);
+}
+
+void CLeaveParty(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CLeaveParty: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ if(Player->GetPartyLeader(false) == 0){
+ print(3, "Spieler ist kein Mitglied einer Jagdgruppe.\n");
+ return;
+ }
+
+ LeaveParty(Player->ID, false);
+}
+
+void COpenChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("COpenChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ try{
+ OpenChannel(Player->ID);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+}
+
+void CInviteToChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CInviteToChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] == 0){
+ print(2, "CInviteToChannel: Kein Name angegeben.\n");
+ return;
+ }
+
+ try{
+ InviteToChannel(Player->ID, Name);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+}
+
+void CExcludeFromChannel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CExcludeFromChannel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ // TODO(fusion): The original function didn check if name was empty but it
+ // is probably a good idea.
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] == 0){
+ print(2, "CInviteToChannel: Kein Name angegeben.\n");
+ return;
+ }
+
+ try{
+ ExcludeFromChannel(Player->ID, Name);
+ }catch(RESULT r){
+ SendResult(Connection, r);
+ }
+}
+
+void CCancel(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CCancel: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ try{
+ Player->Combat.StopAttack(0);
+ if(Player->ToDoClear()){
+ SendSnapback(Connection);
+ }
+ }catch(RESULT r){
+ // no-op
+ }
+
+ Player->ToDoYield();
+}
+
+void CRefreshField(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRefreshField: Connection ist NULL.\n");
+ return;
+ }
+
+ int FieldX = Buffer->readWord();
+ int FieldY = Buffer->readWord();
+ int FieldZ = Buffer->readByte();
+
+ if(!IsOnMap(FieldX, FieldY, FieldZ)){
+ return;
+ }
+
+ if(!CheckVisibility(CL_CMD_REFRESH_FIELD, Connection, FieldX, FieldY, FieldZ)){
+ return;
+ }
+
+ SendFieldData(Connection, FieldX, FieldY, FieldZ);
+}
+
+void CRefreshContainer(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRefreshContainer: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ int ContainerNr = Buffer->readByte();
+ if(ContainerNr < NARRAY(TPlayer::OpenContainer)){
+ Object Con = Player->GetOpenContainer(ContainerNr);
+ if(Con != NONE){
+ SendContainer(Connection, ContainerNr);
+ }
+ }
+}
+
+void CGetOutfit(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CGetOutfit: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ if(CheckRight(Player->ID, GAMEMASTER_OUTFIT)){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not change your outfit.");
+ return;
+ }
+
+ SendOutfit(Connection);
+}
+
+void CSetOutfit(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CSetOutfit: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ TOutfit NewOutfit = {};
+ NewOutfit.OutfitID = Buffer->readWord();
+ Buffer->readBytes(NewOutfit.Colors, sizeof(NewOutfit.Colors));
+
+ int FirstOutfit = (Player->Sex == 1) ? 128 : 136;
+ int LastOutfit = (Player->Sex == 1) ? 131 : 139;
+ if(CheckRight(Player->ID, PREMIUM_ACCOUNT)){
+ LastOutfit += 3;
+ }
+
+ if(NewOutfit.OutfitID < FirstOutfit || NewOutfit.OutfitID > LastOutfit){
+ if(Player->Sex == 1){
+ print(3, "CSetOutfit: Ungültiges Outfit %d für Männer.\n", NewOutfit.OutfitID);
+ }else{
+ print(3, "CSetOutfit: Ungültiges Outfit %d für Frauen.\n", NewOutfit.OutfitID);
+ }
+ return;
+ }
+
+ if(NewOutfit.Colors[0] > 132
+ || NewOutfit.Colors[1] > 132
+ || NewOutfit.Colors[2] > 132
+ || NewOutfit.Colors[3] > 132){
+ print(3, "CSetOutfit: Ungültige Farbe für Outfit.\n");
+ return;
+ }
+
+ if(Player->Outfit == Player->OrgOutfit){
+ Player->Outfit = NewOutfit;
+ AnnounceChangedCreature(Player->ID, CREATURE_OUTFIT_CHANGED);
+ }
+
+ Player->OrgOutfit = NewOutfit;
+}
+
+void CAddBuddy(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CAddBuddy: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ char Name[30];
+ Buffer->readString(Name, sizeof(Name));
+ if(Name[0] != 0){
+ Player->AddBuddy(Name);
+ }
+}
+
+void CRemoveBuddy(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRemoveBuddy: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ uint32 CharacterID = Buffer->readQuad();
+ Player->RemoveBuddy(CharacterID);
+}
+
+// NOTE(fusion): These logging functions were out of control. It's not necessarily
+// better now but it is way simpler and do we even need any special formatting?
+
+void CBugReport(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CBugReport: Connection ist NULL.\n");
+ return;
+ }
+
+ char Text[1024];
+ Buffer->readString(Text, sizeof(Text));
+
+ bool Empty = true;
+ for(int i = 0; Text[i] != 0; i += 1){
+ if(!isprint(Text[i])){
+ Text[i] = 0;
+ break;
+ }else if(!isSpace(Text[i])){
+ Empty = false;
+ }
+ }
+
+ if(Empty){
+ return;
+ }
+
+ // NOTE(fusion): `ctime` will already add a new line character which is why
+ // there is none in this first `Log` call.
+ int PlayerX, PlayerY, PlayerZ;
+ time_t Time = time(NULL);
+ Connection->GetPosition(&PlayerX, &PlayerY, &PlayerZ);
+ Log("bugreport", "%s - %d/%d - [%d,%d,%d] - %s",
+ Connection->GetName(),
+ Connection->TerminalType,
+ Connection->TerminalVersion,
+ PlayerX, PlayerY, PlayerZ,
+ ctime(&Time));
+ Log("bugreport", "%s\n", Text);
+ Log("bugreport", "---------------------------------------------------------------------------\n");
+
+ SendMessage(Connection, TALK_STATUS_MESSAGE, "Comment sent.");
+}
+
+void CRuleViolation(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CRuleViolation: Connection ist NULL.\n");
+ return;
+ }
+
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player == NULL){
+ return;
+ }
+
+ char Name[30];
+ char Comment[200];
+ Buffer->readString(Name, sizeof(Name));
+ int Reason = Buffer->readByte();
+ int Action = Buffer->readByte();
+ Buffer->readString(Comment, sizeof(Comment));
+ uint32 StatementID = Buffer->readQuad();
+ bool IPBanishment = Buffer->readByte() != 0;
+
+ if(!CheckBanishmentRight(Player->ID, Reason, Action)
+ || (IPBanishment && !CheckRight(Player->ID, IP_BANISHMENT))){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You have no authorization for this action.");
+ return;
+ }
+
+ if(Comment[0] == 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Please provide a comment for this report.");
+ return;
+ }
+
+ if(Action == 6 && StatementID == 0){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Please provide a statement for this rule violation.");
+ return;
+ }
+
+ TPlayer *Criminal;
+ const char *IPAddress = NULL;
+ bool IgnoreGamemasters = !CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL);
+ if(IdentifyPlayer(Name, false, IgnoreGamemasters, &Criminal) == 0){
+ if(CheckRight(Criminal->ID, NO_BANISHMENT)){
+ if(Action == 1 || Action == 3 || Action == 5){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "This name has already been approved.");
+ return;
+ }
+
+ if(Action != 6){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "You may not report a god or gamemaster.");
+ return;
+ }
+ }
+
+ strcpy(Name, Criminal->Name);
+ IPAddress = Criminal->IPAddress;
+ }else{
+ if(GetCharacterID(Name) == 0){
+ SendResult(Connection, PLAYERNOTEXISTING);
+ return;
+ }
+
+ strcpy(Name, GetCharacterName(Name));
+ if(IPBanishment){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Player is not online. No IP address was banished.");
+ IPBanishment = false;
+ }
+ }
+
+ int NumberOfStatements = 0;
+ vector<TReportedStatement> *ReportedStatements = NULL;
+ bool HasStatement = ((Reason >= 9 && Reason <= 27) || Reason == 29);
+ if(HasStatement && StatementID != 0){
+ uint32 ListenerID = (Action != 6 ? Player->ID : 0);
+ int Context = GetCommunicationContext(ListenerID, StatementID,
+ &NumberOfStatements, &ReportedStatements);
+ if(Context == 1){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Statement is unknown. Perhaps it is too old?");
+ return;
+ }else if(Context == 2){
+ SendMessage(Connection, TALK_FAILURE_MESSAGE,
+ "Statement has already been reported.");
+ return;
+ }
+ }
+
+ PunishmentOrder(Player, Name,IPAddress, Reason, Action, Comment,
+ NumberOfStatements, ReportedStatements, StatementID, IPBanishment);
+}
+
+void CErrorFileEntry(TConnection *Connection, TReadBuffer *Buffer){
+ if(Connection == NULL){
+ error("CErrorFileEntry: Connection ist NULL.\n");
+ return;
+ }
+
+ char Title[64];
+ char Date[32];
+ char Stack[2048];
+ char Comment[512];
+ Buffer->readString(Title, sizeof(Title));
+ Buffer->readString(Date, sizeof(Date));
+ Buffer->readString(Stack, sizeof(Stack));
+ Buffer->readString(Comment, sizeof(Comment));
+ if(Stack[0] == 0 && Comment[0] == 0){
+ return;
+ }
+
+ // NOTE(fusion): `ctime` will already add a new line character which is why
+ // there is none in this first `Log` call.
+ int PlayerX, PlayerY, PlayerZ;
+ time_t Time = time(NULL);
+ Connection->GetPosition(&PlayerX, &PlayerY, &PlayerZ);
+ Log("client-error", "%s - %d/%d - [%d,%d,%d] - %s",
+ Connection->GetName(),
+ Connection->TerminalType,
+ Connection->TerminalVersion,
+ PlayerX, PlayerY, PlayerZ,
+ ctime(&Time));
+ Log("client-error", "%s\n", Title);
+ Log("client-error", "%s\n", Date);
+
+ if(Stack[0] != 0){
+ Log("client-error", "\n");
+ Log("client-error", "%s\n", Stack);
+ }
+
+ if(Comment[0] != 0){
+ Log("client-error", "\n");
+ Log("client-error", "%s\n", Comment);
+ }
+
+ Log("client-error","---------------------------------------------------------------------------\n");
+}
+
+void ReceiveData(TConnection *Connection){
+ if(Connection == NULL){
+ error("ReceiveData: Connection ist NULL.\n");
+ return;
+ }
+
+ if(Connection->InDataSize <= 0){
+ error("ReceiveData: Keine Daten vorhanden.\n");
+ return;
+ }
+
+ if((Connection->InDataSize + 2) > (int)sizeof(Connection->InData)){
+ error("ReceiveData: Zu große Paketlänge %d.\n", Connection->InDataSize);
+ return;
+ }
+
+ // TODO(fusion): I thought the client would actually pack multiple commands
+ // in the same packet. Perhaps not until some later version?
+
+ // IMPORTANT(fusion): The actual payload size is in the buffer's first two
+ // bytes which is why we start reading from offset two.
+ TReadBuffer Buffer(Connection->InData + 2, Connection->InDataSize);
+
+ uint8 Command;
+ try{
+ Command = Buffer.readByte();
+ }catch(const char *str){
+ error("ReceiveData: Fehler beim Auslesen des Kommandos (%s).\n", str);
+ return;
+ }
+
+ if(Connection->State == CONNECTION_LOGIN){
+ if(Command != CL_CMD_LOGIN){
+ error("ReceiveData: Falsches Login-Kommando %d.\n", Command);
+ }else if(!Connection->JoinGame(&Buffer)){
+ Log("game", "Einloggen gescheitert.\n");
+ SendResult(Connection, LOGINERROR);
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player != NULL){
+ DecrementIsOnlineOrder(Player->ID);
+ }else{
+ error("ReceiveData: Einloggen gescheitert und keine Kreatur bekannt.\n");
+ }
+ Connection->Disconnect();
+ }
+ return;
+ }
+
+ if(!CommandAllowed(Connection, Command)){
+ return;
+ }
+
+ Connection->ResetTimer(Command);
+ try{
+ switch(Command){
+ case CL_CMD_LOGOUT: CQuitGame(Connection, &Buffer); break;
+ case CL_CMD_PING: CPing(Connection, &Buffer); break;
+ case CL_CMD_GO_PATH: CGoPath(Connection, &Buffer); break;
+ case CL_CMD_GO_NORTH: CGoDirection(Connection, 0, -1); break;
+ case CL_CMD_GO_EAST: CGoDirection(Connection, 1, 0); break;
+ case CL_CMD_GO_SOUTH: CGoDirection(Connection, 0, 1); break;
+ case CL_CMD_GO_WEST: CGoDirection(Connection, -1, 0); break;
+ case CL_CMD_GO_STOP: CGoStop(Connection, &Buffer); break;
+ case CL_CMD_GO_NORTHEAST: CGoDirection(Connection, 1, -1); break;
+ case CL_CMD_GO_SOUTHEAST: CGoDirection(Connection, 1, 1); break;
+ case CL_CMD_GO_SOUTHWEST: CGoDirection(Connection, -1, 1); break;
+ case CL_CMD_GO_NORTHWEST: CGoDirection(Connection, -1, -1); break;
+ case CL_CMD_ROTATE_NORTH: CRotate(Connection, DIRECTION_NORTH); break;
+ case CL_CMD_ROTATE_EAST: CRotate(Connection, DIRECTION_EAST); break;
+ case CL_CMD_ROTATE_SOUTH: CRotate(Connection, DIRECTION_SOUTH); break;
+ case CL_CMD_ROTATE_WEST: CRotate(Connection, DIRECTION_WEST); break;
+ case CL_CMD_MOVE_OBJECT: CMoveObject(Connection, &Buffer); break;
+ case CL_CMD_TRADE_OBJECT: CTradeObject(Connection, &Buffer); break;
+ case CL_CMD_INSPECT_TRADE: CInspectTrade(Connection, &Buffer); break;
+ case CL_CMD_ACCEPT_TRADE: CAcceptTrade(Connection, &Buffer); break;
+ case CL_CMD_REJECT_TRADE: CRejectTrade(Connection, &Buffer); break;
+ case CL_CMD_USE_OBJECT: CUseObject(Connection, &Buffer); break;
+ case CL_CMD_USE_TWO_OBJECTS: CUseTwoObjects(Connection, &Buffer); break;
+ case CL_CMD_USE_ON_CREATURE: CUseOnCreature(Connection, &Buffer); break;
+ case CL_CMD_TURN_OBJECT: CTurnObject(Connection, &Buffer); break;
+ case CL_CMD_CLOSE_CONTAINER: CCloseContainer(Connection, &Buffer); break;
+ case CL_CMD_UP_CONTAINER: CUpContainer(Connection, &Buffer); break;
+ case CL_CMD_EDIT_TEXT: CEditText(Connection, &Buffer); break;
+ case CL_CMD_EDIT_LIST: CEditList(Connection, &Buffer); break;
+ case CL_CMD_LOOK_AT_POINT: CLookAtPoint(Connection, &Buffer); break;
+ case CL_CMD_TALK: CTalk(Connection, &Buffer); break;
+ case CL_CMD_GET_CHANNELS: CGetChannels(Connection, &Buffer); break;
+ case CL_CMD_JOIN_CHANNEL: CJoinChannel(Connection, &Buffer); break;
+ case CL_CMD_LEAVE_CHANNEL: CLeaveChannel(Connection, &Buffer); break;
+ case CL_CMD_PRIVATE_CHANNEL: CPrivateChannel(Connection, &Buffer); break;
+ case CL_CMD_PROCESS_REQUEST: CProcessRequest(Connection, &Buffer); break;
+ case CL_CMD_REMOVE_REQUEST: CRemoveRequest(Connection, &Buffer); break;
+ case CL_CMD_CANCEL_REQUEST: CCancelRequest(Connection, &Buffer); break;
+ case CL_CMD_SET_TACTICS: CSetTactics(Connection, &Buffer); break;
+ case CL_CMD_ATTACK: CAttack(Connection, &Buffer, false); break;
+ case CL_CMD_FOLLOW: CAttack(Connection, &Buffer, true); break;
+ case CL_CMD_INVITE_TO_PARTY: CInviteToParty(Connection, &Buffer); break;
+ case CL_CMD_JOIN_PARTY: CJoinParty(Connection, &Buffer); break;
+ case CL_CMD_REVOKE_INVITATION: CRevokeInvitation(Connection, &Buffer); break;
+ case CL_CMD_PASS_LEADERSHIP: CPassLeadership(Connection, &Buffer); break;
+ case CL_CMD_LEAVE_PARTY: CLeaveParty(Connection, &Buffer); break;
+ case CL_CMD_OPEN_CHANNEL: COpenChannel(Connection, &Buffer); break;
+ case CL_CMD_INVITE_TO_CHANNEL: CInviteToChannel(Connection, &Buffer); break;
+ case CL_CMD_EXCLUDE_FROM_CHANNEL: CExcludeFromChannel(Connection, &Buffer); break;
+ case CL_CMD_CANCEL: CCancel(Connection, &Buffer); break;
+ case CL_CMD_REFRESH_FIELD: CRefreshField(Connection, &Buffer); break;
+ case CL_CMD_REFRESH_CONTAINER: CRefreshContainer(Connection, &Buffer); break;
+ case CL_CMD_GET_OUTFIT: CGetOutfit(Connection, &Buffer); break;
+ case CL_CMD_SET_OUTFIT: CSetOutfit(Connection, &Buffer); break;
+ case CL_CMD_ADD_BUDDY: CAddBuddy(Connection, &Buffer); break;
+ case CL_CMD_REMOVE_BUDDY: CRemoveBuddy(Connection, &Buffer); break;
+ case CL_CMD_BUG_REPORT: CBugReport(Connection, &Buffer); break;
+ case CL_CMD_RULE_VIOLATION: CRuleViolation(Connection, &Buffer); break;
+ case CL_CMD_ERROR_FILE_ENTRY: CErrorFileEntry(Connection, &Buffer); break;
+ default:{
+ print(3, "Unbekanntes Kommando %d.\n", Command);
+ break;
+ }
+ }
+ }catch(const char *str){
+ error("Fehler beim Auslesen der Daten für Kommando %d (%s).\n", Command, str);
+ }
+}
+
+void ReceiveData(void){
+ TConnection *Connection = GetFirstConnection();
+ while(Connection != NULL){
+ if(Connection->Live() && Connection->WaitingForACK){
+ ReceiveData(Connection);
+ Connection->WaitingForACK = false;
+ // TODO(fusion): It could have been disconnected inside `ReceiveData`?
+ if(Connection->Live()){
+ kill(Connection->GetPID(), SIGUSR1);
+ }
+ }
+ Connection = GetNextConnection();
+ }
+}
+
+void InitReceiving(void){
+ // no-op
+}
+
+void ExitReceiving(void){
+ // no-op
+}
diff --git a/src/sending.cc b/src/sending.cc
index 52c3e28..14551da 100644
--- a/src/sending.cc
+++ b/src/sending.cc
@@ -1091,8 +1091,8 @@ void SendEditText(TConnection *Connection, Object Obj){
char SpellbookBuffer[4096] = {};
if(ObjType.getFlag(WRITE) || ObjType.getFlag(WRITEONCE)){
MaxLength = (ObjType.getFlag(WRITE)
- ? ObjType.getAttribute(MAXLENGTH)
- : ObjType.getAttribute(MAXLENGTHONCE));
+ ? (int)ObjType.getAttribute(MAXLENGTH)
+ : (int)ObjType.getAttribute(MAXLENGTHONCE));
MaxLength -= 1;
Text = GetDynamicString(Obj.getAttribute(TEXTSTRING));
Editor = GetDynamicString(Obj.getAttribute(EDITOR));
@@ -1532,12 +1532,12 @@ void SendPrivateChannel(TConnection *Connection, const char *Name){
FinishSendData(Connection);
}
-void SendOpenRequest(TConnection *Connection){
+void SendOpenRequestQueue(TConnection *Connection){
if(!BeginSendData(Connection)){
return;
}
- SendByte(Connection, SV_CMD_OPEN_REQUEST);
+ SendByte(Connection, SV_CMD_OPEN_REQUEST_QUEUE);
SendWord(Connection, (uint16)CHANNEL_RULEVIOLATIONS);
FinishSendData(Connection);
}
@@ -1724,6 +1724,29 @@ void BroadcastMessage(int Mode, const char *Text, ...){
}
}
+void CreateGamemasterRequest(const char *Name, const char *Text){
+ if(Name == NULL){
+ error("CreateGamemasterRequest: Name ist NULL.\n");
+ return;
+ }
+
+ if(Text == NULL){
+ error("CreateGamemasterRequest: Name ist NULL.\n");
+ return;
+ }
+
+ TConnection *Connection = GetFirstConnection();
+ while(Connection != NULL){
+ if(Connection->Live()){
+ TPlayer *Player = Connection->GetPlayer();
+ if(Player != NULL && ChannelSubscribed(CHANNEL_RULEVIOLATIONS, Player->ID)){
+ SendTalk(Connection, 0, Name, TALK_GAMEMASTER_REQUEST, Text, 0);
+ }
+ }
+ Connection = GetNextConnection();
+ }
+}
+
void DeleteGamemasterRequest(const char *Name){
if(Name == NULL){
error("DeleteGamemasterRequest: Name ist NULL.\n");
diff --git a/src/stubs.hh b/src/stubs.hh
index a7bd80d..e3b694e 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -18,6 +18,9 @@ typedef void TSendMailsFunction(TPlayerData *PlayerData);
extern void AbortWriter(void);
extern void AddBuddyOrder(TCreature *Creature, uint32 CharacterID);
extern void RemoveBuddyOrder(TCreature *Creature, uint32 BuddyID);
+extern void ChangeGuests(uint16 HouseID, TPlayer *Player, const char *Text);
+extern void ChangeSubowners(uint16 HouseID, TPlayer *Player, const char *Text);
+extern void ChangeNameDoor(Object Door, TPlayer *Player, const char *Text);
extern void ChangeNPCState(TCreature *Npc, int NewState, bool Stimulus);
extern void CharacterDeathOrder(TCreature *Creature, int OldLevel,
uint32 Offender, const char *Remark, bool Unjustified);
@@ -47,7 +50,6 @@ extern void PunishmentOrder(TCreature *Creature, const char *Name, const char *I
int Reason, int Action, const char *Comment, int NumberOfStatements,
vector<TReportedStatement> *ReportedStatements, uint32 StatementID,
bool IPBanishment);
-extern void ReceiveData(void);
extern void SavePlayerData(TPlayerData *Slot);
extern bool LoadPlayerData(TPlayerData *Slot);
extern bool PlayerDataExists(uint32 CharacterID);