rendered paste bodyIndex: src/server/gem.cpp
===================================================================
--- src/server/gem.cpp (Revision 1785)
+++ src/server/gem.cpp (Arbeitskopie)
@@ -1300,109 +1300,124 @@
}
else if ( msg_id == "pickup")
{
- // If the player is in range of the item AND the item may be picked up or securityOveride, and check for dead user
- if (actor->IsAlive() && RangeTo(actor) < RANGE_TO_SELECT && IsPickable())
+ // Check if the char is dead
+ if (!actor->IsAlive())
{
- gemActor* gActor = dynamic_cast<gemActor*>(actor);
- psCharacter* chardata = NULL;
- if (gActor) chardata = gActor->GetCharacterData();
+ psserver->SendSystemInfo(clientnum,"You can't pick up items when you're dead.");
+ return;
+ }
+ // Check if the item is pickupable
+ if (!IsPickable())
+ {
+ psserver->SendSystemInfo(clientnum,"You can't pick up %s.", GetName());
+ return;
+ }
- psItem* item = GetItem();
+ // Check if the item is in range
+ if (!(RangeTo(actor) < RANGE_TO_SELECT))
+ {
+ if (!CacheManager::GetSingleton().GetCommandManager()->Validate(actor->GetClient()->GetSecurityLevel(), "pickup override"))
+ {
+ psserver->SendSystemInfo(clientnum,"You're too far away to pick up %s.", GetName());
+ return;
+ }
+ }
- if (actor->GetClient()->GetSecurityLevel() < GM_LEVEL_2)
+ psItem* item = GetItem();
+
+ // Check if item is guarded
+ if (!CacheManager::GetSingleton().GetCommandManager()->Validate(actor->GetClient()->GetSecurityLevel(), "pickup override"))
+ {
+ unsigned int guardCharacterID = item->GetGuardingCharacterID();
+ gemActor* guardActor = GEMSupervisor::GetSingleton().FindPlayerEntity(guardCharacterID);
+ if (guardCharacterID &&
+ guardCharacterID != actor->GetCharacterData()->GetCharacterID() &&
+ guardActor &&
+ guardActor->RangeTo(item->GetGemObject()) < RANGE_TO_SELECT)
{
- unsigned int guard = item->GetGuardingCharacterID();
- gemActor* guardActor = GEMSupervisor::GetSingleton().FindPlayerEntity(guard);
- if (guard &&
- guard != actor->GetCharacterData()->GetCharacterID() &&
- guardActor &&
- guardActor->RangeTo(item->GetGemObject()) < RANGE_TO_SELECT)
- {
- psserver->SendSystemInfo(clientnum,"You notice that the item is being guarded by %s",
- guardActor->GetCharacterData()->GetCharFullName());
-
- return;
- }
+ psserver->SendSystemInfo(clientnum,"You notice that the item is being guarded by %s",
+ guardActor->GetCharacterData()->GetCharFullName());
+ return;
}
+ }
- item->ScheduleRespawn();
+ // Cache values from item, because item might be deleted by Add
+ csString qname = item->GetQuantityName();
+ gemContainer *container = dynamic_cast<gemContainer*> (this);
- // Cache values from item, because item might be deleted by Add
- csString qname = item->GetQuantityName();
- gemContainer *container = dynamic_cast<gemContainer*> (this);
+ uint32 origUID = item->GetUID();
+ unsigned short origStackCount = item->GetStackCount();
- uint32 origUID = item->GetUID();
- unsigned short origStackCount = item->GetStackCount();
-
- if (chardata && chardata->Inventory().Add(item,false, true, PSCHARACTER_SLOT_NONE, container))
+ gemActor* gActor = dynamic_cast<gemActor*>(actor);
+ psCharacter* chardata = NULL;
+ if (gActor) chardata = gActor->GetCharacterData();
+ if (chardata && chardata->Inventory().Add(item,false, true, PSCHARACTER_SLOT_NONE, container))
+ {
+ Client* client = actor->GetClient();
+ if (!client)
{
- // item is deleted if we pickup money
- if(item)
- {
- psPickupEvent evt(
+ Debug2(LOG_ANY,clientnum,"User action from unknown client! Clientnum:%d\n",clientnum);
+ return;
+ }
+ client->SetTargetObject(NULL);
+ // item is deleted if we pickup money
+ if(item)
+ {
+ item->ScheduleRespawn();
+ psPickupEvent evt(
+ chardata->GetCharacterID(),
+ item->GetUID(),
+ item->GetStackCount(),
+ (int)item->GetCurrentStats()->GetQuality(),
+ 0
+ );
+ evt.FireEvent();
+ }
+ else
+ {
+ psPickupEvent evt(
chardata->GetCharacterID(),
- item->GetUID(),
- item->GetStackCount(),
- (int)item->GetCurrentStats()->GetQuality(),
+ origUID,
+ origStackCount,
+ 0,
0
- );
- evt.FireEvent();
- }
- else
- {
- psPickupEvent evt(
- chardata->GetCharacterID(),
- origUID,
- origStackCount,
- 0,
- 0
- );
- evt.FireEvent();
- }
-
- psSystemMessage newmsg(clientnum, MSG_INFO_BASE, "%s picked up %s", actor->GetName(), qname.GetData() );
- newmsg.Multicast(actor->GetMulticastClients(),0,RANGE_TO_SELECT);
+ );
+ evt.FireEvent();
+ }
+
+ psSystemMessage newmsg(clientnum, MSG_INFO_BASE, "%s picked up %s", actor->GetName(), qname.GetData() );
+ newmsg.Multicast(actor->GetMulticastClients(),0,RANGE_TO_SELECT);
- psserver->GetCharManager()->UpdateItemViews(clientnum);
+ psserver->GetCharManager()->UpdateItemViews(clientnum);
- EntityManager::GetSingleton().RemoveActor(this); // Destroy this
- }
- else
- {
+ EntityManager::GetSingleton().RemoveActor(this); // Destroy this
+ }
+ else
+ {
- /* TODO: Include support for partial pickup of stacks
+ /* TODO: Include support for partial pickup of stacks
- // Check if part of a stack where picked up
- if (item && count > item->GetStackCount())
- {
- count = count - item->GetStackCount();
- qname = psItem::GetQuantityName(item->GetName(),count);
-
- psSystemMessage newmsg(client, MSG_INFO, "%s picked up %s", actor->GetName(), qname.GetData() );
- newmsg.Multicast(actor->GetMulticastClients(),0,RANGE_TO_SELECT);
-
- psserver->GetCharManager()->UpdateItemViews(clientnum);
+ // Check if part of a stack where picked up
+ if (item && count > item->GetStackCount())
+ {
+ count = count - item->GetStackCount();
+ qname = psItem::GetQuantityName(item->GetName(),count);
- csString buf;
- buf.Format("%s, %s, %s, \"%s\", %d, %d", actor->GetName(), "World", "Pickup", GetName(), 0, 0);
- psserver->GetLogCSV()->Write(CSV_EXCHANGES, buf);
-
- }
- */
+ psSystemMessage newmsg(client, MSG_INFO, "%s picked up %s", actor->GetName(), qname.GetData() );
+ newmsg.Multicast(actor->GetMulticastClients(),0,RANGE_TO_SELECT);
- // Assume inventory is full so tell player about that to.
- psserver->SendSystemInfo(clientnum, "You can't carry anymore %s",GetName());
+ psserver->GetCharManager()->UpdateItemViews(clientnum);
+
+ csString buf;
+ buf.Format("%s, %s, %s, \"%s\", %d, %d", actor->GetName(), "World", "Pickup", GetName(), 0, 0);
+ psserver->GetLogCSV()->Write(CSV_EXCHANGES, buf);
+
}
+ */
+
+ // Assume inventory is full so tell player about that to.
+ psserver->SendSystemInfo(clientnum, "You can't carry anymore %s",GetName());
}
- else
- {
- if (!actor->IsAlive())
- psserver->SendSystemInfo(clientnum,"You can't pick up items when you're dead.");
- else if (!IsPickable())
- psserver->SendSystemInfo(clientnum,"You can't pick up this item.");
- else
- psserver->SendSystemInfo(clientnum,"You're too far away to pick up that item.");
- }
}
else if (msg_id == "use")
Index: src/server/usermanager.cpp
===================================================================
--- src/server/usermanager.cpp (Revision 1785)
+++ src/server/usermanager.cpp (Arbeitskopie)
@@ -37,6 +37,7 @@
#include "util/serverconsole.h"
#include "util/pserror.h"
#include "util/psconst.h"
+#include "util/strutil.h"
#include "util/log.h"
#include "util/eventmanager.h"
@@ -374,12 +375,167 @@
{
HandleBanking(client, msg.action);
}
+ else if (msg.command == "/pickup")
+ {
+ HandlePickup(client, msg.target);
+ }
else
{
psserver->SendSystemError(me->clientnum,"Command not supported by server yet.");
}
}
+csArray<csString> UserManager::DecodeCommandArea(Client *client,
+ csString target)
+{
+ csArray<csString> result;
+
+ if (!CacheManager::GetSingleton().GetCommandManager()->Validate(client->GetSecurityLevel(), "command area"))
+ {
+ psserver->SendSystemError(client->GetClientNum(),
+ "You are not allowed to use area", target.GetData());
+ return result;
+ }
+
+ csArray<csString> splitTarget = psSplit(target, ':');
+ size_t splitSize = splitTarget.GetSize();
+
+ if ((2>splitSize) || (splitSize>4))
+ {
+ psserver->SendSystemError(client->GetClientNum(),
+ "Try /$CMD area:item[:range[:name]]");
+ return result;
+ }
+
+ csString itemName = splitTarget[1];
+ csString* rangeName = splitSize > 2 ? &splitTarget[2] : 0;
+ csString* nameFilter = splitSize > 3 ? &splitTarget[3] : 0;
+
+ int range = 99999; /* TODO: check is this value is large enough */
+ if (rangeName)
+ range = atoi(rangeName->GetData());
+
+ bool allNames = true;
+ if (nameFilter && (*nameFilter!="all"))
+ allNames = false;
+
+ gemActor* self = client->GetActor();
+ if (!self)
+ {
+ psserver->SendSystemError(client->GetClientNum(), "You do not exist...");
+ return result;
+ }
+
+ int mode = 0;
+ if (itemName == "players")
+ mode = 0;
+ else if (itemName == "actors")
+ mode = 1;
+ else if (itemName == "items")
+ mode = 2;
+ else if (itemName == "npcs")
+ mode = 3;
+ else if (itemName == "entities")
+ mode = 4;
+ else
+ {
+ psserver->SendSystemError(client->GetClientNum(),
+ "item must be players|actors|items|npcs|entities");
+ return result;
+ }
+
+ csVector3 pos;
+ iSector* sector;
+ self->GetPosition(pos, sector);
+
+ GEMSupervisor* gem = GEMSupervisor::GetSingletonPtr();
+ if (!gem)
+ return result;
+
+ csRef<iCelEntityList> nearlist = gem->pl->FindNearbyEntities(sector, pos,
+ range);
+ size_t count = nearlist->GetCount();
+ size_t handled_entities = 0;
+
+ csArray<csString *> results;
+
+ for (size_t i=0; i<count; i++)
+ {
+ gemObject *nearobj = gem->GetObjectFromEntityList(nearlist, i);
+ if (!nearobj)
+ continue;
+
+ if (!allNames)
+ {
+ csString nearobjName = nearobj->GetName();
+ if (!nearobjName.StartsWith(*nameFilter->GetData(), true))
+ continue;
+ }
+
+ csString newTarget;
+
+ switch (mode)
+ {
+ case 0: // Target players
+ {
+ if (nearobj->GetClientID())
+ {
+ newTarget.Format("pid:%d", nearobj->GetPlayerID());
+ break;
+ }
+ else
+ continue;
+ }
+ case 1: // Target actors
+ {
+ if (nearobj->GetPlayerID())
+ {
+ newTarget.Format("pid:%d", nearobj->GetPlayerID());
+ break;
+ }
+ else
+ continue;
+ }
+ case 2: // Target items
+ {
+ if (nearobj->GetItem())
+ {
+ newTarget.Format("eid:%u", nearobj->GetEntityID());
+ break;
+ }
+ else
+ continue;
+ }
+ case 3: // Target NPCs
+ {
+ if (nearobj->GetNPCPtr())
+ {
+ newTarget.Format("pid:%d", nearobj->GetPlayerID());
+ break;
+ }
+ else
+ continue;
+ }
+ case 4: // Target everything
+ {
+ newTarget.Format("eid:%u", nearobj->GetEntityID());
+ break;
+ }
+ }
+
+ // Run this once for every target in range (each one will be verified and logged seperately)
+ result.Push(newTarget);
+ handled_entities++;
+ }
+
+ if (!handled_entities)
+ {
+ psserver->SendSystemError(client->GetClientNum(),
+ "Nothing of specified type in range.");
+ }
+ return result;
+}
+
bool UserManager::CheckForEmote(csString command, bool execute, MsgEntry *me, Client *client)
{
for(unsigned int i=0; i < emoteList.GetSize(); i++)
@@ -875,7 +1031,6 @@
void UserManager::Who(psUserCmdMessage& msg, Client* client, int clientnum)
{
csString message((size_t) 1024);
- csString temp((size_t) 1024);
csString headerMsg("Players Currently Online");
if (!msg.filter.IsEmpty())
@@ -899,65 +1054,98 @@
unsigned count = 0;
- // Guild rank, guild and title should come from acraig's player prop class.
- ClientIterator i(*clients);
- while(i.HasNext())
+ if (msg.filter.StartsWith("area:"))
{
- Client *curr = i.Next();
- csString playerName(curr->GetName());
- csString guildTitle;
- csString guildName;
- csString format("%s"); // Player name.
-
- if (curr->IsSuperClient() || !curr->GetActor())
- continue;
-
- psGuildInfo* guild = curr->GetActor()->GetGuild();
- if (guild != NULL)
+ csArray<csString> filters = DecodeCommandArea(client, msg.filter);
+ csArray<csString>::Iterator it(filters.GetIterator());
+ while (it.HasNext())
{
- if (guild->id && (!guild->IsSecret()
- || guild->id == client->GetGuildID()))
+ csString pid = it.Next();
+ gemObject *object = psserver->GetAdminManager()->FindObjectByString(pid,client->GetActor());
+ Client* thisclient = object->GetClient();
+ if (thisclient)
{
- psGuildLevel* level = curr->GetActor()->GetGuildLevel();
- if (level)
- {
- format.Append(", %s in %s"); // Guild level title.
- guildTitle = level->title;
- }
- else
- {
- format.Append(", %s");
- }
- guildName = guild->name;
+ if (!WhoProcessClient(thisclient, client->GetGuildID(), &message, msg.filter,
+ false, &count))
+ break;
}
}
- temp.Format(format.GetData(), curr->GetName(), guildTitle.GetData(),
- guildName.GetData());
-
- csString lower(temp);
- StrToLowerCase(lower);
- if (!msg.filter.IsEmpty() && lower.FindStr(msg.filter) == (size_t)-1)
- continue;
-
- if (temp.Length() + message.Length() > MAXPACKETSIZE)
- break;
- else
- message.Append('\n');
- message.Append(temp);
-
- count++;
}
+ else
+ {
+ // Guild rank, guild and title should come from acraig's player prop class.
+ ClientIterator i(*clients);
+ while (i.HasNext())
+ {
+ Client *curr = i.Next();
+ if (!WhoProcessClient(curr, client->GetGuildID(), &message, msg.filter, true,
+ &count))
+ break;
+ }
+ }
// Could be about to overflow by now, so check.
+ csString temp;
temp.Format("%u shown from %zu players online\n", count, clients->Count());
message.Append('\n');
message.Append(temp);
- psSystemMessageSafe newmsg(clientnum ,MSG_WHO, message);
+ psSystemMessageSafe newmsg(clientnum, MSG_WHO, message);
newmsg.SendMessage();
}
+bool UserManager::WhoProcessClient(Client *curr, int guildId, csString* message, csString filter, bool check, unsigned * count)
+{
+ if (curr->IsSuperClient() || !curr->GetActor())
+ return true;
+
+ csString temp((size_t) 1024);
+ csString playerName(curr->GetName());
+ csString guildTitle;
+ csString guildName;
+ csString format("%s"); // Player name.
+
+ psGuildInfo* guild = curr->GetActor()->GetGuild();
+ if (guild != NULL)
+ {
+ if (guild->id && (!guild->IsSecret() || guild->id
+ == guildId))
+ {
+ psGuildLevel* level = curr->GetActor()->GetGuildLevel();
+ if (level)
+ {
+ format.Append(", %s in %s"); // Guild level title.
+ guildTitle = level->title;
+ }
+ else
+ {
+ format.Append(", %s");
+ }
+ guildName = guild->name;
+ }
+ }
+ temp.Format(format.GetData(), curr->GetName(), guildTitle.GetData(),
+ guildName.GetData());
+
+ if (check)
+ {
+ csString lower(temp);
+ StrToLowerCase(lower);
+ if (!filter.IsEmpty() && lower.FindStr(filter) == (size_t) -1)
+ return true;
+ }
+
+ if (temp.Length() + message->Length() > MAXPACKETSIZE)
+ return false;
+ else
+ message->Append('\n');
+ message->Append(temp);
+
+ (*count)++;
+ return true;
+}
+
void UserManager::StrToLowerCase(csString& str)
{
for (register size_t i = 0; i < str.Length(); ++i)
@@ -1155,6 +1343,17 @@
void UserManager::ReportPosition(psUserCmdMessage& msg,Client *client,int clientnum)
{
+
+ if (msg.player.StartsWith("area:"))
+ {
+ csArray<csString> filters = DecodeCommandArea(client, msg.player);
+ csArray<csString>::Iterator it(filters.GetIterator());
+ while (it.HasNext()) {
+ msg.player = it.Next();
+ ReportPosition(msg, client, clientnum);
+ }
+ }
+
gemObject *object = NULL;
bool self = true;
@@ -1762,6 +1961,41 @@
}
}
+void UserManager::HandlePickup(Client *client, csString target)
+{
+ if (target.StartsWith("area:"))
+ {
+ csArray<csString> filters = DecodeCommandArea(client, target);
+ csArray<csString>::Iterator it(filters.GetIterator());
+ while (it.HasNext()) {
+ HandlePickup(client, it.Next());
+ }
+ }
+ else if (target.StartsWith("eid:", true))
+ {
+ gemObject* object= NULL;
+ GEMSupervisor *gem = GEMSupervisor::GetSingletonPtr();
+ csString eid_str = target.Slice(4);
+ PS_ID eID = (PS_ID)atoi(eid_str.GetDataSafe() );
+ if (eID)
+ {
+ object = gem->FindObject(eID);
+ if (object && object->GetItem())
+ {
+ object->SendBehaviorMessage("pickup", client->GetActor() );
+ }
+ else
+ {
+ psserver->SendSystemError(client->GetClientNum(),
+ "Item not found.", target.GetData());
+ }
+ }
+ }
+ else
+ psserver->SendSystemError(client->GetClientNum(),
+ "You can't pickup %s", target.GetData());
+}
+
void UserManager::GiveTip(int id)
{
unsigned int max=CacheManager::GetSingleton().GetTipLength();
Index: src/server/entitymanager.cpp
===================================================================
--- src/server/entitymanager.cpp (Revision 1785)
+++ src/server/entitymanager.cpp (Arbeitskopie)
@@ -1147,17 +1147,6 @@
object->SendTargetStatDR(client);
}
- // Check to see if this client has the admin level to move this particular item
- bool securityOverride = CacheManager::GetSingleton().GetCommandManager()->Validate(client->GetSecurityLevel(),
- "move unpickupables/spawns");
- if ( action == "pickup"
- && dynamic_cast<gemActiveObject*> (object)
- && ((dynamic_cast<gemActiveObject*> (object))->IsPickable()
- || securityOverride))
- {
- client->SetTargetObject(NULL);
- }
-
Debug5(LOG_USER,client->GetClientNum(), "User Action: %s %s %s:%d\n",client->GetName(),
(const char *)action,
(object)?object->GetName():"None",
Index: src/server/database/mysql/command_access.sql
===================================================================
--- src/server/database/mysql/command_access.sql (Revision 1785)
+++ src/server/database/mysql/command_access.sql (Arbeitskopie)
@@ -239,6 +239,11 @@
INSERT INTO command_group_assignment VALUES( "quest list others", 24 );
INSERT INTO command_group_assignment VALUES( "quest list others", 23 );
INSERT INTO command_group_assignment VALUES( "quest list others", 22 );
+INSERT INTO command_group_assignment VALUES( "pickup override", 30 );
+INSERT INTO command_group_assignment VALUES( "pickup override", 25 );
+INSERT INTO command_group_assignment VALUES( "pickup override", 24 );
+INSERT INTO command_group_assignment VALUES( "pickup override", 23 );
+INSERT INTO command_group_assignment VALUES( "pickup override", 22 );
# GM1 and above
Index: src/server/usermanager.h
===================================================================
--- src/server/usermanager.h (Revision 1785)
+++ src/server/usermanager.h (Arbeitskopie)
@@ -131,7 +131,19 @@
* @param clientnum The client id number of the requesting client.
*/
void Who(psUserCmdMessage& msg, Client* client, int clientnum);
+
+ /** Formats output of a player and adds it to a message.
+ *
+ * @param client The client that is to be formated
+ * @param guildId The guildId of the caller
+ * @param message The target csString object
+ * @param filter What clients
+ * @param check If a check against filter should be done
+ * @param count COunter to be increased in case of a successfull match
+ */
+ bool WhoProcessClient(Client *curr, int guildId, csString* message, csString filter, bool check, unsigned * count);
+
/** Converts a string to lowercase.
*
* @param str The string.
@@ -269,6 +281,12 @@
* @param client The client that issued the command.
*/
void HandleBanking(Client *client, csString accountType);
+
+ /** Handles a player command to pickup an item.
+ * @param client The client that issued the command.
+ * @target description of the item to be picked up.
+ */
+ void HandlePickup(Client *client, csString target);
/** Handles a player request to 'use' the targeted item.
*
@@ -301,6 +319,13 @@
void HandleTargetEvent(MsgEntry *me);
void HandleEntranceMessage( MsgEntry* me, Client *client );
+ /** Decodes an area: expression
+ *
+ * @param client The client of the caller
+ * @param target The area: expression
+ * */
+ csArray<csString> DecodeCommandArea(Client *client, csString target);
+
void SwitchAttackTarget(Client *targeter, Client *targeted);
/** Process an emote command.
Index: src/common/net/messages.cpp
===================================================================
--- src/common/net/messages.cpp (Revision 1785)
+++ src/common/net/messages.cpp (Arbeitskopie)
@@ -1328,6 +1328,11 @@
action = words.Get(1);
return;
}
+ if ( command == "/pickup" )
+ {
+ target = words.Get(1);
+ return;
+ }
valid = false;
}
Index: src/common/net/messages.h
===================================================================
--- src/common/net/messages.h (Revision 1785)
+++ src/common/net/messages.h (Arbeitskopie)
@@ -1092,7 +1092,7 @@
class psUserCmdMessage : public psMessageCracker
{
public:
- csString command,player,filter,action,text;
+ csString command,player,filter,action,text,target;
int dice,sides;
int level;
csString stance;
Index: src/client/cmdusers.cpp
===================================================================
--- src/client/cmdusers.cpp (Revision 1785)
+++ src/client/cmdusers.cpp (Arbeitskopie)
@@ -657,7 +657,19 @@
else
object = FindEntityWithName(words[1]);
if (object)
- psengine->GetCharManager()->SetTarget(object,"pickup");
+ {
+ psengine->GetCharManager()->SetTarget(object,"select");
+ PS_ID mappedID = object->GetID();
+ csString newCmd;
+ newCmd.Format("/pickup eid:%d", mappedID);
+ psUserCmdMessage cmdmsg(newCmd);
+ msgqueue->SendMessage(cmdmsg.msg);
+ }
+ else
+ {
+ psUserCmdMessage cmdmsg(cmd);
+ msgqueue->SendMessage(cmdmsg.msg);
+ }
}
else if ( words[0] == "/game" )