void HandleAnswer(const csString & answer)
    {
        PendingQuestion::HandleAnswer(answer);

        if ( dynamic_cast<psItem*>(item) == NULL )
        {
            Error2("Item held in PendingLootPrompt with id %u has been lost",id);
            return;
        }

        gemActor* looter = gemSupervisor->FindPlayerEntity(looterID);
        gemActor* roller = gemSupervisor->FindPlayerEntity(rollerID);

        gemActor* getter = (answer == "yes") ? looter : roller ;

        // If the getter left the world, default to the other player
        if (!getter /*|| !getter->InGroup()*/ )
        {
            getter = (answer == "yes") ? roller : looter ;

            // If the other player also vanished, get rid of the item and be done with it...
            if (!getter /*|| !getter->InGroup()*/ )
            {
                cacheManager->RemoveInstance(item);
                return;
            }
        }

        // Create the loot message
        csString lootmsg;
        lootmsg.Format("%s was %s a %s by roll winner %s",
                       lootername.GetData(),
                       (getter == looter) ? "allowed to loot" : "stopped from looting",
                       item->GetName(),
                       rollername.GetData() );

        // Attempt to give to getter
        bool dropped = getter->GetCharacterData()->Inventory().AddOrDrop(item);

        if (!dropped)
            lootmsg.Append(", but can't hold anymore");

        // Send out the loot message
        psSystemMessage loot(getter->GetClientID(), MSG_LOOT, lootmsg.GetData() );
        getter->SendGroupMessage(loot.msg);

        psLootEvent evt(
                       looteeID,
                       looteename,
                       getter->GetCharacterData()->GetPID(),
                       lootername,
                       item->GetUID(),
                       item->GetName(),
                       item->GetStackCount(),
                       (int)item->GetCurrentStats()->GetQuality(),
                       0
                       );
        evt.FireEvent();
    }
Exemple #2
0
void LootModule::update()
{
	if (!_player->isAtLogin())
	{
		if (!_player->isBusy())
		{
			std::lock_guard<std::mutex> dropLock(_dropsMutex);
			if (!_drops.empty())
			{
				_isLooting = true;
				_player->setBusy(true);
				_target = _drops.begin()->first;
				loot(_target);
			}
		}
	}
}
Exemple #3
0
Garbage& Pit::spawn_garbage(RowCol rc, int width, int height)
{
	// make sure the Garbage fits in the Pit
	enforce(rc.c >= 0);
	enforce(rc.c + width <= PIT_COLS);

	Loot loot(width * height);
	for(Block::Color& c : loot)
		c = m_color_supplier->next_emerge();

	auto garbage = std::make_unique<Garbage>(rc, width, height, move(loot));
	Garbage* raw_garbage = garbage.get();
	fill_area(*raw_garbage);

	m_contents.push_back(std::move(garbage));

	if(rc.r < m_peak)
		m_peak = rc.r;

	return *raw_garbage;
}
void SpawnManager::HandleLootItem(MsgEntry *me,Client *client)
{
    psLootItemMessage msg(me);

    // Possible hack here?  We are trusting the client to send the right msg.entity?
    gemObject *object = gem->FindObject(msg.entity);
    if (!object)
    {
        Error3("LootItem Message from %s specified an erroneous entity id: %s.\n", client->GetName(), ShowID(msg.entity));
        return;
    }

    gemActor *obj = object->GetActorPtr();
    if (!obj)
    {
        Error3("LootItem Message from %s specified a non-actor entity id: %s.\n", client->GetName(), ShowID(msg.entity));
        return;
    }
    psCharacter *chr = obj->GetCharacterData();
    if (!chr)
    {
        Error3("LootItem Message from %s specified a non-character entity id: %s.\n", client->GetName(), ShowID(msg.entity));
        return;
    }

    // Check the range to the lootable object.
    if (client->GetActor()->RangeTo(obj) > RANGE_TO_LOOT )
    {
        psserver->SendSystemError(client->GetClientNum(), "Too far away to loot %s.", obj->GetName() );
        return;
    }

    psItem *item = chr->RemoveLootItem(msg.lootitem);
    if (!item)
    {
        // Take this out because it is just the result of duplicate loot commands due to lag
        //Warning3(LOG_COMBAT,"LootItem Message from %s specified bad item id of %d.\n",client->GetName(), msg.lootitem);
        return;
    }

    item->SetLoaded();

    csRef<PlayerGroup> group = client->GetActor()->GetGroup();
    Client *randfriendclient = NULL;
    if (group.IsValid())
    {
        randfriendclient = obj->GetRandomLootClient(RANGE_TO_LOOT*10);
        if (!randfriendclient)
        {
            Error3("GetRandomLootClient failed for loot msg from %s, object %s.\n", client->GetName(), item->GetName() );
            return;
        }
    }

    csString type;
    Client *looterclient;  // Client that gets the item
    if ( msg.lootaction == msg.LOOT_SELF || !group.IsValid() )
    {
        looterclient = client;
        type = "Loot Self";
    }
    else
    {
        looterclient = randfriendclient;
        type = "Loot Roll";
    }

    // Ask group member before take
    if (msg.lootaction == msg.LOOT_SELF && group.IsValid() && client != randfriendclient && obj->HasBeenAttackedBy(randfriendclient->GetActor()))
    {
        psserver->SendSystemInfo(client->GetClientNum(),
                                 "Asking roll winner %s if you may take the %s...",
                                  randfriendclient->GetName(), item->GetName() );
        csString request;
        request.Format("You have won the roll for a %s, but %s wants to take it."
                       "  Will you allow this action?",
                       item->GetName(), client->GetName());

        // Item will be held in the prompt until answered.

        PendingLootPrompt *p = new PendingLootPrompt(client, randfriendclient, item, chr, request, cacheManager, gem);
        psserver->questionmanager->SendQuestion(p);

        type.Append(" Pending");
    }
    // Continue with normal looting if not prompting
    else
    {
        // Create the loot message
        csString lootmsg;
        if (group.IsValid())
            lootmsg.Format("%s won the roll and",looterclient->GetName());
        else
            lootmsg.Format("You");
        lootmsg.AppendFmt(" looted a %s",item->GetName());

        // Attempt to give to looter
        bool dropped = looterclient->GetActor()->GetCharacterData()->Inventory().AddOrDrop(item);

        if (!dropped)
        {
            lootmsg.Append(", but can't hold anymore");
            type.Append(" (dropped)");
        }

        // Send out the loot message
        psSystemMessage loot(me->clientnum, MSG_LOOT, lootmsg.GetData() );
        looterclient->GetActor()->SendGroupMessage(loot.msg);

        item->Save(false);
    }

    // Trigger item removal on every client in the group which has intrest
    if (group.IsValid())
    {
        for (int i=0; i < (int)group->GetMemberCount(); i++)
        {
            int cnum = group->GetMember(i)->GetClientID();
            if (obj->IsLootableClient(cnum))
            {
                psLootRemoveMessage rem(cnum,msg.lootitem);
                rem.SendMessage();
            }
        }
    }
    else
    {
        psLootRemoveMessage rem(client->GetClientNum(),msg.lootitem);
        rem.SendMessage();
    }

    psLootEvent evt(
                   chr->GetPID(),
                   chr->GetCharName(),
                   looterclient->GetCharacterData()->GetPID(),
                   looterclient->GetCharacterData()->GetCharName(),
                   item->GetUID(),
                   item->GetName(),
                   item->GetStackCount(),
                   (int)item->GetCurrentStats()->GetQuality(),
                   0
                   );
    evt.FireEvent();

}