bool nobBaseWarehouse::OrderJob(const Job job, noRoadNode* const goal, const bool allow_recruiting)
{
    RTTR_Assert(goal);
    // Maybe we have to recruit one
    if(!inventory[job])
    {
        if(!allow_recruiting)
            return false;
        TryRecruitJob(job);
    }

    noFigure* fig = JobFactory::CreateJob(job, pos, player, goal);
    // Wenn Figur nicht sofort von abgeleiteter Klasse verwenet wird, fügen wir die zur Leave-Liste hinzu
    if(!UseFigureAtOnce(fig, *goal))
        AddLeavingFigure(fig);

    // Ziel Bescheid sagen, dass dortin ein neuer Arbeiter kommt (bei Flaggen als das anders machen)
    if(goal->GetType() != NOP_FLAG)
    {
        RTTR_Assert(dynamic_cast<noBaseBuilding*>(goal));
        static_cast<noBaseBuilding*>(goal)->GotWorker(job, fig);
    }

    inventory.real.Remove(job);

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

    return true;
}
Пример #2
0
bool nobBaseMilitary::CallDefender(nofAttacker* attacker)
{
    // Ist noch ein Verteidiger draußen (der z.B. grad wieder reingeht?
    if(defender_)
    {
        // Dann nehmen wir den, müssen ihm nur den neuen Angreifer mitteilen
        defender_->NewAttacker(attacker);
        // Leute, die aus diesem Gebäude zum Angriff/aggressiver Verteidigung rauskommen wollen,
        // blocken
        CancelJobs();

        return true;
    }
    // ansonsten einen neuen aus dem Gebäude holen
    else if((defender_ = ProvideDefender(attacker)))
    {
        // Leute, die aus diesem Gebäude zum Angriff/aggressiver Verteidigung rauskommen wollen,
        // blocken
        CancelJobs();
        // Soldat muss noch rauskommen
        AddLeavingFigure(defender_);

        return true;
    }
    else
    {
        // Gebäude ist leer, dann kann es erobert werden
        return false;
    }
}
void nobBaseWarehouse::FetchWare()
{
    if(!fetch_double_protection)
        AddLeavingFigure(new nofWarehouseWorker(pos, player, 0, true));

    fetch_double_protection = false;
}
/// Starts a trade caravane from this warehouse
void nobBaseWarehouse::StartTradeCaravane(const GoodType gt,  Job job, const unsigned count, const TradeRoute& tr, nobBaseWarehouse* goal)
{
    nofTradeLeader* tl = new nofTradeLeader(pos, player, tr, this->GetPos(), goal->GetPos());
    AddLeavingFigure(tl);

    // Create the donkeys or other people
    nofTradeDonkey* last = NULL;
    for(unsigned i = 0; i < count; ++i)
    {
        nofTradeDonkey* next = new nofTradeDonkey(pos, player, gt, job);

        if(last)
            last->SetSuccessor(next);
        else
            tl->SetSuccessor(next);

        last = next;
        AddLeavingFigure(next);
    }

    GameClientPlayer& owner = gwg->GetPlayer(player);
    // Remove leader
    inventory.real.Remove(JOB_HELPER);
    owner.DecreaseInventoryJob(JOB_HELPER, 1);

    // Also diminish the count of donkeys
    if(job == JOB_NOTHING)
    {
        // Diminish the goods in the warehouse
        RTTR_Assert(gt != GD_NOTHING);
        inventory.real.Remove(gt, count);
        owner.DecreaseInventoryWare(gt, count);
        //now that we have removed the goods lets remove the donkeys
        inventory.real.Remove(JOB_PACKDONKEY, count);
        owner.DecreaseInventoryJob(JOB_PACKDONKEY, count);
    }
    else
    {
        RTTR_Assert(gt == GD_NOTHING);
        //remove the jobs & the helpers
        inventory.real.Remove(job, count);
        owner.DecreaseInventoryJob(job, count);
        inventory.real.Remove(JOB_HELPER, count);
        owner.DecreaseInventoryJob(JOB_HELPER, count);
    }
}
nofCarrier* nobBaseWarehouse::OrderDonkey(RoadSegment* road, noRoadNode* const goal_flag)
{
    // Überhaupt ein Esel vorhanden?
    if(!inventory[JOB_PACKDONKEY])
        return NULL;

    nofCarrier* donkey = new nofCarrier(nofCarrier::CT_DONKEY, pos, player, road, goal_flag);
    AddLeavingFigure(donkey);
    inventory.real.Remove(JOB_PACKDONKEY);

    return donkey;
}
Пример #6
0
/// Erhält die Waren von einem Schiff und nimmt diese in den Warenbestand auf
void nobHarborBuilding::ReceiveGoodsFromShip(std::list<noFigure*>& figures, std::list<Ware*>& wares)
{
    // Menschen zur Ausgehliste hinzufügen
    for(std::list<noFigure*>::const_iterator it = figures.begin(); it != figures.end(); ++it)
    {
        (*it)->ArrivedByShip(pos);

        // Wenn es kein Ziel mehr hat, sprich keinen weiteren Weg, kann es direkt hier gelagert werden
        if((*it)->GetGoal() == this)
            (*it)->SetGoalToNULL();
        else if(!(*it)->HasNoGoal())
        {
            unsigned char nextDir;
            MapPoint next_harbor = (*it)->ExamineRouteBeforeShipping(nextDir);

            if (nextDir == 4)
            {
                // Increase visual count
                if((*it)->GetJobType() == JOB_BOATCARRIER)
                {
                    inventory.visual.Add(JOB_HELPER);
                    inventory.visual.Add(GD_BOAT);
                }
                else
                    inventory.visual.Add((*it)->GetJobType());
                AddLeavingFigure(*it);
                (*it)->ShipJourneyEnded();
            }
            else if (nextDir == SHIP_DIR)
            {
                AddFigureForShip(*it, next_harbor);
            }else
            {
                // No or invalid path -> Store here
                RTTR_Assert(nextDir == 0xFF);
                (*it)->SetGoalToNULL();
                AddDependentFigure(*it);
            }
        }else
            AddDependentFigure(*it); // No goal? We take it
        if ((*it)->HasNoGoal())
             AddFigure(*it, true);
    }
    figures.clear();

    // Waren zur Warteliste hinzufügen
    for(std::list<Ware*>::iterator it = wares.begin(); it != wares.end(); ++it)
    {
        (*it)->ShipJorneyEnded(this);
        AddWare(*it);
    }
    wares.clear();
}
void nobBaseWarehouse::OrderTroops(nobMilitary* goal, unsigned count,bool ignoresettingsendweakfirst)
{
    // Soldaten durchgehen und count rausschicken

    // Ränge durchgehen, absteigend, starke zuerst
    if (gwg->GetPlayer(player).militarySettings_[1] >= MILITARY_SETTINGS_SCALE[1] / 2 && !ignoresettingsendweakfirst)
    {
        for(unsigned i = SOLDIER_JOBS.size(); i && count; --i)
        {
            const Job curRank = SOLDIER_JOBS[i-1];
            // Vertreter der Ränge ggf rausschicken
            while(inventory[curRank] && count)
            {
                nofSoldier* soldier = new nofPassiveSoldier(pos, player, goal, goal, i - 1);
                inventory.real.Remove(curRank);
                AddLeavingFigure(soldier);
                goal->GotWorker(curRank, soldier);
                --count;
            }
        }
    }
    // Ränge durchgehen, aufsteigend, schwache zuerst
    else
    {
        for(unsigned i = 1; i <= SOLDIER_JOBS.size() && count; ++i)
        {
            const Job curRank = SOLDIER_JOBS[i - 1];
            // Vertreter der Ränge ggf rausschicken
            while(inventory[curRank] && count)
            {
                nofSoldier* soldier = new nofPassiveSoldier(pos, player, goal, goal, i - 1);
                inventory.real.Remove(curRank);
                AddLeavingFigure(soldier);
                goal->GotWorker(curRank, soldier);
                --count;
            }
        }
    }

}
Пример #8
0
nofAggressiveDefender* nobMilitary::SendDefender(nofAttacker* attacker)
{
    // Sind noch Soldaten da?
    if(troops.size() > 1)
    {
        // Verteidiger auswählen
        nofPassiveSoldier* soldier = ChooseSoldier();
        // neuen aggressiven Verteidiger daraus erzeugen
        nofAggressiveDefender* defender = new nofAggressiveDefender(soldier, attacker);
        // soll rausgehen
        AddLeavingFigure(defender);
        SoldierOnMission(soldier, defender);
        // alten passiven Soldaten vernichten
        soldier->Destroy();
        delete soldier;

        return defender;
    }
    else
        return NULL;
}
Пример #9
0
void nobMilitary::SendSoldiersHome()
{
	int diff = 1 - static_cast<int>(GetTotalSoldiers());
    if(diff < 0) //poc: this should only be >0 if we are being captured. capturing should be true until its the last soldier and this last one would count twice here and result in a returning soldier that shouldnt return.
	{
		// Nur rausschicken, wenn es einen Weg zu einem Lagerhaus gibt!
        if(!gwg->GetPlayer(player).FindWarehouse(*this, FW::NoCondition(), true, false))
            return;
        int mrank=-1;
        for(SortedTroops::reverse_iterator it = troops.rbegin(); diff && troops.size() > 1; ++diff)
        {
            if(mrank<0) //set mrank = highest rank
                mrank=(*it)->GetRank();
            else if (mrank>(*it)->GetRank()) //if the current soldier is of lower rank than what we started with -> send no more troops out
                return;
            (*it)->LeaveBuilding();
            AddLeavingFigure(*it);
            it = helpers::erase(troops, it);
        }
	}
}
nofAggressiveDefender* nobBaseWarehouse::SendDefender(nofAttacker* attacker)
{
    // Sind noch Soldaten da?
    unsigned char rank;
    for(rank = SOLDIER_JOBS.size(); rank > 0; --rank)
    {
        if(inventory[SOLDIER_JOBS[rank - 1]])
            break;
    }

    // Wenn kein Soldat mehr da ist --> 0 zurückgeben
    if(!rank)
        return NULL;

    // Dann den Stärksten rausschicken
    nofAggressiveDefender* soldier = new nofAggressiveDefender(pos, player, this, rank - 1, attacker);
    inventory.real.Remove(SOLDIER_JOBS[rank - 1]);
    AddLeavingFigure(soldier);

    troops_on_mission.push_back(soldier);

    return soldier;
}
void nobBaseWarehouse::OrderCarrier(noRoadNode& goal, RoadSegment& workplace)
{
    RTTR_Assert(workplace.getCarrier(0) == NULL);
    const bool isBoatRequired = workplace.GetRoadType() == RoadSegment::RT_BOAT;

    // We assume, that the caller already checked, if this is possible
    RTTR_Assert(inventory[JOB_HELPER]);
    if(isBoatRequired)
        RTTR_Assert(inventory[GD_BOAT]);

    nofCarrier* carrier = new nofCarrier(isBoatRequired ? nofCarrier::CT_BOAT : nofCarrier::CT_NORMAL, pos, player, &workplace, &goal);
    workplace.setCarrier(0, carrier);

    if(!UseFigureAtOnce(carrier, goal))
        AddLeavingFigure(carrier);

    inventory.real.Remove(JOB_HELPER);
    if(isBoatRequired)
        inventory.real.Remove(GD_BOAT);

    // Evtl. kein Gehilfe mehr, sodass das Rekrutieren gestoppt werden muss
    TryStopRecruiting();
}
Пример #12
0
/// Erhält die Waren von einem Schiff und nimmt diese in den Warenbestand auf
void nobHarborBuilding::ReceiveGoodsFromShip(const std::list<noFigure*> figures, const std::list<Ware*> wares)
{
	// Menschen zur Ausgehliste hinzufügen
	for(std::list<noFigure*>::const_iterator it = figures.begin();it!=figures.end();++it)
	{
		if((*it)->GetJobType() == JOB_BOATCARRIER)
		{
			++goods.people[JOB_HELPER];
			++goods.goods[GD_BOAT];
		}
		else
			++goods.people[(*it)->GetJobType()];

		// Wenn es kein Ziel mehr hat, sprich keinen weiteren Weg, kann es direkt hier gelagert
		// werden
		if ((*it)->HasNoGoal() || ((*it)->GetGoal() == this))
		{
			AddFigure(*it, false);
		} else
		{
			Point<MapCoord> next_harbor = (*it)->ExamineRouteBeforeShipping();
			unsigned char next_dir = (*it)->GetDir();

			if (next_dir == 4)
			{
				AddLeavingFigure(*it);
				(*it)->ShipJourneyEnded();
			} else if (next_dir == SHIP_DIR)
			{
				AddFigureForShip(*it, next_harbor);
			} else
			{
				AddFigure(*it, false);
			}
		}
	}

	// Waren zur Warteliste hinzufügen
	for(std::list<Ware*>::const_iterator it = wares.begin();it!=wares.end();++it)
	{
		// Optische Warenwerte entsprechend erhöhen
		++goods.goods[ConvertShields((*it)->type)];
		if((*it)->ShipJorneyEnded(this))
		{
			
			// Ware will die weitere Reise antreten, also muss sie zur Liste der rausgetragenen Waren
			// hinzugefügt werden
			waiting_wares.push_back(*it);
		}
		else
		{
			// Ansonsten fügen wir die Ware einfach zu unserem Inventar dazu
			RemoveDependentWare(*it);
			++real_goods.goods[ConvertShields((*it)->type)];
			players->getElement(player)->RemoveWare(*it);
			delete *it;
		}
	}

	// Ggf. neues Rausgeh-Event anmelden, was notwendig ist, wenn z.B. nur Waren zur Liste hinzugefügt wurden
	AddLeavingEvent();
}
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);
}
Пример #14
0
void nobMilitary::RegulateTrainTroops()
{
    if(!gwg->GetPlayer(player).FindWarehouse(*this, FW::NoCondition(), true, false))
    {
        is_regulating_troops = false;
        return;
    }
    
    is_regulating_troops = true;

	boost::array< unsigned char, 5 > RankCounts{ { 0, 0, 0, 0, 0 } };

	for( auto& Soldier : troops )
        ++RankCounts[ Soldier->GetRank() ];
    
    for( auto& Soldier : ordered_troops )
        ++RankCounts[ Soldier->GetRank() ];

    for( auto& Soldier : troops_on_mission )
        ++RankCounts[ Soldier->GetRank() ];

    for( auto& Soldier : far_away_capturers )
        ++RankCounts[ Soldier->GetRank() ];

    SortedTroops::reverse_iterator it = troops.rbegin();

    auto GetSoldierRank = 
    []( const Job& Job )
    {
        return unsigned char( Job - JOB_PRIVATE );
    };
    
	for( auto SoldierRankIt = SOLDIER_JOBS.crbegin(); SoldierRankIt != SOLDIER_JOBS.crend(); ++SoldierRankIt  )
    {
        auto CurrentRank = GetSoldierRank( *SoldierRankIt );
        
		if( CurrentRank >= GetSoldierRank( JOB_GENERAL ))
		{
			while( it != troops.rend() && ( *it )->GetRank() == CurrentRank && troops.size() > 1 )
			{
				(*it)->LeaveBuilding();
				AddLeavingFigure(*it);
				it = helpers::erase(troops, it);
			}
		}
		else if( CurrentRank > GetSoldierRank( JOB_PRIVATE ) && CurrentRank < GetSoldierRank( JOB_GENERAL ) )
		{
			if( !RankCounts[CurrentRank] )
			{
				gwg->GetPlayer(player).OrderTroops(this, 
					std::min( TROOPS_COUNT[nation][size] - static_cast<int>(GetTotalSoldiers()), 1 )
					,true, SOLDIER_JOBS[ CurrentRank ]);
			}
			else
			if( RankCounts[CurrentRank] > 1 )
			{
				unsigned SendOut = RankCounts[CurrentRank] - 1;
				while( it != troops.rend() && ( *it )->GetRank() == CurrentRank && troops.size() > 1 )
				{
					if( SendOut > 0 )
					{
						(*it)->LeaveBuilding();
						AddLeavingFigure(*it);
						it = helpers::erase(troops, it);
						--SendOut;
					}
					else
						++it;
				}
			}
		}
		else
		{
			// PRIVATES
			gwg->GetPlayer(player).OrderTroops(this, 
					TROOPS_COUNT[nation][size] - static_cast<int>(GetTotalSoldiers()) 
					,true, SOLDIER_JOBS[ CurrentRank ]);
		}
	
	}

    is_regulating_troops = false;
}
Пример #15
0
void nobMilitary::RegulateTroops()
{
    RTTR_Assert(helpers::contains(gwg->GetPlayer(player).GetMilitaryBuildings(), this)); // If this fails, the building is beeing destroyed!

    // Wenn das Gebäude eingenommen wird, erstmal keine neuen Truppen und warten, wieviele noch reinkommen
    if(IsCaptured())
        return;

    // Already regulate its troops => Don't call this method again
    if(is_regulating_troops)
        return;

    is_regulating_troops = true;

    if( mAutoTrain )
    {
        RegulateTrainTroops();
        is_regulating_troops = false;
        return;
    }

    // Zu viele oder zu wenig Truppen?
    int diff = CalcTroopsCount() - static_cast<int>(GetTotalSoldiers());
    if(diff < 0) //poc: this should only be >0 if we are being captured. capturing should be true until its the last soldier and this last one would count twice here and result in a returning soldier that shouldnt return.
    {
        // Zu viel --> überflüssige Truppen nach Hause schicken
        // Zuerst die bestellten Soldaten wegschicken
        // Weak ones first
        std::vector<nofPassiveSoldier*> notNeededSoldiers;
        GameClientPlayer& owner = gwg->GetPlayer(player);
        if (owner.militarySettings_[1] > MILITARY_SETTINGS_SCALE[1] / 2)
        {
            for(SortedTroops::iterator it = ordered_troops.begin(); diff && !ordered_troops.empty(); ++diff)
            {
                notNeededSoldiers.push_back(*it);
                it = helpers::erase(ordered_troops, it);
            }
        }
        // Strong ones first
        else
        {
            for(SortedTroops::reverse_iterator it = ordered_troops.rbegin(); diff && !ordered_troops.empty(); ++diff)
            {
                notNeededSoldiers.push_back(*it);
                it = helpers::erase(ordered_troops, it);
            }
        }

        // send the not-needed-soldiers away
        for (std::vector<nofPassiveSoldier*>::iterator it = notNeededSoldiers.begin(); it != notNeededSoldiers.end(); ++it)
        {
            (*it)->NotNeeded();
        }

        // Nur rausschicken, wenn es einen Weg zu einem Lagerhaus gibt!
        if(owner.FindWarehouse(*this, FW::NoCondition(), true, false))
        {
            // Dann den Rest (einer muss immer noch drinbleiben!)
            // erst die schwachen Soldaten raus
            if (owner.militarySettings_[1] > MILITARY_SETTINGS_SCALE[1] / 2)
            {
                for(SortedTroops::iterator it = troops.begin(); diff && troops.size() > 1; ++diff)
                {
                    (*it)->LeaveBuilding();
                    AddLeavingFigure(*it);
                    it = helpers::erase(troops, it);
                }
            }
            // erst die starken Soldaten raus
            else
            {
                for(SortedTroops::reverse_iterator it = troops.rbegin(); diff && troops.size() > 1; ++diff)
                {
                    (*it)->LeaveBuilding();
                    AddLeavingFigure(*it);
                    it = helpers::erase(troops, it);
                }
            }
        }

    }
    else if(diff > 0)
    {
        // Zu wenig Truppen

        // Gebäude wird angegriffen und
        // Addon aktiv, nur soviele Leute zum Nachbesetzen schicken wie Verteidiger eingestellt
        if (IsUnderAttack() && gwg->GetGGS().getSelection(AddonId::DEFENDER_BEHAVIOR) == 2)
        {
            diff = (gwg->GetPlayer(player).militarySettings_[2] * diff) / MILITARY_SETTINGS_SCALE[2];
        }
		//only order new troops if there is a chance that there is a path - pathfinding from each warehouse with soldiers to this mil building will start at the warehouse and cost time
        bool mightHaveRoad=false;
		for(unsigned i=2; i<7; i++) //every direction but 1 because 1 is the building connection so it doesnt count for this check
		{
			if(GetFlag()->routes[i%6])
			{
			    mightHaveRoad=true;
				break;
			}
		}
		if(mightHaveRoad)
			gwg->GetPlayer(player).OrderTroops(this, diff);
    }

    is_regulating_troops = false;
}