• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 21780228483

07 Feb 2026 12:38PM UTC coverage: 50.817% (+0.06%) from 50.754%
21780228483

push

github

Flow86
Also use references for non-NULL arguments in `GamePlayer`

44 of 59 new or added lines in 11 files covered. (74.58%)

520 existing lines in 14 files now uncovered.

22787 of 44841 relevant lines covered (50.82%)

42084.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.24
/libs/s25main/figures/nofBuildingWorker.cpp
1
// Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "nofBuildingWorker.h"
6
#include "EventManager.h"
7
#include "GamePlayer.h"
8
#include "Loader.h"
9
#include "RTTR_Assert.h"
10
#include "SerializedGameData.h"
11
#include "SoundManager.h"
12
#include "Ware.h"
13
#include "buildings/nobBaseWarehouse.h"
14
#include "buildings/nobUsual.h"
15
#include "helpers/MaxEnumValue.h"
16
#include "world/GameWorld.h"
17
#include "nodeObjs/noFlag.h"
18
#include "gameData/JobConsts.h"
19
#include "gameData/ShieldConsts.h"
20

21
nofBuildingWorker::nofBuildingWorker(const Job job, const MapPoint pos, const unsigned char player, nobUsual* workplace)
12✔
22
    : noFigure(job, pos, player, workplace), state(State::FigureWork), workplace(workplace), was_sounding(false)
12✔
23
{
24
    RTTR_Assert(dynamic_cast<nobUsual*>(static_cast<GameObject*>(
12✔
25
      workplace))); // Assume we have at least a GameObject and check if it is a valid workplace
26
}
12✔
27

28
void nofBuildingWorker::Serialize(SerializedGameData& sgd) const
6✔
29
{
30
    noFigure::Serialize(sgd);
6✔
31

32
    sgd.PushEnum<uint8_t>(state);
6✔
33

34
    if(fs != FigureState::GoHome && fs != FigureState::Wander)
6✔
35
    {
36
        sgd.PushObject(workplace);
6✔
37
        sgd.PushOptionalEnum<uint8_t>(ware);
6✔
38
        sgd.PushBool(was_sounding);
6✔
39
    }
40
}
6✔
41

42
nofBuildingWorker::nofBuildingWorker(SerializedGameData& sgd, const unsigned obj_id)
3✔
43
    : noFigure(sgd, obj_id), state(sgd.Pop<State>())
3✔
44
{
45
    if(fs != FigureState::GoHome && fs != FigureState::Wander)
3✔
46
    {
47
        workplace = sgd.PopObject<nobUsual>();
3✔
48
        if(sgd.GetGameDataVersion() < 5)
3✔
49
        {
UNCOV
50
            const auto iWare = sgd.PopUnsignedChar();
×
UNCOV
51
            if(iWare == rttr::enum_cast(GoodType::Nothing))
×
UNCOV
52
                ware = boost::none;
×
53
            else
UNCOV
54
                ware = GoodType(iWare);
×
55
        } else
56
            ware = sgd.PopOptionalEnum<GoodType>();
3✔
57
        was_sounding = sgd.PopBool();
3✔
58
    } else
59
    {
UNCOV
60
        workplace = nullptr;
×
UNCOV
61
        ware = boost::none;
×
UNCOV
62
        was_sounding = false;
×
63
    }
64
}
3✔
65

66
void nofBuildingWorker::AbrogateWorkplace()
×
67
{
UNCOV
68
    if(workplace)
×
69
    {
UNCOV
70
        workplace->WorkerLost();
×
71
        workplace = nullptr;
×
72
    }
73
}
×
74

75
void nofBuildingWorker::Draw(DrawPoint drawPt)
×
76
{
UNCOV
77
    switch(state)
×
78
    {
UNCOV
79
        case State::FigureWork:
×
80
        case State::HunterChasing:
81
        case State::HunterWalkingToCadaver:
82
        case State::HunterFindingShootingpoint: DrawWalking(drawPt); break;
×
UNCOV
83
        case State::Work:
×
84
        case State::HunterShooting:
85
        case State::HunterEviscerating:
86
        case State::HunterWaitingForAnimalReady:
87
        case State::CatapultTargetBuilding:
88
        case State::CatapultBackoff: DrawWorking(drawPt); break;
×
UNCOV
89
        case State::CarryoutWare: DrawWalkingWithWare(drawPt); break;
×
UNCOV
90
        case State::WalkingHome:
×
91
        case State::EnterBuilding:
UNCOV
92
            if(ware)
×
93
                DrawWalkingWithWare(drawPt);
×
94
            else
95
                DrawWalking(drawPt);
×
UNCOV
96
            break;
×
97
        default: DrawOtherStates(drawPt); break;
×
98
    }
UNCOV
99
}
×
100

101
void nofBuildingWorker::Walked()
144✔
102
{
103
    switch(state)
144✔
104
    {
105
        case State::EnterBuilding:
15✔
106
        {
107
            // Hab ich noch ne Ware in der Hand?
108

109
            if(ware)
15✔
110
            {
111
                // dann war draußen kein Platz --> ist jetzt evtl Platz?
UNCOV
112
                state = State::WaitForWareSpace;
×
UNCOV
113
                if(workplace->GetFlag()->HasSpaceForWare())
×
UNCOV
114
                    FreePlaceAtFlag();
×
115
                // Ab jetzt warten, d.h. nicht mehr arbeiten --> schlecht für die Produktivität
UNCOV
116
                workplace->StartNotWorking();
×
117
            } else
118
            {
119
                // Anfangen zu Arbeiten
120
                TryToWork();
15✔
121
            }
122
        }
123
        break;
15✔
124
        case State::CarryoutWare:
3✔
125
        {
126
            // Alles weitere übernimmt nofBuildingWorker
127
            WorkingReady();
3✔
128
        }
129
        break;
3✔
130
        default: WalkedDerived();
126✔
131
    }
132
}
144✔
133

134
void nofBuildingWorker::WorkingReady()
17✔
135
{
136
    // wir arbeiten nicht mehr
137
    workplace->is_working = false;
17✔
138

139
    // Trage ich eine Ware?
140
    if(ware)
17✔
141
    {
142
        noFlag* flag = workplace->GetFlag();
4✔
143
        // Ist noch Platz an der Fahne?
144
        if(flag->HasSpaceForWare())
4✔
145
        {
146
            // Ware erzeugen
147
            auto real_ware = std::make_unique<Ware>(*ware, nullptr, flag);
4✔
148
            real_ware->WaitAtFlag(flag);
4✔
149
            // Inventur entsprechend erhöhen, dabei Schilder unterscheiden!
150
            GoodType ware_type = ConvertShields(real_ware->type);
4✔
151
            world->GetPlayer(player).IncreaseInventoryWare(ware_type, 1);
4✔
152
            // Abnehmer für Ware finden
153
            real_ware->SetGoal(world->GetPlayer(player).FindClientForWare(*real_ware));
4✔
154
            // Ware soll ihren weiteren Weg berechnen
155
            real_ware->RecalcRoute();
4✔
156
            // Ware ablegen
157
            flag->AddWare(std::move(real_ware));
4✔
158
            // Warenstatistik erhöhen
159
            world->GetPlayer(this->player).IncreaseMerchandiseStatistic(ware_type);
4✔
160
            // Tragen nun keine Ware mehr
161
            ware = boost::none;
4✔
162
        }
163
    }
164

165
    // Wieder reingehen
166
    StartWalking(Direction::NorthWest);
17✔
167
    state = State::EnterBuilding;
17✔
168
}
17✔
169

170
void nofBuildingWorker::TryToWork()
48✔
171
{
172
    if(!workplace->IsProductionDisabled() && AreWaresAvailable())
48✔
173
    {
174
        state = State::Waiting1;
21✔
175
        current_ev = GetEvMgr().AddEvent(
42✔
176
          this, (GetGOT() == GO_Type::NofCatapultman) ? CATAPULT_WAIT1_LENGTH : JOB_CONSTS[job_].wait1_length, 1);
21✔
177
        workplace->StopNotWorking();
21✔
178
    } else
179
    {
180
        state = State::WaitingForWaresOrProductionStopped;
27✔
181
        // Nun arbeite ich nich mehr
182
        workplace->StartNotWorking();
27✔
183
    }
184
}
48✔
185

186
bool nofBuildingWorker::AreWaresAvailable() const
47✔
187
{
188
    return workplace->WaresAvailable();
47✔
189
}
190

191
void nofBuildingWorker::GotWareOrProductionAllowed()
49✔
192
{
193
    // Falls man auf Waren wartet, kann man dann anfangen zu arbeiten
194
    if(state == State::WaitingForWaresOrProductionStopped)
49✔
195
    {
196
        // anfangen zu arbeiten
197
        TryToWork();
23✔
198
    }
199
}
49✔
200

201
void nofBuildingWorker::GoalReached()
7✔
202
{
203
    // Tür zumachen (ist immer bis zu Erstbesetzung offen)
204
    workplace->CloseDoor();
7✔
205
    // Gebäude Bescheid sagen, dass ich da bin
206
    workplace->WorkerArrived();
7✔
207

208
    WorkplaceReached();
7✔
209

210
    // ggf. anfangen zu arbeiten
211
    TryToWork();
7✔
212
}
7✔
213

214
bool nofBuildingWorker::FreePlaceAtFlag()
2✔
215
{
216
    // Hinaus gehen, um Ware abzulegen, falls wir auf einen freien Platz warten
217
    if(state == State::WaitForWareSpace)
2✔
218
    {
UNCOV
219
        StartWalking(Direction::SouthEast);
×
UNCOV
220
        state = State::CarryoutWare;
×
UNCOV
221
        return true;
×
222
    } else
223
        return false;
2✔
224
}
225
void nofBuildingWorker::LostWork()
1✔
226
{
227
    switch(state)
1✔
228
    {
UNCOV
229
        default: break;
×
230
        case State::FigureWork:
1✔
231
        {
232
            // Auf Wegen nach Hause gehen
233
            GoHome();
1✔
234
        }
235
        break;
1✔
UNCOV
236
        case State::Waiting1:
×
237
        case State::Waiting2:
238
        case State::Work:
239
        case State::WaitingForWaresOrProductionStopped:
240
        case State::WaitForWareSpace:
241
        case State::HunterShooting:
242
        case State::HunterEviscerating:
243
        case State::HunterWaitingForAnimalReady:
244
        case State::CatapultTargetBuilding:
245
        case State::CatapultBackoff:
246
        {
247
            // Bisheriges Event abmelden, da die Arbeit unterbrochen wird
UNCOV
248
            GetEvMgr().RemoveEvent(current_ev);
×
249

250
            // Bescheid sagen, dass Arbeit abgebrochen wurde
UNCOV
251
            WorkAborted();
×
252

253
            // Rumirren
UNCOV
254
            StartWandering();
×
UNCOV
255
            Wander();
×
256

257
            // Evtl. Sounds löschen
UNCOV
258
            world->GetSoundMgr().stopSounds(*this);
×
259

260
            state = State::FigureWork;
×
261
        }
UNCOV
262
        break;
×
263
        case State::EnterBuilding:
×
264
        case State::CarryoutWare:
265
        case State::WalkToWorkpoint:
266
        case State::WalkingHome:
267
        case State::HunterChasing:
268
        case State::HunterFindingShootingpoint:
269
        case State::HunterWalkingToCadaver:
270
        {
271
            // Bescheid sagen, dass Arbeit abgebrochen wurde
UNCOV
272
            WorkAborted();
×
273

274
            // Rumirren
275
            // Bei diesen States läuft man schon, darf also nicht noch zusätzlich Wander aufrufen, da man dann ja im
276
            // Laufen nochmal losläuft!
277
            StartWandering();
×
278

279
            // Evtl. Sounds löschen
UNCOV
280
            world->GetSoundMgr().stopSounds(*this);
×
281

282
            state = State::FigureWork;
×
283
        }
UNCOV
284
        break;
×
285
    }
286

287
    workplace = nullptr;
1✔
288
}
1✔
289

290
void nofBuildingWorker::ProductionStopped()
3✔
291
{
292
    // Wenn ich gerade warte und schon ein Arbeitsevent angemeldet habe, muss das wieder abgemeldet werden
293
    if(state == State::Waiting1)
3✔
294
    {
UNCOV
295
        GetEvMgr().RemoveEvent(current_ev);
×
UNCOV
296
        current_ev = nullptr;
×
UNCOV
297
        state = State::WaitingForWaresOrProductionStopped;
×
UNCOV
298
        workplace->StartNotWorking();
×
299
    }
300
}
3✔
301

302
void nofBuildingWorker::WorkAborted() {}
×
303

304
void nofBuildingWorker::WorkplaceReached() {}
7✔
305

306
/// Zeichnen der Figur in sonstigen Arbeitslagen
307
void nofBuildingWorker::DrawOtherStates(DrawPoint) {}
×
308

309
/// Zeichnet Figur beim Hereinlaufen/nach Hause laufen mit evtl. getragenen Waren
UNCOV
310
void nofBuildingWorker::DrawWalkingWithWare(DrawPoint drawPt)
×
311
{
312
    unsigned short id = GetCarryID();
×
313
    // >=CARRY_ID_CARRIER_OFFSET -> carrier.bob else jobs.bob!
UNCOV
314
    if(id >= CARRY_ID_CARRIER_OFFSET)
×
315
    {
UNCOV
316
        id -= CARRY_ID_CARRIER_OFFSET;
×
317
        RTTR_Assert(id <= helpers::MaxEnumValue_v<GoodType>);
×
UNCOV
318
        DrawWalkingCarrier(drawPt, GoodType(id), JOB_SPRITE_CONSTS[job_].isFat());
×
319
    } else
UNCOV
320
        DrawWalking(drawPt, LOADER.GetBob("jobs"), id, JOB_SPRITE_CONSTS[job_].isFat());
×
321
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc