void nobBaseWarehouse::HandleCollectEvent()
{
    // Storing wares done?
    bool storing_done = false;
    // Is storing still wanted?
    bool storing_wanted = false;

    // Untersuchen, welche Waren und Figuren eingelagert werden sollen
    for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i)
    {
        // Soll Ware eingeliefert werden?
        if(!GetInventorySetting(GoodType(i)).IsSet(EInventorySetting::COLLECT))
            continue;

        storing_wanted = true;

        // Lagerhaus suchen, das diese Ware enthält
        nobBaseWarehouse* wh = gwg->GetPlayer(player).FindWarehouse(*this, FW::HasWareButNoCollect(GoodType(i)), false, false);
        // Gefunden?
        if(wh)
        {
            // Dann bestellen
            Ware* ware = wh->OrderWare(GoodType(i), this);
            if(ware)
            {
                RTTR_Assert(IsWareDependent(ware));
                storing_done = true;
                break;
            }
        }
    }

    // Menschen "bestellen" wenn noch keine Ware bestellt wurde
    if(!storing_done)
    {
        for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i)
        {
            // Soll dieser Typ von Mensch bestellt werden?
            if(!GetInventorySetting(Job(i)).IsSet(EInventorySetting::COLLECT))
                continue;

            storing_wanted = true;

            // Lagerhaus suchen, das diesen Job enthält
            nobBaseWarehouse* wh = gwg->GetPlayer(player).FindWarehouse(*this, FW::HasFigureButNoCollect(Job(i), false), false, false);
            // Gefunden?
            if(wh)
            {
                // Dann bestellen
                if(wh->OrderJob(Job(i), this, false))
                    break;
            }
        }
    }

    // Storing still wanted?
    // Then continue ordering new stuff
    if(storing_wanted)
        store_event = em->AddEvent(this, STORE_INTERVAL, 4);
}
void nobBaseWarehouse::Clear()
{
    for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i)
        gwg->GetPlayer(player).DecreaseInventoryWare(GoodType(i), inventory[GoodType(i)]);
    
    for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i)
        gwg->GetPlayer(player).DecreaseInventoryJob(Job(i), inventory[Job(i)]);

    inventory.clear();
    
    for(std::list<Ware*>::iterator it = waiting_wares.begin(); it != waiting_wares.end(); ++it)
    {
        (*it)->WareLost(player);
        (*it)->Destroy();
        delete (*it);
    }

    waiting_wares.clear();

    for (unsigned i = 0; i < 5; ++i)
    {
        // TODO: inventory!?
        reserve_soldiers_available[i] = 0;
        reserve_soldiers_claimed_visual[i] = 0;
        reserve_soldiers_claimed_real[i] = 0;
    }
}
void nobBaseWarehouse::AddToInventory()
{
    for(unsigned int i = 0; i < WARE_TYPES_COUNT; ++i)
        gwg->GetPlayer(player).IncreaseInventoryWare(GoodType(i), inventory[GoodType(i)]);

    for(unsigned int i = 0; i < JOB_TYPES_COUNT; ++i)
        gwg->GetPlayer(player).IncreaseInventoryJob(Job(i), inventory[Job(i)]);
}
Exemplo n.º 4
0
iwTrade::iwTrade(const nobBaseWarehouse& wh, const GameWorldViewer& gwv, GameCommandFactory& gcFactory)
    : IngameWindow(wh.CreateGUIID(), (unsigned short) - 2, (unsigned short) - 2, 400, 194, _("Trade"), LOADER.GetImageN("resource", 41)),
      wh(wh), gwv(gwv), gcFactory(gcFactory), possibleSrcWarehouses(gwv.GetPlayer().GetWarehousesForTrading(wh))
{
    // Get title of the player
    SetTitle(_("Trade with %s") + gwv.GetWorld().GetPlayer(wh.GetPlayer()).name);
    // Gebäudebild und dessen Schatten
    AddImage( 0, 100, 144, LOADER.GetNationImage(wh.GetNation(), 250 + 5 * wh.GetBuildingType()));

    const unsigned left_column = 200;

    this->AddComboBox(4, left_column, 84, 160, 18, TC_GREY, NormalFont, 90); // Ware/Figure names
    this->AddText(1, left_column, 30, "Deal in:", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont);
    ctrlComboBox* box = this->AddComboBox(2, left_column, 44, 160, 18, TC_GREY, NormalFont, 200); // Ware or figure?
    box->AddString(_("Wares"));
    box->AddString(_("Settlers"));
    this->AddText(3, left_column, 70, "Type:", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont);


    // Create possible wares, figures
    for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i)
    {
        // Only add one shield type
        if(GoodType(i) != ConvertShields(GoodType(i)))
            continue;
        // Don't add nothing or empty water
        if(i == GD_NOTHING || i == GD_WATEREMPTY)
            continue;
        wares.push_back(GoodType(i));
    }
    for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i)
    {
        // Can't trade boat carriers
        if(i == JOB_BOATCARRIER)
            continue;
        jobs.push_back(Job(i));
    }

    AddImage(5, left_column + 20, 130, NULL, _("Ware you like to trade"));
    AddEdit(6, left_column + 34, 120, 39 , 20, TC_GREY, NormalFont)->SetNumberOnly(true);
    AddText(7, left_column + 75, 125, "/ 20", COLOR_YELLOW, glArchivItem_Font::DF_LEFT, NormalFont);

    AddTextButton(8, left_column, 150, 150, 22, TC_GREEN2, _("Send"), NormalFont);

    // Choose wares at first
    box->SetSelection(0);
    Msg_ComboSelectItem(2, 0);
}
Exemplo n.º 5
0
iwTrade::iwTrade(const nobBaseWarehouse& wh, const GameWorldViewer& gwv, GameCommandFactory& gcFactory)
    : IngameWindow(wh.CreateGUIID(), IngameWindow::posAtMouse, Extent(400, 194), _("Trade"), LOADER.GetImageN("resource", 41)), wh(wh),
      gwv(gwv), gcFactory(gcFactory), possibleSrcWarehouses(gwv.GetPlayer().GetWarehousesForTrading(wh))
{
    // Get title of the player
    SetTitle((boost::format(_("Trade with %s")) % gwv.GetWorld().GetPlayer(wh.GetPlayer()).name).str());
    // Gebäudebild und dessen Schatten
    AddImage(0, DrawPoint(100, 144), LOADER.GetNationImage(wh.GetNation(), 250 + 5 * wh.GetBuildingType()));

    const unsigned left_column = 200;

    AddComboBox(4, DrawPoint(left_column, 84), Extent(160, 18), TC_GREY, NormalFont, 90); // Ware/Figure names
    AddText(1, DrawPoint(left_column, 30), "Deal in:", COLOR_YELLOW, FontStyle::LEFT, NormalFont);
    ctrlComboBox* box = this->AddComboBox(2, DrawPoint(left_column, 44), Extent(160, 18), TC_GREY, NormalFont, 200); // Ware or figure?
    box->AddString(_("Wares"));
    box->AddString(_("Settlers"));
    AddText(3, DrawPoint(left_column, 70), "Type:", COLOR_YELLOW, FontStyle::LEFT, NormalFont);

    // Create possible wares, figures
    for(unsigned i = 0; i < NUM_WARE_TYPES; ++i)
    {
        // Only add one shield type
        if(GoodType(i) != ConvertShields(GoodType(i)))
            continue;
        // Don't add empty water
        if(i == GD_WATEREMPTY)
            continue;
        wares.push_back(GoodType(i));
    }
    for(unsigned i = 0; i < NUM_JOB_TYPES; ++i)
    {
        // Can't trade boat carriers
        if(i == JOB_BOATCARRIER)
            continue;
        jobs.push_back(Job(i));
    }

    AddImage(5, DrawPoint(left_column + 20, 130), static_cast<ITexture*>(nullptr), _("Ware you like to trade"));
    AddEdit(6, DrawPoint(left_column + 34, 120), Extent(39, 20), TC_GREY, NormalFont)->SetNumberOnly(true);
    AddText(7, DrawPoint(left_column + 75, 125), "/ 20", COLOR_YELLOW, FontStyle::LEFT, NormalFont);

    AddTextButton(8, DrawPoint(left_column, 150), Extent(150, 22), TC_GREEN2, _("Send"), NormalFont);

    // Choose wares at first
    box->SetSelection(0);
    Msg_ComboSelectItem(2, 0);
}
Exemplo n.º 6
0
Ware::Ware(SerializedGameData& sgd, const unsigned obj_id) : GameObject(sgd, obj_id),
    next_dir(sgd.PopUnsignedChar()),
    state(State(sgd.PopUnsignedChar())),
    location(sgd.PopObject<noRoadNode>(GOT_UNKNOWN)),
    type(GoodType(sgd.PopUnsignedChar())),
    goal(sgd.PopObject<noBaseBuilding>(GOT_UNKNOWN)),
    next_harbor(sgd.PopMapPoint())
{}
/// Fügt einige Güter hinzu
void nobBaseWarehouse::AddGoods(const Inventory& goods)
{
    for(unsigned int i = 0; i < WARE_TYPES_COUNT; ++i)
    {
        inventory.Add(GoodType(i), goods.goods[i]);

        if(goods.goods[i])
            CheckUsesForNewWare(GoodType(i));
    }

    for(unsigned int i = 0; i < JOB_TYPES_COUNT; ++i)
    {
        inventory.Add(Job(i), goods.people[i]);

        if(goods.people[i])
            CheckJobsForNewFigure(Job(i));
    }
}
Exemplo n.º 8
0
  bool isAnyGoodStored()
  {
    bool anyGoodStored = false;
    for( int i = 0; i < G_MAX; ++i)
    {
      anyGoodStored |= ( goodStore.getCurrentQty( GoodType(i) ) >= 100 );
    }

    return anyGoodStored;
  }
Exemplo n.º 9
0
nofTradeDonkey::nofTradeDonkey(SerializedGameData * sgd, const unsigned obj_id)
: noFigure(sgd,obj_id),
leader(sgd->PopObject<nofTradeLeader>(GOT_NOF_TRADELEADER)),
successor(sgd->PopObject<nofTradeDonkey>(GOT_NOF_TRADEDONKEY)),
gt(GoodType(sgd->PopUnsignedChar())),
next_dirs(sgd->PopUnsignedInt())
{
	for(unsigned i = 0;i<next_dirs.size();++i)
		next_dirs[i] = sgd->PopUnsignedChar();
}
void nobBaseWarehouse::Destroy_nobBaseWarehouse()
{
    if(GetBuildingType() != BLD_HARBORBUILDING)
    {
        // Aus der Warenhausliste entfernen
        gwg->GetPlayer(player).RemoveWarehouse(this);
    }else
    {
        // Harbors should also remove the warehouse
        RTTR_Assert(!helpers::contains(gwg->GetPlayer(player).GetStorehouses(), this));
    }

    // Den Waren und Figuren Bescheid sagen, die zu uns auf den Weg sind, dass wir nun nicht mehr existieren
    for(std::list<noFigure*>::iterator it = dependent_figures.begin(); it != dependent_figures.end(); ++it)
        (*it)->GoHome();
    dependent_figures.clear();
	for(std::list<Ware*>::iterator it = dependent_wares.begin(); it!=dependent_wares.end(); ++it)
        WareNotNeeded(*it);
    dependent_wares.clear();

    // ggf. Events abmelden
    em->RemoveEvent(recruiting_event);
    em->RemoveEvent(producinghelpers_event);
    em->RemoveEvent(empty_event);
    em->RemoveEvent(store_event);

    // Waiting Wares löschen
    for(std::list<Ware*>::iterator it = waiting_wares.begin(); it != waiting_wares.end(); ++it)
    {
        (*it)->WareLost(player);
        delete (*it);
    }
    waiting_wares.clear();

    // restliche Warenbestände von der Inventur wieder abziehen
    for(unsigned int i = 0; i < WARE_TYPES_COUNT; ++i)
        gwg->GetPlayer(player).DecreaseInventoryWare(GoodType(i), inventory[GoodType(i)]);

    // Objekt, das die flüchtenden Leute nach und nach ausspuckt, erzeugen
    new BurnedWarehouse(pos, player, inventory.real.people);

    Destroy_nobBaseMilitary();
}
Exemplo n.º 11
0
Ware::Ware(SerializedGameData * sgd, const unsigned obj_id) : GameObject(sgd,obj_id),
    next_dir(sgd->PopUnsignedChar()),
    state(State(sgd->PopUnsignedChar())),
    location(sgd->PopObject<noRoadNode>(GOT_UNKNOWN)),
    type(GoodType(sgd->PopUnsignedChar())),
    goal(sgd->PopObject<noBaseBuilding>(GOT_UNKNOWN))

{
    next_harbor.x = sgd->PopUnsignedShort();
    next_harbor.y = sgd->PopUnsignedShort();
    //assert(obj_id != 1197877);
}
Exemplo n.º 12
0
int GameWorldBase::LUA_AddWares(lua_State *L)
{
//	GameWorldBase *gw = static_cast<GameWorldBase*>(lua_touserdata(L,lua_upvalueindex(1)));
	int argc = lua_gettop(L) - 1;

	if ((argc < 0) || (argc % 2 == 1))
	{
		lua_pushstring(L, "wrong arguments: player, ware1, count1, ware2, count2, ...");
		lua_error(L);
		return(0);
	}

	// player
	unsigned pnr = luaL_checknumber(L, 1);

	if (pnr >= GAMECLIENT.GetPlayerCount())
	{
		lua_pushstring(L, "player number invalid!");
		lua_error(L);
		return(0);
	}

	GameClientPlayer *player = GAMECLIENT.GetPlayer(pnr);

	nobBaseWarehouse *warehouse = player->GetFirstWH();

	if (warehouse == NULL)
	{
		lua_pushstring(L, "player has no warehouses!");
		lua_error(L);
		return(0);
	}

	Goods goods;

	unsigned cnt = 2;
	for (argc >>= 1; argc > 0; --argc)
	{
		unsigned type = luaL_checknumber(L, cnt++);
		unsigned count = luaL_checknumber(L, cnt++);

		if (type < WARE_TYPES_COUNT)
		{
			goods.goods[type] += count;
			player->IncreaseInventoryWare(GoodType(type), count);
		}
	}

	warehouse->AddGoods(goods);

	return(0);
}
nofBuildingWorker::nofBuildingWorker(SerializedGameData& sgd, const unsigned obj_id)
    : noFigure(sgd, obj_id), state(State(sgd.PopUnsignedChar()))
{
    if(fs != FS_GOHOME && fs != FS_WANDER)
    {
        workplace = sgd.PopObject<nobUsual>(GOT_UNKNOWN);
        ware = GoodType(sgd.PopUnsignedChar());
        was_sounding = sgd.PopBool();
    } else
    {
        workplace = nullptr;
        ware = GD_NOTHING;
        was_sounding = false;
    }
}
nofMetalworker::nofMetalworker(SerializedGameData& sgd, const unsigned obj_id)
    : nofWorkman(sgd, obj_id), nextProducedTool(GoodType(sgd.PopUnsignedChar()))
{
    if(state == STATE_ENTERBUILDING && current_ev == nullptr && ware == GD_NOTHING && nextProducedTool == GD_NOTHING)
    {
        LOG.write("Found invalid metalworker. Assuming corrupted savegame -> Trying to fix this. If you encounter this with a new game, "
                  "report this!");
        RTTR_Assert(false);
        state = STATE_WAITINGFORWARES_OR_PRODUCTIONSTOPPED;
        current_ev = GetEvMgr().AddEvent(this, 1000, 2);
    }
    toolOrderSub = gwg->GetNotifications().subscribe<ToolNote>([this](const ToolNote& note) {
        if((note.type == ToolNote::OrderPlaced || note.type == ToolNote::SettingsChanged) && note.player == this->player)
            CheckForOrders();
    });
}
bool nobBaseWarehouse::AreWaresToEmpty() const
{
    // Prüfen, ob Warentyp ausgelagert werden soll und ob noch Waren davon vorhanden sind
    // Waren überprüfen
    for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i)
    {
        if(GetInventorySetting(GoodType(i)).IsSet(EInventorySetting::SEND) && inventory[GoodType(i)])
            return true;
    }

    // Figuren überprüfen
    for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i)
    {
        if(GetInventorySetting(Job(i)).IsSet(EInventorySetting::SEND) && inventory[Job(i)])
            return true;
    }

    return false;
}
Exemplo n.º 16
0
nofBuildingWorker::nofBuildingWorker(SerializedGameData* sgd, const unsigned obj_id) : noFigure(sgd, obj_id),
    state(State(sgd->PopUnsignedChar()))
{
    if(fs != FS_GOHOME && fs != FS_WANDER)
    {
        workplace = sgd->PopObject<nobUsual>(GOT_UNKNOWN);
        ware = GoodType(sgd->PopUnsignedChar());
        not_working = sgd->PopUnsignedShort();
        since_not_working = sgd->PopUnsignedInt();
        was_sounding = sgd->PopBool();
    }
    else
    {
        workplace = 0;
        ware = GD_NOTHING;
        not_working = 0;
        since_not_working = 0xFFFFFFFF;
        was_sounding = false;
    }
    OutOfRessourcesMsgSent = sgd->PopBool();
}
/// Verändert Ein/Auslagerungseinstellungen (real)
void nobBaseWarehouse::SetInventorySetting(const bool isJob, const unsigned char type, InventorySetting state)
{
    state.MakeValid();
    InventorySetting oldState;
    if(isJob)
    {
        oldState = inventorySettings.figures[type];
        inventorySettings.figures[type] = state;
    }
    else
    {
        oldState = inventorySettings.wares[type];
        inventorySettings.wares[type] = state;
    }

    /// Bei anderen Spielern als dem lokalen, der das in Auftrag gegeben hat, müssen die visuellen ebenfalls
    /// geändert werden oder auch bei Replays
    if(GAMECLIENT.IsReplayModeOn() || GAMECLIENT.GetPlayerID() != player)
        SetInventorySettingVisual(isJob, type, state);

    if(oldState.IsSet(EInventorySetting::STOP) && !state.IsSet(EInventorySetting::STOP))
    {
        // Evtl gabs verlorene Waren, die jetzt in das HQ wieder reinkönnen
        gwg->GetPlayer(player).FindClientForLostWares();
    } // No else here!
    if(!oldState.IsSet(EInventorySetting::SEND) && state.IsSet(EInventorySetting::SEND))
    {
        // Sind Waren vorhanden, die ausgelagert werden müssen und ist noch kein Auslagerungsevent vorhanden --> neues anmelden
        if(!empty_event && (isJob ? inventory[Job(type)] : inventory[GoodType(type)]))
            empty_event = em->AddEvent(this, empty_INTERVAL, 3);
    }else if(!oldState.IsSet(EInventorySetting::COLLECT) && state.IsSet(EInventorySetting::COLLECT))
    {
        // Sollen Waren eingelagert werden? Dann müssen wir neue bestellen
        if(!store_event)
            store_event = em->AddEvent(this, STORE_INTERVAL, 4);
    }
    NotifyListeners(1);
}
Exemplo n.º 18
0
LONG PushContextNode
(
    struct IFFHandle   *iff,
    LONG	       type,
    LONG	       id,
    LONG	       size,
    LONG	       scan,
    struct IFFParseBase_intern *IFFParseBase
)
{
    /* Allocates and puts a new context-node into the top of the context-stack
     Also does GoodType and GoodID checking  */
    struct ContextNode	 *cn;
    BOOL composite;

    D(bug("PushContextNode(iff=%p, type=%c%c%c%c, id=%c%c%c%c, size=%d, scan=%d)\n",
	iff,
	dmkid(type),
	dmkid(id),
	size,
	scan
    ));

    /* Set the composite flag if we have a composite contextnnode */
    if (id == ID_FORM || id == ID_LIST || id == ID_CAT || id == ID_PROP)
    {
	composite = TRUE;
	/* We have a new type, check it */
    }
    else
    {
	composite = FALSE;
	/* No composite type found.  Get old type from top contextnode */
	cn = TopChunk(iff);
	type = cn->cn_Type;
    }

      /* Check if type and ids are valid */
    if (!(GoodType(type) && GoodID(id)) )
	ReturnInt ("PushContextNode",LONG,IFFERR_MANGLED);

    /* Allocate a new context node */
    if ( !(cn = AllocMem ( sizeof (struct IntContextNode), MEMF_ANY ) ) )
	ReturnInt ("PushContextNode",LONG,IFFERR_NOMEM);

    /* Put the context node at top of the stack */
    AddHead ( (struct List*)&( GetIntIH(iff)->iff_CNStack ), (struct Node*)cn );

    /* Set the contextnode attrs */
    cn->cn_Type  =  type;
    cn->cn_ID	= id;
    cn->cn_Size  = size;
    cn->cn_Scan  =  scan;

    GetIntCN(cn)->cn_Composite = composite;
    /* Initialize the LCI-list */
    NewList ((struct List*)&( GetIntCN(cn)->cn_LCIList ));

    /* Deeper stack */
    iff->iff_Depth ++;

    ReturnInt ("PushContextNode",LONG,0L);
}
Exemplo n.º 19
0
nofMetalworker::nofMetalworker(SerializedGameData* sgd, const unsigned obj_id) : nofWorkman(sgd, obj_id), nextProducedTool(GoodType(sgd->PopUnsignedChar()))
{
    if(state == STATE_ENTERBUILDING && current_ev == NULL && ware == GD_NOTHING && nextProducedTool == GD_NOTHING)
    {
        LOG.lprintf("Found invalid metalworker. Assuming corrupted savegame -> Trying to fix this. If you encounter this with a new game, report this!");
        state = STATE_WAITINGFORWARES_OR_PRODUCTIONSTOPPED;
        current_ev = em->AddEvent(this, 1000, 2);
    }
}
void nobBaseWarehouse::HandleSendoutEvent()
{
    // Fight or something in front of the house? Try again later!
    if(!gwg->IsRoadNodeForFigures(gwg->GetNeighbour(pos, 4), 4))
    {
        empty_event = em->AddEvent(this, empty_INTERVAL, 3);
        return;
    }

    std::vector<unsigned> possibleIds;
    // Waren und Figuren zum Auslagern zusammensuchen
    // Wenn keine Platz an Flagge, dann keine Waren raus
    if(GetFlag()->IsSpaceForWare())
    {
        for(unsigned i = 0; i < WARE_TYPES_COUNT; ++i)
        {
            if(GetInventorySetting(GoodType(i)).IsSet(EInventorySetting::SEND) && inventory[GoodType(i)])
                possibleIds.push_back(i);
        }
    }

    for(unsigned i = 0; i < JOB_TYPES_COUNT; ++i)
    {
        // Figuren, die noch nicht implementiert sind, nicht nehmen!
        if(GetInventorySetting(Job(i)).IsSet(EInventorySetting::SEND) && inventory[Job(i)])
            possibleIds.push_back(WARE_TYPES_COUNT + i);
    }

    // Gibts überhaupt welche?
    if(possibleIds.empty())
        // ansonsten gleich tschüss
        return;

    // Eine ID zufällig auswählen
    unsigned selectedId = possibleIds[RANDOM.Rand(__FILE__, __LINE__, GetObjId(), possibleIds.size())];

    if(selectedId < WARE_TYPES_COUNT)
    {
        // Ware
        Ware* ware = new Ware(GoodType(selectedId), NULL, this);
        noBaseBuilding* wareGoal = gwg->GetPlayer(player).FindClientForWare(ware);
        if(wareGoal != this)
        {
            ware->SetGoal(wareGoal);

            // Ware zur Liste hinzufügen, damit sie dann rausgetragen wird
            waiting_wares.push_back(ware);

            AddLeavingEvent();

            // Ware aus Inventar entfernen
            inventory.real.Remove(GoodType(selectedId));

            // Evtl. kein Schwert/Schild/Bier mehr da, sodass das Rekrutieren gestoppt werden muss
            TryStopRecruiting();
        } else
        {
            gwg->GetPlayer(player).RemoveWare(ware);
            ware->Destroy();
            deletePtr(ware);
        }
    } else
    {
        // Figur
        selectedId -= WARE_TYPES_COUNT;

        nobBaseWarehouse* wh = gwg->GetPlayer(player).FindWarehouse(*this, FW::AcceptsFigureButNoSend(Job(selectedId)), true, false);
        if(wh != this)
        {
            nofPassiveWorker* fig = new nofPassiveWorker(Job(selectedId), pos, player, NULL);

            if(wh)
                fig->GoHome(wh);
            else
                fig->StartWandering();

            AddLeavingFigure(fig);

            // Person aus Inventar entfernen
            inventory.real.Remove(Job(selectedId));

            // Evtl. kein Gehilfe mehr da, sodass das Rekrutieren gestoppt werden muss
            TryStopRecruiting();
        }
    }

    // Weitere Waren/Figuren zum Auslagern?
    if(AreWaresToEmpty())
        // --> Nächstes Event
        empty_event = em->AddEvent(this, empty_INTERVAL, 3);
}
void nobBaseWarehouse::CheckOuthousing(const bool isJob, unsigned job_ware_id)
{
    // Check if we need to send this ware or figure and register an event for this
    // If we already have an event, we don't need to do anything
    if(empty_event)
        return;

    // Bootsträger in Träger umwandeln, der evtl dann raus soll
    if(isJob && job_ware_id == JOB_BOATCARRIER)
        job_ware_id = JOB_HELPER;

    const InventorySetting setting = isJob ? GetInventorySetting(Job(job_ware_id)) : GetInventorySetting(GoodType(job_ware_id));
    if(setting.IsSet(EInventorySetting::SEND))
        empty_event = em->AddEvent(this, empty_INTERVAL, 3);
}