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

Return-To-The-Roots / s25client / 22044569181

15 Feb 2026 10:50PM UTC coverage: 50.34% (-0.5%) from 50.826%
22044569181

Pull #1720

github

web-flow
Merge 4dbe54b70 into 6db06730b
Pull Request #1720: Add leather addon

274 of 1055 new or added lines in 65 files covered. (25.97%)

286 existing lines in 28 files now uncovered.

23017 of 45723 relevant lines covered (50.34%)

43559.46 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
        {
50
            const auto iWare = sgd.PopUnsignedChar();
×
51
            // GoodType::Nothing is moved because of adding new wares due addons
52
            // The old GoodType::Nothing is now GoodType::Grapes
NEW
53
            if(iWare == rttr::enum_cast(GoodType::Grapes))
×
UNCOV
54
                ware = boost::none;
×
55
            else
56
                ware = GoodType(iWare);
×
57
        } else
58
            ware = sgd.PopOptionalEnum<GoodType>();
3✔
59
        was_sounding = sgd.PopBool();
3✔
60
    } else
61
    {
62
        workplace = nullptr;
×
63
        ware = boost::none;
×
64
        was_sounding = false;
×
65
    }
66
}
3✔
67

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

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

105
void nofBuildingWorker::Walked()
144✔
106
{
107
    switch(state)
144✔
108
    {
109
        case State::EnterBuilding:
15✔
110
        {
111
            // Hab ich noch ne Ware in der Hand?
112

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

138
void nofBuildingWorker::WorkingReady()
17✔
139
{
140
    // wir arbeiten nicht mehr
141
    workplace->is_working = false;
17✔
142

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

169
    // Wieder reingehen
170
    StartWalking(Direction::NorthWest);
17✔
171
    state = State::EnterBuilding;
17✔
172
}
17✔
173

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

190
bool nofBuildingWorker::AreWaresAvailable() const
47✔
191
{
192
    return workplace->WaresAvailable();
47✔
193
}
194

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

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

212
    WorkplaceReached();
7✔
213

214
    // ggf. anfangen zu arbeiten
215
    TryToWork();
7✔
216
}
7✔
217

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

255
            // Bescheid sagen, dass Arbeit abgebrochen wurde
256
            WorkAborted();
×
257

258
            // Rumirren
259
            StartWandering();
×
260
            Wander();
×
261

262
            // Evtl. Sounds löschen
263
            world->GetSoundMgr().stopSounds(*this);
×
264

265
            state = State::FigureWork;
×
266
        }
267
        break;
×
268
        case State::EnterBuilding:
×
269
        case State::CarryoutWare:
270
        case State::WalkToWorkpoint:
271
        case State::WalkingHome:
272
        case State::HunterChasing:
273
        case State::HunterFindingShootingpoint:
274
        case State::HunterWalkingToCadaver:
275
        case State::SkinnerWalkingToCarcass:
276
        {
277
            // Bescheid sagen, dass Arbeit abgebrochen wurde
278
            WorkAborted();
×
279

280
            // Rumirren
281
            // Bei diesen States läuft man schon, darf also nicht noch zusätzlich Wander aufrufen, da man dann ja im
282
            // Laufen nochmal losläuft!
283
            StartWandering();
×
284

285
            // Evtl. Sounds löschen
286
            world->GetSoundMgr().stopSounds(*this);
×
287

288
            state = State::FigureWork;
×
289
        }
290
        break;
×
291
    }
292

293
    workplace = nullptr;
1✔
294
}
1✔
295

296
void nofBuildingWorker::ProductionStopped()
3✔
297
{
298
    // Wenn ich gerade warte und schon ein Arbeitsevent angemeldet habe, muss das wieder abgemeldet werden
299
    if(state == State::Waiting1)
3✔
300
    {
301
        GetEvMgr().RemoveEvent(current_ev);
×
302
        current_ev = nullptr;
×
303
        state = State::WaitingForWaresOrProductionStopped;
×
304
        workplace->StartNotWorking();
×
305
    }
306
}
3✔
307

308
void nofBuildingWorker::WorkAborted() {}
×
309

310
void nofBuildingWorker::WorkplaceReached() {}
7✔
311

312
/// Zeichnen der Figur in sonstigen Arbeitslagen
313
void nofBuildingWorker::DrawOtherStates(DrawPoint) {}
×
314

315
/// Zeichnet Figur beim Hereinlaufen/nach Hause laufen mit evtl. getragenen Waren
316
void nofBuildingWorker::DrawWalkingWithWare(DrawPoint drawPt)
×
317
{
318
    unsigned short id = GetCarryID();
×
319
    // >=CARRY_ID_CARRIER_OFFSET -> carrier.bob else jobs.bob!
320
    if(id >= CARRY_ID_CARRIER_OFFSET)
×
321
    {
322
        id -= CARRY_ID_CARRIER_OFFSET;
×
323
        RTTR_Assert(id <= helpers::MaxEnumValue_v<GoodType>);
×
324
        DrawWalkingCarrier(drawPt, GoodType(id), JOB_SPRITE_CONSTS[job_].isFat());
×
325
    } else
326
        DrawWalking(drawPt, LOADER.GetBob("jobs"), id, JOB_SPRITE_CONSTS[job_].isFat());
×
327
}
×
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