diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/map.cc | 6 | ||||
| -rw-r--r-- | src/map.hh | 2 | ||||
| -rw-r--r-- | src/operate.cc | 213 | ||||
| -rw-r--r-- | src/stubs.hh | 5 |
4 files changed, 211 insertions, 15 deletions
@@ -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); @@ -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); |
