Skip to content

Commit 39fabcb

Browse files
authored
Merge pull request #5256 from ong-yinggao98/squad-features
Add function to remove unit from squad
2 parents c217409 + 6d44e8f commit 39fabcb

File tree

5 files changed

+140
-0
lines changed

5 files changed

+140
-0
lines changed

docs/changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ Template for new versions:
3535
## Documentation
3636

3737
## API
38+
- ``Military::removeFromSquad``: removes unit from any squad assignments
3839

3940
## Lua
4041
- ``dfhack.units.setAutomaticProfessions``: sets unit labors according to current work detail settings
42+
- ``dfhack.military.removeFromSquad``: Lua API for ``Military::removeFromSquad``
4143

4244
## Removed
4345

docs/dev/Lua API.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,14 @@ Military module
19861986

19871987
Returns the name of a squad as a string.
19881988

1989+
* ``dfhack.military.removeFromSquad(unit_id)``
1990+
1991+
Removes a unit from its squad. Unsets the unit's
1992+
military information (i.e., ``unit.military.squad_id`` and
1993+
``unit.military.squad_pos``), the squad's position information (i.e.,
1994+
``squad.positions[squad_pos].occupant``), and modifies the unit's entity links
1995+
to indicate former squad membership or command.
1996+
19891997
Items module
19901998
------------
19911999

library/LuaApi.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,7 @@ static const LuaWrapper::FunctionReg dfhack_military_module[] = {
23412341
WRAPM(Military, makeSquad),
23422342
WRAPM(Military, updateRoomAssignments),
23432343
WRAPM(Military, getSquadName),
2344+
WRAPM(Military, removeFromSquad),
23442345
{ NULL, NULL }
23452346
};
23462347

library/include/modules/Military.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace Military
1717
DFHACK_EXPORT std::string getSquadName(int32_t squad_id);
1818
DFHACK_EXPORT df::squad* makeSquad(int32_t assignment_id);
1919
DFHACK_EXPORT void updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::squad_use_flags flags);
20+
DFHACK_EXPORT bool removeFromSquad(int32_t unit_id);
2021

2122
}
2223
}

library/modules/Military.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44
#include "MiscUtils.h"
55
#include "modules/Military.h"
66
#include "modules/Translation.h"
7+
#include "modules/Units.h"
78
#include "df/building.h"
89
#include "df/building_civzonest.h"
10+
#include "df/histfig_entity_link_former_positionst.h"
11+
#include "df/histfig_entity_link_former_squadst.h"
12+
#include "df/histfig_entity_link_positionst.h"
13+
#include "df/histfig_entity_link_squadst.h"
914
#include "df/historical_figure.h"
1015
#include "df/historical_entity.h"
1116
#include "df/entity_position.h"
@@ -16,6 +21,7 @@
1621
#include "df/squad_schedule_order.h"
1722
#include "df/squad_order.h"
1823
#include "df/squad_order_trainst.h"
24+
#include "df/unit.h"
1925
#include "df/world.h"
2026

2127
using namespace DFHack;
@@ -289,3 +295,125 @@ void Military::updateRoomAssignments(int32_t squad_id, int32_t civzone_id, df::s
289295
}
290296
}
291297
}
298+
299+
static void remove_soldier_entity_link(df::historical_figure* hf, df::squad* squad)
300+
{
301+
int32_t start_year = -1;
302+
for (size_t i = 0; i < hf->entity_links.size(); i++)
303+
{
304+
df::histfig_entity_link* link = hf->entity_links[i];
305+
if (link->getType() != df::enums::histfig_entity_link_type::SQUAD)
306+
continue;
307+
308+
auto squad_link = strict_virtual_cast<df::histfig_entity_link_squadst>(link);
309+
if (squad_link == nullptr || squad_link->squad_id != squad->id)
310+
continue;
311+
312+
hf->entity_links.erase(hf->entity_links.begin() + i);
313+
start_year = squad_link->start_year;
314+
315+
delete squad_link;
316+
break;
317+
}
318+
319+
if (start_year == -1)
320+
return;
321+
322+
auto former_squad = df::allocate<df::histfig_entity_link_former_squadst>();
323+
former_squad->squad_id = squad->id;
324+
former_squad->entity_id = squad->entity_id;
325+
former_squad->start_year = start_year;
326+
former_squad->end_year = *df::global::cur_year;
327+
former_squad->link_strength = 100;
328+
329+
hf->entity_links.push_back(former_squad);
330+
}
331+
332+
static void remove_officer_entity_link(df::historical_figure* hf, df::squad* squad)
333+
{
334+
std::vector<Units::NoblePosition> nps;
335+
if (!Units::getNoblePositions(&nps, hf))
336+
return;
337+
338+
int32_t assignment_id = -1;
339+
for (auto& np : nps)
340+
{
341+
if (np.entity->id != squad->entity_id || np.assignment->squad_id != squad->id)
342+
continue;
343+
344+
np.assignment->histfig = -1;
345+
np.assignment->histfig2 = -1;
346+
347+
assignment_id = np.assignment->id;
348+
break;
349+
}
350+
351+
if (assignment_id == -1)
352+
return;
353+
354+
int32_t start_year = -1;
355+
for (size_t i = 0; i < hf->entity_links.size(); i++)
356+
{
357+
df::histfig_entity_link* link = hf->entity_links[i];
358+
if (link->getType() != df::enums::histfig_entity_link_type::POSITION)
359+
continue;
360+
361+
auto pos_link = strict_virtual_cast<df::histfig_entity_link_positionst>(link);
362+
if (pos_link == nullptr)
363+
continue;
364+
if (pos_link->assignment_id != assignment_id && pos_link->entity_id != squad->entity_id)
365+
continue;
366+
367+
hf->entity_links.erase(hf->entity_links.begin() + i);
368+
start_year = pos_link->start_year;
369+
370+
delete pos_link;
371+
break;
372+
}
373+
374+
if (start_year == -1)
375+
return;
376+
377+
auto former_pos = df::allocate<df::histfig_entity_link_former_positionst>();
378+
former_pos->assignment_id = assignment_id;
379+
former_pos->entity_id = squad->entity_id;
380+
former_pos->start_year = start_year;
381+
former_pos->end_year = *df::global::cur_year;
382+
former_pos->link_strength = 100;
383+
384+
hf->entity_links.push_back(former_pos);
385+
}
386+
387+
bool Military::removeFromSquad(int32_t unit_id)
388+
{
389+
df::unit *unit = df::unit::find(unit_id);
390+
if (unit == nullptr || unit->military.squad_id == -1 || unit->military.squad_position == -1)
391+
return false;
392+
393+
int32_t squad_id = unit->military.squad_id;
394+
df::squad* squad = df::squad::find(squad_id);
395+
if (squad == nullptr)
396+
return false;
397+
398+
int32_t squad_pos = unit->military.squad_position;
399+
df::squad_position* pos = vector_get(squad->positions, squad_pos);
400+
if (pos == nullptr)
401+
return false;
402+
403+
df::historical_figure* hf = df::historical_figure::find(unit->hist_figure_id);
404+
if (hf == nullptr)
405+
return false;
406+
407+
// remove from squad information
408+
pos->occupant = -1;
409+
// remove from unit information
410+
unit->military.squad_id = -1;
411+
unit->military.squad_position = -1;
412+
413+
if (squad_pos == 0) // is unit a commander?
414+
remove_officer_entity_link(hf, squad);
415+
else
416+
remove_soldier_entity_link(hf, squad);
417+
418+
return true;
419+
}

0 commit comments

Comments
 (0)