From 05ec30b99472e8c17cd33c29d0e7859e02dc9fc8 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Thu, 12 Jun 2025 02:09:27 -0300 Subject: more work on `operate.cc` --- reference/game.c | 330 ------------------------------------------------------- src/map.cc | 6 +- src/map.hh | 2 +- src/operate.cc | 213 +++++++++++++++++++++++++++++++++-- src/stubs.hh | 5 +- 5 files changed, 211 insertions(+), 345 deletions(-) diff --git a/reference/game.c b/reference/game.c index 2a7f774..3686e32 100644 --- a/reference/game.c +++ b/reference/game.c @@ -18375,336 +18375,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } -void AnnounceGraphicalEffect(int x,int y,int z,int Type) - -{ - TConnection *pTVar1; - bool bVar2; - ulong ID; - ulong CharacterID; - TPlayer *pTVar3; - int x_00; - TPlayer *pl; - undefined1 local_4c [4]; - TFindCreatures Search; - - bVar2 = IsOnMap(x,y,z); - if (bVar2) { - TFindCreatures::TFindCreatures((TFindCreatures *)local_4c,0x10,0xe,x,y,1); - while( true ) { - CharacterID = TFindCreatures::getNext((TFindCreatures *)local_4c); - if (CharacterID == 0) break; - pTVar3 = GetPlayer(CharacterID); - if ((pTVar3 != (TPlayer *)0x0) && - (pTVar1 = (pTVar3->super_TCreature).Connection, pTVar1 != (TConnection *)0x0)) { - bVar2 = TConnection::IsVisible(pTVar1,x,y,z); - if (bVar2) { - pTVar1 = (pTVar3->super_TCreature).Connection; - SendGraphicalEffect(pTVar1,x_00,(int)pTVar1,x,y); - } - } - } - } - return; -} - - - -void AnnounceTextualEffect(int x,int y,int z,int Color,char *Text) - -{ - TConnection *this; - bool bVar1; - ulong ID; - ulong CharacterID; - TPlayer *pTVar2; - TPlayer *pl; - undefined1 local_4c [4]; - TFindCreatures Search; - - bVar1 = IsOnMap(x,y,z); - if (bVar1) { - TFindCreatures::TFindCreatures((TFindCreatures *)local_4c,0x10,0xe,x,y,1); - while( true ) { - CharacterID = TFindCreatures::getNext((TFindCreatures *)local_4c); - if (CharacterID == 0) break; - pTVar2 = GetPlayer(CharacterID); - if ((pTVar2 != (TPlayer *)0x0) && - (this = (pTVar2->super_TCreature).Connection, this != (TConnection *)0x0)) { - bVar1 = TConnection::IsVisible(this,x,y,z); - if (bVar1) { - SendTextualEffect((pTVar2->super_TCreature).Connection,x,y,z,Color,Text); - } - } - } - } - return; -} - - - -void AnnounceMissile(int sx,int sy,int sz,int zx,int zy,int zz,int Type) - -{ - TConnection *pTVar1; - bool bVar2; - ulong ID; - ulong CharacterID; - TPlayer *pTVar3; - int iVar4; - int extraout_EDX; - int extraout_EDX_00; - TPlayer *pl; - int iVar5; - int iVar6; - undefined1 local_4c [4]; - TFindCreatures Search; - - bVar2 = IsOnMap(sx,sy,sz); - if (bVar2) { - bVar2 = IsOnMap(zx,zy,zz); - if (bVar2) { - iVar5 = sy - zy; - iVar4 = -iVar5; - if (-1 < iVar5) { - iVar4 = iVar5; - } - iVar6 = sx - zx; - iVar5 = -iVar6; - if (-1 < iVar6) { - iVar5 = iVar6; - } - TFindCreatures::TFindCreatures - ((TFindCreatures *)local_4c,iVar5 / 2 + 0x11,iVar4 / 2 + 0xf,(sx + zx) / 2, - (zy + sy) / 2,1); -LAB_0808ec90: - CharacterID = TFindCreatures::getNext((TFindCreatures *)local_4c); - if (CharacterID != 0) { - pTVar3 = GetPlayer(CharacterID); - if ((pTVar3 != (TPlayer *)0x0) && - (pTVar1 = (pTVar3->super_TCreature).Connection, pTVar1 != (TConnection *)0x0)) { - bVar2 = TConnection::IsVisible(pTVar1,sx,sy,sz); - iVar4 = extraout_EDX; - if (!bVar2) { - bVar2 = TConnection::IsVisible - ((pTVar3->super_TCreature).Connection,zx,zy,zz); - iVar4 = extraout_EDX_00; - if (!bVar2) goto LAB_0808ec90; - } - pTVar1 = (pTVar3->super_TCreature).Connection; - SendMissileEffect(pTVar1,iVar4,(int)pTVar1,sx,sy,sz,zx,zy); - } - goto LAB_0808ec90; - } - } - } - return; -} - - - -void CheckTopMoveObject(ulong CreatureID,Object *Obj,Object *Ignore) - -{ - bool bVar1; - bool bVar2; - ulong uVar3; - undefined4 *puVar4; - Object *pOVar5; - Object local_7c [4]; - Object local_6c [4]; - Object local_5c [4]; - Object local_4c; - Object Help; - Object local_3c; - Object Best; - Object local_2c; - Object Con; - - // try { // try from 0808ed5b to 0808efdb has its CatchHandler @ 0808eff3 - bVar1 = Object::exists(Obj); - if (!bVar1) { - error("CheckTopMoveObject: Objekt existiert nicht.\n"); - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_0808eeb3: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); - } - if ((CreatureID != 0) && (bVar1 = IsCreaturePlayer(CreatureID), bVar1)) { - Object::getContainer(&local_2c); - Object::getObjectType(&local_3c); - if ((local_3c.ObjectID == 0) && - ((Object::getObjectType(&local_3c), local_3c.ObjectID != 99 || - (uVar3 = Object::getCreatureID(Obj), uVar3 != CreatureID)))) { - pOVar5 = local_5c; - local_3c.ObjectID = NONE.ObjectID; - local_5c[0].ObjectID = local_2c.ObjectID; - GetFirstContainerObject(&local_4c); - local_5c[0].ObjectID = NONE.ObjectID; - if (local_4c.ObjectID != NONE.ObjectID) { - do { - local_6c[0] = (Object)Ignore->ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - if (local_4c.ObjectID != local_6c[0].ObjectID) { - local_6c[0].ObjectID = NONE.ObjectID; - bVar1 = false; - if (local_3c.ObjectID == NONE.ObjectID) { -LAB_0808ee2b: - bVar1 = true; - } - else { - Object::getObjectType(local_5c); - bVar2 = ObjectType::getFlag((ObjectType *)local_5c,UNMOVE); - if ((!bVar2) && - ((Object::getObjectType(local_5c), local_5c[0].ObjectID != 99 || - (Object::getObjectType(local_5c), local_5c[0].ObjectID != 99)))) - goto LAB_0808ee2b; - } - if (bVar1) { - local_7c[0].ObjectID = local_4c.ObjectID; - local_3c.ObjectID = local_4c.ObjectID; - local_5c[0].ObjectID = local_4c.ObjectID; - } - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,BANK); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,CLIP); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,BOTTOM); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,TOP); - if ((!bVar1) && - (pOVar5 = &local_4c, Object::getObjectType(local_7c), - local_7c[0].ObjectID != 99)) break; - } - } - } - } - pOVar5 = &local_4c; - Object::getNextObject(local_6c); - local_7c[0].ObjectID = local_6c[0].ObjectID; - local_4c.ObjectID = local_6c[0].ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - } while (local_6c[0].ObjectID != NONE.ObjectID); - } - local_7c[0].ObjectID = local_3c.ObjectID; - local_6c[0].ObjectID = local_3c.ObjectID; - if (Obj->ObjectID != local_3c.ObjectID) { - puVar4 = (undefined4 *)__cxa_allocate_exception(4,pOVar5); - *puVar4 = 1; - goto LAB_0808eeb3; - } - } - } - return; -} - - - -void CheckTopUseObject(ulong CreatureID,Object *Obj) - -{ - bool bVar1; - bool bVar2; - undefined4 *puVar3; - Object *pOVar4; - Object local_7c [4]; - Object local_6c [4]; - Object local_5c [4]; - Object local_4c; - Object Help; - Object local_3c; - Object Best; - Object local_2c; - Object Con; - - // try { // try from 0808f02b to 0808f27b has its CatchHandler @ 0808f293 - bVar1 = Object::exists(Obj); - if (!bVar1) { - error("CheckTopUseObject: Objekt existiert nicht.\n"); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_0808f19d: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); - } - if ((CreatureID != 0) && (bVar1 = IsCreaturePlayer(CreatureID), bVar1)) { - Object::getContainer(&local_2c); - Object::getObjectType(&local_3c); - if (local_3c.ObjectID == 0) { - pOVar4 = local_5c; - local_3c.ObjectID = NONE.ObjectID; - local_5c[0].ObjectID = local_2c.ObjectID; - GetFirstContainerObject(&local_4c); - local_5c[0].ObjectID = NONE.ObjectID; - if (local_4c.ObjectID != NONE.ObjectID) { - do { - local_6c[0].ObjectID = NONE.ObjectID; - bVar1 = false; - local_5c[0].ObjectID = NONE.ObjectID; - if (local_3c.ObjectID == NONE.ObjectID) { -LAB_0808f0cd: - bVar1 = true; - } - else { - Object::getObjectType(local_5c); - if (local_5c[0].ObjectID != 99) { - Object::getObjectType(local_5c); - bVar2 = ObjectType::getFlag((ObjectType *)local_5c,LIQUIDPOOL); - if (!bVar2) goto LAB_0808f0cd; - } - } - if (bVar1) { - local_7c[0].ObjectID = local_4c.ObjectID; - local_3c.ObjectID = local_4c.ObjectID; - local_5c[0].ObjectID = local_4c.ObjectID; - } - Object::getObjectType(local_7c); - pOVar4 = (Object *)0x9; - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,FORCEUSE); - if (bVar1) break; - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,BANK); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,CLIP); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,BOTTOM); - if (!bVar1) { - Object::getObjectType(local_7c); - bVar1 = ObjectType::getFlag((ObjectType *)local_7c,TOP); - if ((!bVar1) && - (pOVar4 = &local_4c, Object::getObjectType(local_7c), - local_7c[0].ObjectID != 99)) break; - } - } - } - pOVar4 = &local_4c; - Object::getNextObject(local_6c); - local_7c[0].ObjectID = local_6c[0].ObjectID; - local_4c.ObjectID = local_6c[0].ObjectID; - local_5c[0].ObjectID = NONE.ObjectID; - } while (local_6c[0].ObjectID != NONE.ObjectID); - } - local_7c[0].ObjectID = local_3c.ObjectID; - local_6c[0].ObjectID = local_3c.ObjectID; - if (Obj->ObjectID != local_3c.ObjectID) { - puVar3 = (undefined4 *)__cxa_allocate_exception(4,pOVar4); - *puVar3 = 1; - goto LAB_0808f19d; - } - } - } - return; -} - - - void CheckTopMultiuseObject(ulong CreatureID,Object *Obj) { diff --git a/src/map.cc b/src/map.cc index 9ce568d..b9085c9 100644 --- a/src/map.cc +++ b/src/map.cc @@ -2017,7 +2017,7 @@ int GetObjectPriority(Object Obj){ }else if(ObjType.isCreatureContainer()){ ObjPriority = PRIORITY_CREATURE; }else{ - ObjPriority = PRIORITY_OTHER; + ObjPriority = PRIORITY_LOW; } return ObjPriority; } @@ -2043,11 +2043,11 @@ void PlaceObject(Object Obj, Object Con, bool Append){ Object Cur(Con.getAttribute(CONTENT)); if(ConType.isMapContainer()){ // TODO(fusion): Review. The loop below was a bit rough but it seems that - // append is forced for non PRIORITY_CREATURE and PRIORITY_OTHER. + // append is forced for non PRIORITY_CREATURE and PRIORITY_LOW. int ObjPriority = GetObjectPriority(Obj); Append = Append || (ObjPriority != PRIORITY_CREATURE - && ObjPriority != PRIORITY_OTHER); + && ObjPriority != PRIORITY_LOW); while(Cur != NONE){ int CurPriority = GetObjectPriority(Cur); diff --git a/src/map.hh b/src/map.hh index e1a9e22..8989f05 100644 --- a/src/map.hh +++ b/src/map.hh @@ -26,7 +26,7 @@ enum : int { PRIORITY_BOTTOM = 2, PRIORITY_TOP = 3, PRIORITY_CREATURE = 4, - PRIORITY_OTHER = 5, + PRIORITY_LOW = 5, }; struct Object { diff --git a/src/operate.cc b/src/operate.cc index a76e723..603cc7f 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -4,7 +4,6 @@ #include "stubs.hh" // operate.cc -void CheckTopMoveObject(uint32 CreatureID, Object Obj, Object Ignore); void CheckMoveObject(uint32 CreatureID, Object Obj, bool Take); void CheckMapDestination(uint32 CreatureID, Object Obj, Object MapCon); void CheckDepotSpace(uint32 CreatureID, Object Source, Object Destination, int Count); @@ -27,6 +26,12 @@ void SeparationEvent(Object Obj, Object Start); //================================================================================================== //================================================================================================== +// TODO(fusion): The radii parameters for `TFindCreatures` are commonly around +// 16 and 14 for x and y respectively so there is probably some constant involved. +// Also, since we're talking about radii, these values are quite large when you +// consider the regular client's viewport dimensions of 15x11 visible fields or +// 18x14 total fields. + void AnnounceMovingCreature(uint32 CreatureID, Object Con){ TCreature *Creature = GetCreature(CreatureID); if(Creature == NULL){ @@ -37,12 +42,11 @@ void AnnounceMovingCreature(uint32 CreatureID, Object Con){ int ConX, ConY, ConZ; GetObjectCoordinates(Con, &ConX, &ConY, &ConZ); - // TODO(fusion): 17 and 15 are probably related to the client's viewport dimensions. - int SearchWidth = 17 + std::abs(Creature->posx - ConX) / 2; - int SearchHeight = 15 + std::abs(Creature->posy - ConY) / 2; + int SearchRadiusX = 16 + (std::abs(Creature->posx - ConX) / 2) + 1; + int SearchRadiusY = 14 + (std::abs(Creature->posy - ConY) / 2) + 1; int SearchCenterX = (Creature->posx + ConX) / 2; int SearchCenterY = (Creature->posy + ConY) / 2; - TFindCreatures Search(SearchWidth, SearchHeight, SearchCenterX, SearchCenterY, FIND_PLAYERS); + TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_PLAYERS); while(true){ uint32 CharacterID = Search.getNext(); if(CharacterID == 0){ @@ -50,9 +54,11 @@ void AnnounceMovingCreature(uint32 CreatureID, Object Con){ } TPlayer *Player = GetPlayer(CharacterID); - if(Player != NULL && Player->Connection != NULL){ - SendMoveCreature(Player->Connection, CreatureID, ConX, ConY, ConZ); + if(Player == NULL || Player->Connection == NULL){ + continue; } + + SendMoveCreature(Player->Connection, CreatureID, ConX, ConY, ConZ); } } @@ -103,8 +109,11 @@ void AnnounceChangedField(Object Obj, int Type){ } TPlayer *Player = GetPlayer(CharacterID); - if(Player == NULL || Player->Connection == NULL - || !Player->Connection->IsVisible(ObjX, ObjY, ObjZ)){ + if(Player == NULL || Player->Connection == NULL){ + continue; + } + + if(!Player->Connection->IsVisible(ObjX, ObjY, ObjZ)){ continue; } @@ -205,6 +214,187 @@ void AnnounceChangedObject(Object Obj, int Type){ } } +void AnnounceGraphicalEffect(int x, int y, int z, int Type){ + if(!IsOnMap(x, y, z)){ + return; + } + + TFindCreatures Search(16, 14, x, y, FIND_PLAYERS); + while(true){ + uint32 CharacterID = Search.getNext(); + if(CharacterID == 0){ + break; + } + + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL || Player->Connection == NULL){ + continue; + } + + if(!Player->Connection->IsVisible(x, y, z)){ + continue; + } + + SendGraphicalEffect(Player->Connection, x, y, z, Type); + } +} + +void AnnounceTextualEffect(int x, int y, int z, int Color, const char *Text){ + if(!IsOnMap(x, y, z)){ + return; + } + + TFindCreatures Search(16, 14, x, y, FIND_PLAYERS); + while(true){ + uint32 CharacterID = Search.getNext(); + if(CharacterID == 0){ + break; + } + + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL || Player->Connection == NULL){ + continue; + } + + if(!Player->Connection->IsVisible(x, y, z)){ + continue; + } + + SendTextualEffect(Player->Connection, x, y, z, Color, Text); + } +} + +void AnnounceMissile(int OrigX, int OrigY, int OrigZ, + int DestX, int DestY, int DestZ, int Type){ + if(!IsOnMap(OrigX, OrigY, OrigZ) || !IsOnMap(DestX, DestY, DestZ)){ + return; + } + + int SearchRadiusX = 16 + (std::abs(OrigX - DestX) / 2) + 1; + int SearchRadiusY = 14 + (std::abs(OrigY - DestY) / 2) + 1; + int SearchCenterX = (OrigX + DestX) / 2; + int SearchCenterY = (OrigY + DestY) / 2; + TFindCreatures Search(SearchRadiusX, SearchRadiusY, SearchCenterX, SearchCenterY, FIND_PLAYERS); + while(true){ + uint32 CharacterID = Search.getNext(); + if(CharacterID == 0){ + break; + } + + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL || Player->Connection == NULL){ + continue; + } + + if(!Player->Connection->IsVisible(OrigX, OrigY, OrigY) + && !Player->Connection->IsVisible(DestX, DestY, DestZ)){ + continue; + } + + SendMissileEffect(Player->Connection, + OrigX, OrigY, OrigY, + DestX, DestY, DestZ, Type); + } +} + +void CheckTopMoveObject(uint32 CreatureID, Object Obj, Object Ignore){ + if(!Obj.exists()){ + error("CheckTopMoveObject: Objekt existiert nicht.\n"); + throw ERROR; + } + + if(CreatureID == 0 || !IsCreaturePlayer(CreatureID)){ + return; + } + + Object Con = Obj.getContainer(); + ObjectType ConType = Con.getObjectType(); + if(!ConType.isMapContainer()){ + return; + } + + ObjectType ObjType = Obj.getObjectType(); + if(ObjType.isCreatureContainer() && Obj.getCreatureID() == CreatureID){ + return; + } + + Object Best = NONE; + bool BestIsCreature = false; + Object Help = GetFirstContainerObject(Con); + while(Help != NONE){ + if(Help != Ignore){ + ObjectType HelpType = Help.getObjectType(); + + // NOTE(fusion): We're looking for the top move object. The creature + // check here makes sure only the first creature found is kept as the + // best candidate, since creatures on a map container are in a sequence. + if(Best == NONE || (!HelpType.getFlag(UNMOVE) && (!BestIsCreature || !HelpType.isCreatureContainer()))){ + Best = Help; + BestIsCreature = HelpType.isCreatureContainer(); + } + + // TODO(fusion): This is probably some inlined function to check whether + // an object has a low stack priority. + if(!HelpType.getFlag(BANK) + && !HelpType.getFlag(CLIP) + && !HelpType.getFlag(BOTTOM) + && !HelpType.getFlag(TOP) + && !HelpType.isCreatureContainer()){ + break; + } + } + Help = Help.getNextObject(); + } + + if(Obj != Best){ + throw NOTACCESSIBLE; + } +} + +void CheckTopUseObject(uint32 CreatureID, Object Obj){ + if(!Obj.exists()){ + error("CheckTopUseObject: Objekt existiert nicht.\n"); + throw ERROR; + } + + if(CreatureID == 0 || !IsCreaturePlayer(CreatureID)){ + return; + } + + Object Con = Obj.getContainer(); + ObjectType ConType = Con.getObjectType(); + if(!ConType.isMapContainer()){ + return; + } + + Object Best = NONE; + Object Help = GetFirstContainerObject(Con); + while(Help != NONE){ + ObjectType HelpType = Help.getObjectType(); + if(Best == NONE || (!HelpType.isCreatureContainer() && !HelpType.getFlag(LIQUIDPOOL))){ + Best = Help; + } + + if(HelpType.getFlag(FORCEUSE)){ + break; + } + + if(!HelpType.getFlag(BANK) + && !HelpType.getFlag(CLIP) + && !HelpType.getFlag(BOTTOM) + && !HelpType.getFlag(TOP) + && !HelpType.isCreatureContainer()){ + break; + } + + Help = Help.getNextObject(); + } + + if(Obj != Best){ + throw NOTACCESSIBLE; + } +} + // TODO(fusion): This could have been a simple return value. void CheckContainerDestination(Object Obj, Object Con){ Object Help = Con; @@ -343,6 +533,9 @@ void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Ob error("Move: Übergebenes Objekt existiert nicht mehr.\n"); } + // NOTE(fusion): Refresh object type just in case a merge event modified it. + ObjType = Obj.getObjectType(); + int ObjCount = 1; if(ObjType.getFlag(CUMULATIVE)){ ObjCount = (int)Obj.getAttribute(AMOUNT); @@ -378,7 +571,7 @@ void Move(uint32 CreatureID, Object Obj, Object Con, int Count, bool NoMerge, Ob } } - // NOTE(fusion): `Obj` becomes the split part while `Remainder`, the remainder. + // NOTE(fusion): `Obj` becomes the split part while `Remainder`, the remaining part. Object Remainder = NONE; if(Split){ Remainder = Obj; diff --git a/src/stubs.hh b/src/stubs.hh index a2c5f25..4104dd3 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -86,11 +86,14 @@ extern void SendSetInventory(TConnection *Connection, int Position, Object Obj); extern void SendEditList(TConnection *Connection, uint8 ListType, uint32 ID, const char *Text); extern void SendFullScreen(TConnection *Connection); extern void SendFloors(TConnection *Connection, bool Up); +extern void SendGraphicalEffect(TConnection *Connection, int x, int y, int z, int Type); +extern void SendTextualEffect(TConnection *Connection, int x, int y, int z, int Color, const char *Text); +extern void SendMissileEffect(TConnection *Connection, int OrigX, int OrigY, int OrigZ, int DestX, int DestY, int DestZ, int Type); extern void SendRow(TConnection *Connection, int Direction); extern void SendMails(TPlayerData *PlayerData); extern void SendMarkCreature(TConnection *Connection, uint32 CreatureID, int Color); extern void SendMessage(TConnection *Connection, int Mode, const char *Text, ...) ATTR_PRINTF(3, 4); -void SendMoveCreature(TConnection *Connection, uint32 CreatureID, int x, int y, int z); +extern void SendMoveCreature(TConnection *Connection, uint32 CreatureID, int x, int y, int z); extern void SendPlayerData(TConnection *Connection); extern void SendPlayerSkills(TConnection *Connection); extern void SendPlayerState(TConnection *Connection, uint8 State); -- cgit v1.2.3