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(); }
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); } } } }
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(); }