Merge branch 'develop' of https://github.com/DFHack/dfhack into develop

develop
Japa 2016-03-05 17:30:54 +05:30
commit 5ec03774b5
22 changed files with 408 additions and 111 deletions

@ -105,7 +105,7 @@ if (NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl OR NOT EXISTS ${dfhac
endif() endif()
# set up versioning. # set up versioning.
set(DF_VERSION "0.42.05") set(DF_VERSION "0.42.06")
SET(DFHACK_RELEASE "alpha1") SET(DFHACK_RELEASE "alpha1")
SET(DFHACK_PRERELEASE TRUE) SET(DFHACK_PRERELEASE TRUE)

@ -70,11 +70,31 @@ New Features
Fixes Fixes
----- -----
- More plugins should recognize non-dwarf citizens
- Fixed a possible crash from cloning jobs
- `confirm` note-delete: No longer interferes with name entry
- `exportlegends`: Handles entities without specific races, and a few other fixes for things new to v0.42 - `exportlegends`: Handles entities without specific races, and a few other fixes for things new to v0.42
- `gaydar`: Fixed text display on OS X/Linux and failure with soul-less creatures
- `manipulator`:
- allowed editing of non-dwarf citizens
- stopped ghosts and visitors from being editable
- fixed applying last custom profession
- `modtools/create-unit`: Stopped making units without civs historical figures
- `modtools/force`:
- Removed siege option
- Prevented a crash resulting from a bad civilization option
- `showmood`: Fixed name display on OS X/Linux - `showmood`: Fixed name display on OS X/Linux
Misc Improvements Misc Improvements
----------------- -----------------
- `autolabor`, `autohauler`, `manipulator`: Added support for new jobs/labors/skills
- `devel/export-dt-ini`: Updated for 0.42.06
- `lua`: Now supports some built-in variables like `gui/gm-editor`, e.g. ``unit``, ``screen``
- `stockflow`: Now offers better control over individual craft jobs
- `weather`: now implemented by a script - `weather`: now implemented by a script

@ -0,0 +1,6 @@
IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt
IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%" -DBUILD_DEVEL=0 -DBUILD_DEV_PLUGINS=0 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1

@ -1,8 +1,6 @@
#define NO_DFHACK_VERSION_MACROS #define NO_DFHACK_VERSION_MACROS
#include "DFHackVersion.h" #include "DFHackVersion.h"
#include "git-describe.h" #include "git-describe.h"
#include "Export.h"
#include <string>
namespace DFHack { namespace DFHack {
namespace Version { namespace Version {
const char *dfhack_version() const char *dfhack_version()

@ -1521,6 +1521,7 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isDwarf), WRAPM(Units, isDwarf),
WRAPM(Units, isCitizen), WRAPM(Units, isCitizen),
WRAPM(Units, getAge), WRAPM(Units, getAge),
WRAPM(Units, getKillCount),
WRAPM(Units, getNominalSkill), WRAPM(Units, getNominalSkill),
WRAPM(Units, getEffectiveSkill), WRAPM(Units, getEffectiveSkill),
WRAPM(Units, getExperience), WRAPM(Units, getExperience),
@ -1531,10 +1532,12 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getCasteProfessionName), WRAPM(Units, getCasteProfessionName),
WRAPM(Units, getProfessionColor), WRAPM(Units, getProfessionColor),
WRAPM(Units, getCasteProfessionColor), WRAPM(Units, getCasteProfessionColor),
WRAPM(Units, getSquadName),
WRAPM(Units, isWar), WRAPM(Units, isWar),
WRAPM(Units, isHunter), WRAPM(Units, isHunter),
WRAPM(Units, isAvailableForAdoption), WRAPM(Units, isAvailableForAdoption),
WRAPM(Units, isOwnCiv), WRAPM(Units, isOwnCiv),
WRAPM(Units, isOwnGroup),
WRAPM(Units, isOwnRace), WRAPM(Units, isOwnRace),
WRAPM(Units, getRaceName), WRAPM(Units, getRaceName),
WRAPM(Units, getRaceNamePlural), WRAPM(Units, getRaceNamePlural),

@ -527,3 +527,96 @@ namespace DFHack {namespace Lua {
name##_event.invoke(out, 7); \ name##_event.invoke(out, 7); \
} \ } \
} }
//No handler versions useful for vmethod events, when we already have a place to put code at triggering
#define DEFINE_LUA_EVENT_NH_0(name) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out) { \
if (name##_event.state_if_count()) { \
name##_event.invoke(out, 0); \
} \
}
#define DEFINE_LUA_EVENT_NH_1(name, arg_type1) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
name##_event.invoke(out, 1); \
} \
}
#define DEFINE_LUA_EVENT_NH_2(name, arg_type1, arg_type2) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
name##_event.invoke(out, 2); \
} \
}
#define DEFINE_LUA_EVENT_NH_3(name, arg_type1, arg_type2, arg_type3) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
name##_event.invoke(out, 3); \
} \
}
#define DEFINE_LUA_EVENT_NH_4(name, arg_type1, arg_type2, arg_type3, arg_type4) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
DFHack::Lua::Push(state, arg4); \
name##_event.invoke(out, 4); \
} \
}
#define DEFINE_LUA_EVENT_NH_5(name, arg_type1, arg_type2, arg_type3, arg_type4, arg_type5) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4, arg_type5 arg5) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
DFHack::Lua::Push(state, arg4); \
DFHack::Lua::Push(state, arg5); \
name##_event.invoke(out, 5); \
} \
}
#define DEFINE_LUA_EVENT_NH_6(name, arg_type1, arg_type2, arg_type3, arg_type4, arg_type5,arg_type6) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4,arg_type5 arg5, arg_type6 arg6) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
DFHack::Lua::Push(state, arg4); \
DFHack::Lua::Push(state, arg5); \
DFHack::Lua::Push(state, arg6); \
name##_event.invoke(out, 6); \
} \
}
#define DEFINE_LUA_EVENT_NH_7(name, arg_type1, arg_type2, arg_type3, arg_type4, arg_type5,arg_type6,arg_type7) \
static DFHack::Lua::Notification name##_event; \
void name(color_ostream &out, arg_type1 arg1, arg_type2 arg2, arg_type3 arg3, arg_type4 arg4,arg_type5 arg5, arg_type6 arg6, arg_type7 arg7) { \
if (auto state = name##_event.state_if_count()) { \
DFHack::Lua::Push(state, arg1); \
DFHack::Lua::Push(state, arg2); \
DFHack::Lua::Push(state, arg3); \
DFHack::Lua::Push(state, arg4); \
DFHack::Lua::Push(state, arg5); \
DFHack::Lua::Push(state, arg6); \
DFHack::Lua::Push(state, arg7); \
name##_event.invoke(out, 7); \
} \
}

@ -240,6 +240,7 @@ DFHACK_EXPORT bool isWar(df::unit* unit);
DFHACK_EXPORT bool isHunter(df::unit* unit); DFHACK_EXPORT bool isHunter(df::unit* unit);
DFHACK_EXPORT bool isAvailableForAdoption(df::unit* unit); DFHACK_EXPORT bool isAvailableForAdoption(df::unit* unit);
DFHACK_EXPORT bool isOwnCiv(df::unit* unit); DFHACK_EXPORT bool isOwnCiv(df::unit* unit);
DFHACK_EXPORT bool isOwnGroup(df::unit* unit);
DFHACK_EXPORT bool isOwnRace(df::unit* unit); DFHACK_EXPORT bool isOwnRace(df::unit* unit);
DFHACK_EXPORT std::string getRaceNameById(int32_t race_id); DFHACK_EXPORT std::string getRaceNameById(int32_t race_id);
@ -267,6 +268,7 @@ DFHACK_EXPORT bool isForest(df::unit* unit);
DFHACK_EXPORT bool isMarkedForSlaughter(df::unit* unit); DFHACK_EXPORT bool isMarkedForSlaughter(df::unit* unit);
DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false); DFHACK_EXPORT double getAge(df::unit *unit, bool true_age = false);
DFHACK_EXPORT int getKillCount(df::unit *unit);
DFHACK_EXPORT int getNominalSkill(df::unit *unit, df::job_skill skill_id, bool use_rust = false); DFHACK_EXPORT int getNominalSkill(df::unit *unit, df::job_skill skill_id, bool use_rust = false);
DFHACK_EXPORT int getEffectiveSkill(df::unit *unit, df::job_skill skill_id); DFHACK_EXPORT int getEffectiveSkill(df::unit *unit, df::job_skill skill_id);

@ -71,6 +71,7 @@ df::job *DFHack::Job::cloneJobStruct(df::job *job, bool keepEverything)
pnew->flags.bits.suspend = job->flags.bits.suspend; pnew->flags.bits.suspend = job->flags.bits.suspend;
pnew->completion_timer = -1; pnew->completion_timer = -1;
pnew->posting_index = -1;
} }
pnew->list_link = NULL; pnew->list_link = NULL;

@ -31,6 +31,7 @@ distribution.
#include <map> #include <map>
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
#include <numeric>
using namespace std; using namespace std;
#include "VersionInfo.h" #include "VersionInfo.h"
@ -47,29 +48,31 @@ using namespace std;
#include "Core.h" #include "Core.h"
#include "MiscUtils.h" #include "MiscUtils.h"
#include "df/world.h" #include "df/burrow.h"
#include "df/ui.h" #include "df/caste_raw.h"
#include "df/job.h" #include "df/creature_raw.h"
#include "df/unit_inventory_item.h" #include "df/curse_attr_change.h"
#include "df/unit_soul.h" #include "df/entity_position.h"
#include "df/nemesis_record.h" #include "df/entity_position_assignment.h"
#include "df/historical_entity.h"
#include "df/entity_raw.h" #include "df/entity_raw.h"
#include "df/entity_raw_flags.h" #include "df/entity_raw_flags.h"
#include "df/game_mode.h"
#include "df/histfig_entity_link_positionst.h"
#include "df/historical_entity.h"
#include "df/historical_figure.h" #include "df/historical_figure.h"
#include "df/historical_figure_info.h" #include "df/historical_figure_info.h"
#include "df/entity_position.h" #include "df/historical_kills.h"
#include "df/entity_position_assignment.h" #include "df/history_event_hist_figure_diedst.h"
#include "df/histfig_entity_link_positionst.h"
#include "df/identity.h" #include "df/identity.h"
#include "df/burrow.h" #include "df/job.h"
#include "df/creature_raw.h" #include "df/nemesis_record.h"
#include "df/caste_raw.h" #include "df/squad.h"
#include "df/game_mode.h" #include "df/ui.h"
#include "df/unit_inventory_item.h"
#include "df/unit_misc_trait.h" #include "df/unit_misc_trait.h"
#include "df/unit_skill.h" #include "df/unit_skill.h"
#include "df/curse_attr_change.h" #include "df/unit_soul.h"
#include "df/squad.h" #include "df/world.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
@ -815,26 +818,22 @@ bool Units::isCitizen(df::unit *unit)
// except that the game appears to let melancholy/raving // except that the game appears to let melancholy/raving
// dwarves count as citizens. // dwarves count as citizens.
if (!isDwarf(unit) || !isSane(unit))
return false;
if (unit->flags1.bits.marauder || if (unit->flags1.bits.marauder ||
unit->flags1.bits.invader_origin || unit->flags1.bits.invader_origin ||
unit->flags1.bits.active_invader || unit->flags1.bits.active_invader ||
unit->flags1.bits.forest || unit->flags1.bits.forest ||
unit->flags1.bits.merchant || unit->flags1.bits.merchant ||
unit->flags1.bits.diplomat) unit->flags1.bits.diplomat ||
unit->flags2.bits.visitor ||
unit->flags2.bits.visitor_uninvited ||
unit->flags2.bits.underworld ||
unit->flags2.bits.resident)
return false; return false;
if (unit->flags1.bits.tame) if (!isSane(unit))
return true; return false;
return unit->civ_id == ui->civ_id && return isOwnGroup(unit);
unit->civ_id != -1 &&
!unit->flags2.bits.underworld &&
!unit->flags2.bits.resident &&
!unit->flags2.bits.visitor_uninvited &&
!unit->flags2.bits.visitor;
} }
bool Units::isDwarf(df::unit *unit) bool Units::isDwarf(df::unit *unit)
@ -888,6 +887,22 @@ bool Units::isOwnCiv(df::unit* unit)
return unit->civ_id == ui->civ_id; return unit->civ_id == ui->civ_id;
} }
// check if creature belongs to the player's group
bool Units::isOwnGroup(df::unit* unit)
{
CHECK_NULL_POINTER(unit);
auto histfig = df::historical_figure::find(unit->hist_figure_id);
if (!histfig)
return false;
for (size_t i = 0; i < histfig->entity_links.size(); i++)
{
auto link = histfig->entity_links[i];
if (link->entity_id == ui->group_id && link->getType() == df::histfig_entity_link_type::MEMBER)
return true;
}
return false;
}
// check if creature belongs to the player's race // check if creature belongs to the player's race
// (in combination with check for civ helps to filter out own dwarves) // (in combination with check for civ helps to filter out own dwarves)
bool Units::isOwnRace(df::unit* unit) bool Units::isOwnRace(df::unit* unit)
@ -1084,6 +1099,25 @@ double Units::getAge(df::unit *unit, bool true_age)
return cur_time - birth_time; return cur_time - birth_time;
} }
int Units::getKillCount(df::unit *unit)
{
CHECK_NULL_POINTER(unit);
auto histfig = df::historical_figure::find(unit->hist_figure_id);
int count = 0;
if (histfig && histfig->info->kills)
{
auto kills = histfig->info->kills;
count += std::accumulate(kills->killed_count.begin(), kills->killed_count.end(), 0);
for (auto it = kills->events.begin(); it != kills->events.end(); ++it)
{
if (virtual_cast<df::history_event_hist_figure_diedst>(df::history_event::find(*it)))
++count;
}
}
return count;
}
inline void adjust_skill_rating(int &rating, bool is_adventure, int value, int dwarf3_4, int dwarf1_2, int adv9_10, int adv3_4, int adv1_2) inline void adjust_skill_rating(int &rating, bool is_adventure, int value, int dwarf3_4, int dwarf1_2, int adv9_10, int adv3_4, int adv1_2)
{ {
if (is_adventure) if (is_adventure)
@ -1783,6 +1817,7 @@ int8_t Units::getCasteProfessionColor(int race, int casteid, df::profession pid)
std::string Units::getSquadName(df::unit *unit) std::string Units::getSquadName(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit);
if (unit->military.squad_id == -1) if (unit->military.squad_id == -1)
return ""; return "";
df::squad *squad = df::squad::find(unit->military.squad_id); df::squad *squad = df::squad::find(unit->military.squad_id);

@ -1 +1 @@
Subproject commit dd3e9e7f47a7991e91d5188546be107fdb61015b Subproject commit 49e1324f415056f3ae39cb32328e3351a3a2b383

@ -107,6 +107,23 @@ void add_tasks(gem_map &gem_types, df::building_workshopst *workshop) {
} }
} }
bool valid_gem(df::item* item) {
if (item->getType() != item_type::ROUGH) return false;
if (item->getMaterial() != builtin_mats::INORGANIC) return false;
if (item->flags.bits.in_job) return false;
if (item->flags.bits.forbid) return false;
if (item->flags.bits.dump) return false;
if (item->flags.bits.owned) return false;
if (item->flags.bits.trader) return false;
if (item->flags.bits.hostile) return false;
if (item->flags.bits.removed) return false;
if (item->flags.bits.encased) return false;
if (item->flags.bits.construction) return false;
if (item->flags.bits.garbage_collect) return false;
if (item->flags.bits.in_building) return false;
return true;
}
void create_jobs() { void create_jobs() {
// Creates jobs in Jeweler's Workshops as necessary. // Creates jobs in Jeweler's Workshops as necessary.
// Todo: Consider path availability? // Todo: Consider path availability?
@ -137,7 +154,7 @@ void create_jobs() {
Buildings::StockpileIterator stored; Buildings::StockpileIterator stored;
for (stored.begin(stockpile); !stored.done(); ++stored) { for (stored.begin(stockpile); !stored.done(); ++stored) {
auto item = *stored; auto item = *stored;
if (item->getType() == item_type::ROUGH && item->getMaterial() == builtin_mats::INORGANIC) { if (valid_gem(item)) {
stockpiled.insert(item->id); stockpiled.insert(item->id);
piled[item->getMaterialIndex()] += 1; piled[item->getMaterialIndex()] += 1;
} }
@ -182,8 +199,7 @@ void create_jobs() {
auto gems = world->items.other[items_other_id::ROUGH]; auto gems = world->items.other[items_other_id::ROUGH];
for (auto g = gems.begin(); g != gems.end(); ++g) { for (auto g = gems.begin(); g != gems.end(); ++g) {
auto item = *g; auto item = *g;
// ROUGH also includes raw glass; the INORGANIC check filters that out. if (valid_gem(item) && !stockpiled.count(item->id)) {
if (item->getMaterial() == builtin_mats::INORGANIC && !stockpiled.count(item->id)) {
available[item->getMaterialIndex()] += 1; available[item->getMaterialIndex()] += 1;
} }
} }
@ -268,7 +284,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
if (enabled && World::isFortressMode()) { if (enabled && World::isFortressMode()) {
// Determine whether auto gem cutting has been disabled for this fort. // Determine whether auto gem cutting has been disabled for this fort.
auto config = World::GetPersistentData(CONFIG_KEY); auto config = World::GetPersistentData(CONFIG_KEY);
running = !(config.isValid() && config.ival(0)); running = config.isValid() && !config.ival(0);
last_frame_count = world->frame_counter; last_frame_count = world->frame_counter;
} }
} else if (event == DFHack::SC_MAP_UNLOADED) { } else if (event == DFHack::SC_MAP_UNLOADED) {
@ -286,9 +302,9 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
} }
enabled = enable; enabled = enable;
running = enabled && World::isFortressMode();
} }
running = enabled && World::isFortressMode();
return CR_OK; return CR_OK;
} }

@ -365,7 +365,15 @@ static const dwarf_state dwarf_states[] = {
BUSY /* PushTrackVehicle */, BUSY /* PushTrackVehicle */,
BUSY /* PlaceTrackVehicle */, BUSY /* PlaceTrackVehicle */,
BUSY /* StoreItemInVehicle */, BUSY /* StoreItemInVehicle */,
BUSY /* GeldAnimal */ BUSY /* GeldAnimal */,
BUSY /* MakeFigurine */,
BUSY /* MakeAmulet */,
BUSY /* MakeScepter */,
BUSY /* MakeCrown */,
BUSY /* MakeRing */,
BUSY /* MakeEarring */,
BUSY /* MakeBracelet */,
BUSY /* MakeGem */
}; };
struct labor_info struct labor_info

@ -360,7 +360,16 @@ static const dwarf_state dwarf_states[] = {
BUSY /* CarveTrack */, BUSY /* CarveTrack */,
BUSY /* PushTrackVehicle */, BUSY /* PushTrackVehicle */,
BUSY /* PlaceTrackVehicle */, BUSY /* PlaceTrackVehicle */,
BUSY /* StoreItemInVehicle */ BUSY /* StoreItemInVehicle */,
BUSY /* GeldAnimal */,
BUSY /* MakeFigurine */,
BUSY /* MakeAmulet */,
BUSY /* MakeScepter */,
BUSY /* MakeCrown */,
BUSY /* MakeRing */,
BUSY /* MakeEarring */,
BUSY /* MakeBracelet */,
BUSY /* MakeGem */
}; };
struct labor_info struct labor_info
@ -1328,6 +1337,15 @@ public:
job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE); job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE); job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::StoreItemInVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE); job_to_labor_table[df::job_type::StoreItemInVehicle] = jlf_const(df::unit_labor::PUSH_HAUL_VEHICLE);
job_to_labor_table[df::job_type::GeldAnimal] = jlf_const(df::unit_labor::GELD);
job_to_labor_table[df::job_type::MakeFigurine] = jlf_make_object;
job_to_labor_table[df::job_type::MakeAmulet] = jlf_make_object;
job_to_labor_table[df::job_type::MakeScepter] = jlf_make_object;
job_to_labor_table[df::job_type::MakeCrown] = jlf_make_object;
job_to_labor_table[df::job_type::MakeRing] = jlf_make_object;
job_to_labor_table[df::job_type::MakeEarring] = jlf_make_object;
job_to_labor_table[df::job_type::MakeBracelet] = jlf_make_object;
job_to_labor_table[df::job_type::MakeGem] = jlf_make_object;
}; };
df::unit_labor find_job_labor(df::job* j) df::unit_labor find_job_labor(df::job* j)

@ -92,51 +92,32 @@ static bool is_lua_hook(const std::string &name)
/* /*
* Hooks * Hooks
*/ */
static void handle_fillsidebar(color_ostream &out,df::building_actual*,bool *call_native){};
static void handle_postfillsidebar(color_ostream &out,df::building_actual*){}; DEFINE_LUA_EVENT_NH_2(onWorkshopFillSidebarMenu, df::building_actual*, bool*);
DEFINE_LUA_EVENT_NH_1(postWorkshopFillSidebarMenu, df::building_actual*);
static void handle_reaction_done(color_ostream &out,df::reaction*, df::reaction_product_itemst*, df::unit *unit, std::vector<df::item*> *in_items,std::vector<df::reaction_reagent*> *in_reag
, std::vector<df::item*> *out_items,bool *call_native){}; DEFINE_LUA_EVENT_NH_7(onReactionComplete, df::reaction*, df::reaction_product_itemst*, df::unit *, std::vector<df::item*> *, std::vector<df::reaction_reagent*> *, std::vector<df::item*> *, bool *);
static void handle_contaminate_wound(color_ostream &out,df::item_actual*,df::unit* unit, df::unit_wound* wound, uint8_t a1, int16_t a2){}; DEFINE_LUA_EVENT_NH_5(onItemContaminateWound, df::item_actual*, df::unit*, df::unit_wound*, uint8_t, int16_t);
static void handle_projitem_ci(color_ostream &out,df::proj_itemst*,bool){};
static void handle_projitem_cm(color_ostream &out,df::proj_itemst*){};
static void handle_projunit_ci(color_ostream &out,df::proj_unitst*,bool){};
static void handle_projunit_cm(color_ostream &out,df::proj_unitst*){};
DEFINE_LUA_EVENT_2(onWorkshopFillSidebarMenu, handle_fillsidebar, df::building_actual*,bool* );
DEFINE_LUA_EVENT_1(postWorkshopFillSidebarMenu, handle_postfillsidebar, df::building_actual*);
DEFINE_LUA_EVENT_7(onReactionComplete, handle_reaction_done,df::reaction*, df::reaction_product_itemst*, df::unit *, std::vector<df::item*> *,std::vector<df::reaction_reagent*> *,std::vector<df::item*> *,bool *);
DEFINE_LUA_EVENT_5(onItemContaminateWound, handle_contaminate_wound, df::item_actual*,df::unit* , df::unit_wound* , uint8_t , int16_t );
//projectiles //projectiles
DEFINE_LUA_EVENT_2(onProjItemCheckImpact, handle_projitem_ci, df::proj_itemst*,bool ); DEFINE_LUA_EVENT_NH_2(onProjItemCheckImpact, df::proj_itemst*, bool);
DEFINE_LUA_EVENT_1(onProjItemCheckMovement, handle_projitem_cm, df::proj_itemst*); DEFINE_LUA_EVENT_NH_1(onProjItemCheckMovement, df::proj_itemst*);
DEFINE_LUA_EVENT_2(onProjUnitCheckImpact, handle_projunit_ci, df::proj_unitst*,bool ); DEFINE_LUA_EVENT_NH_2(onProjUnitCheckImpact, df::proj_unitst*, bool);
DEFINE_LUA_EVENT_1(onProjUnitCheckMovement, handle_projunit_cm, df::proj_unitst* ); DEFINE_LUA_EVENT_NH_1(onProjUnitCheckMovement, df::proj_unitst*);
//event manager //event manager
static void handle_int32t(color_ostream &out,int32_t){}; //we don't use this so why not use it everywhere DEFINE_LUA_EVENT_NH_1(onBuildingCreatedDestroyed, int32_t);
static void handle_job_init(color_ostream &out,df::job*){}; DEFINE_LUA_EVENT_NH_1(onJobInitiated, df::job*);
static void handle_job_complete(color_ostream &out,df::job*){}; DEFINE_LUA_EVENT_NH_1(onJobCompleted, df::job*);
static void handle_constructions(color_ostream &out,df::construction*){}; DEFINE_LUA_EVENT_NH_1(onUnitDeath, int32_t);
static void handle_syndrome(color_ostream &out,int32_t,int32_t){}; DEFINE_LUA_EVENT_NH_1(onItemCreated, int32_t);
static void handle_inventory_change(color_ostream& out,int32_t,int32_t,df::unit_inventory_item*,df::unit_inventory_item*){}; DEFINE_LUA_EVENT_NH_1(onConstructionCreatedDestroyed, df::construction*);
static void handle_report(color_ostream& out,int32_t){}; DEFINE_LUA_EVENT_NH_2(onSyndrome, int32_t, int32_t);
static void handle_unitAttack(color_ostream& out,int32_t,int32_t,int32_t){}; DEFINE_LUA_EVENT_NH_1(onInvasion, int32_t);
static void handle_unload(color_ostream& out){}; DEFINE_LUA_EVENT_NH_4(onInventoryChange, int32_t, int32_t, df::unit_inventory_item*, df::unit_inventory_item*);
static void handle_interaction(color_ostream& out, std::string, std::string, int32_t, int32_t, int32_t, int32_t){}; DEFINE_LUA_EVENT_NH_1(onReport, int32_t);
DEFINE_LUA_EVENT_1(onBuildingCreatedDestroyed, handle_int32t, int32_t); DEFINE_LUA_EVENT_NH_3(onUnitAttack, int32_t, int32_t, int32_t);
DEFINE_LUA_EVENT_1(onJobInitiated,handle_job_init,df::job*); DEFINE_LUA_EVENT_NH_0(onUnload);
DEFINE_LUA_EVENT_1(onJobCompleted,handle_job_complete,df::job*); DEFINE_LUA_EVENT_NH_6(onInteraction, std::string, std::string, int32_t, int32_t, int32_t, int32_t);
DEFINE_LUA_EVENT_1(onUnitDeath,handle_int32t,int32_t);
DEFINE_LUA_EVENT_1(onItemCreated,handle_int32t,int32_t);
DEFINE_LUA_EVENT_1(onConstructionCreatedDestroyed, handle_constructions, df::construction*);
DEFINE_LUA_EVENT_2(onSyndrome, handle_syndrome, int32_t,int32_t);
DEFINE_LUA_EVENT_1(onInvasion,handle_int32t,int32_t);
DEFINE_LUA_EVENT_4(onInventoryChange,handle_inventory_change,int32_t,int32_t,df::unit_inventory_item*,df::unit_inventory_item*);
DEFINE_LUA_EVENT_1(onReport,handle_report,int32_t);
DEFINE_LUA_EVENT_3(onUnitAttack,handle_unitAttack,int32_t,int32_t,int32_t);
DEFINE_LUA_EVENT_0(onUnload,handle_unload);
DEFINE_LUA_EVENT_6(onInteraction,handle_interaction, std::string, std::string, int32_t, int32_t, int32_t, int32_t);
DFHACK_PLUGIN_LUA_EVENTS { DFHACK_PLUGIN_LUA_EVENTS {
DFHACK_LUA_EVENT(onWorkshopFillSidebarMenu), DFHACK_LUA_EVENT(onWorkshopFillSidebarMenu),
DFHACK_LUA_EVENT(postWorkshopFillSidebarMenu), DFHACK_LUA_EVENT(postWorkshopFillSidebarMenu),
@ -417,8 +398,6 @@ static bool find_reactions(color_ostream &out)
for (size_t i = 0; i < rlist.size(); i++) for (size_t i = 0; i < rlist.size(); i++)
{ {
//if (!is_lua_hook(rlist[i]->code))
// continue;
reactions[rlist[i]->code].react = rlist[i]; reactions[rlist[i]->code].react = rlist[i];
} }
@ -460,7 +439,6 @@ static void world_specific_hooks(color_ostream &out,bool enable)
{ {
if(enable && find_reactions(out)) if(enable && find_reactions(out))
{ {
//out.print("Detected reaction hooks - enabling plugin.\n");
INTERPOSE_HOOK(product_hook, produce).apply(true); INTERPOSE_HOOK(product_hook, produce).apply(true);
} }
else else

@ -272,6 +272,8 @@ function collect_reactions()
materials.wood.adjective = "wooden" materials.wood.adjective = "wooden"
materials.tooth.adjective = "ivory/tooth" materials.tooth.adjective = "ivory/tooth"
materials.leather.clothing_flag = "LEATHER" materials.leather.clothing_flag = "LEATHER"
materials.shell.short = true
materials.pearl.short = true
-- Collection and Entrapment -- Collection and Entrapment
reaction_entry(result, job_types.CollectWebs) reaction_entry(result, job_types.CollectWebs)
@ -360,6 +362,7 @@ function collect_reactions()
local cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather} local cloth_mats = {materials.cloth, materials.silk, materials.yarn, materials.leather}
for _, material in ipairs(cloth_mats) do for _, material in ipairs(cloth_mats) do
material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material) material_reactions(result, {{job_types.SewImage, "Sew", "Image"}}, material)
material.cloth = true
end end
for _, spec in ipairs{materials.bone, materials.shell, materials.tooth, materials.horn, materials.pearl} do for _, spec in ipairs{materials.bone, materials.shell, materials.tooth, materials.horn, materials.pearl} do
@ -527,6 +530,14 @@ function collect_reactions()
{job_types.MakeFlask, "Forge", "Flask"}, {job_types.MakeFlask, "Forge", "Flask"},
{job_types.MakeChain, "Forge", "Chain"}, {job_types.MakeChain, "Forge", "Chain"},
{job_types.MakeCrafts, "Make", "Crafts"}, {job_types.MakeCrafts, "Make", "Crafts"},
{job_types.MakeFigurine, "Make", "Figurine"},
{job_types.MakeAmulet, "Make", "Amulet"},
{job_types.MakeScepter, "Make", "Scepter"},
{job_types.MakeCrown, "Make", "Crown"},
{job_types.MakeRing, "Make", "Ring"},
{job_types.MakeEarring, "Make", "Earring"},
{job_types.MakeBracelet, "Make", "Bracelet"},
{job_types.MakeGem, "Make Large", "Gem"},
}, mat_flags) }, mat_flags)
end end
@ -719,6 +730,7 @@ function collect_reactions()
end end
end end
-- Crafts
for _, mat in ipairs{ for _, mat in ipairs{
materials.wood, materials.wood,
materials.rock, materials.rock,
@ -732,7 +744,27 @@ function collect_reactions()
materials.pearl, materials.pearl,
materials.yarn, materials.yarn,
} do } do
material_reactions(result, {{job_types.MakeCrafts, "Make", "Crafts"}}, mat) material_reactions(result, {
{job_types.MakeCrafts, "Make", "Crafts"},
{job_types.MakeAmulet, "Make", "Amulet"},
{job_types.MakeBracelet, "Make", "Bracelet"},
{job_types.MakeEarring, "Make", "Earring"},
}, mat)
if not mat.cloth then
material_reactions(result, {
{job_types.MakeCrown, "Make", "Crown"},
{job_types.MakeFigurine, "Make", "Figurine"},
{job_types.MakeRing, "Make", "Ring"},
{job_types.MakeGem, "Make Large", "Gem"},
}, mat)
if not mat.short then
material_reactions(result, {
{job_types.MakeScepter, "Make", "Scepter"},
}, mat)
end
end
end end
-- Siege engine parts -- Siege engine parts

@ -256,10 +256,26 @@ const SkillColumn columns[] = {
{19, 6, profession::NONE, unit_labor::NONE, job_skill::POETRY, "Po"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::POETRY, "Po"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::READING, "Rd"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::READING, "Rd"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::SPEAKING, "Sp"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::SPEAKING, "Sp"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::DANCE, "Dn"},
{20, 5, profession::NONE, unit_labor::NONE, job_skill::MILITARY_TACTICS, "MT"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::MAKE_MUSIC, "MM"},
{20, 5, profession::NONE, unit_labor::NONE, job_skill::TRACKING, "Tr"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::SING_MUSIC, "SM"},
{20, 5, profession::NONE, unit_labor::NONE, job_skill::MAGIC_NATURE, "Dr"}, {19, 6, profession::NONE, unit_labor::NONE, job_skill::PLAY_KEYBOARD_INSTRUMENT, "PK"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::PLAY_STRINGED_INSTRUMENT, "PS"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::PLAY_WIND_INSTRUMENT, "PW"},
{19, 6, profession::NONE, unit_labor::NONE, job_skill::PLAY_PERCUSSION_INSTRUMENT, "PP"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::CRITICAL_THINKING, "CT"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::LOGIC, "Lo"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::MATHEMATICS, "Ma"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::ASTRONOMY, "As"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::CHEMISTRY, "Ch"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::GEOGRAPHY, "Ge"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::OPTICS_ENGINEER, "OE"},
{20, 4, profession::NONE, unit_labor::NONE, job_skill::FLUID_ENGINEER, "FE"},
{21, 5, profession::NONE, unit_labor::NONE, job_skill::MILITARY_TACTICS, "MT"},
{21, 5, profession::NONE, unit_labor::NONE, job_skill::TRACKING, "Tr"},
{21, 5, profession::NONE, unit_labor::NONE, job_skill::MAGIC_NATURE, "Dr"},
}; };
struct UnitInfo struct UnitInfo
@ -992,7 +1008,7 @@ public:
} }
void select_profession(size_t selected) void select_profession(size_t selected)
{ {
if (selected >= manager.templates.size()) if (selected > manager.templates.size())
return; return;
ProfessionTemplate prof = manager.templates[selected - 1]; ProfessionTemplate prof = manager.templates[selected - 1];
@ -1127,15 +1143,21 @@ viewscreen_unitlaborsst::viewscreen_unitlaborsst(vector<df::unit*> &src, int cur
cur->selected = false; cur->selected = false;
cur->active_index = active_idx[unit]; cur->active_index = active_idx[unit];
if (!Units::isOwnRace(unit)) if (!Units::isOwnCiv(unit))
cur->allowEdit = false; cur->allowEdit = false;
if (!Units::isOwnCiv(unit)) if (!Units::isOwnGroup(unit))
cur->allowEdit = false; cur->allowEdit = false;
if (unit->flags1.bits.dead) if (unit->flags1.bits.dead)
cur->allowEdit = false; cur->allowEdit = false;
if (unit->flags2.bits.visitor)
cur->allowEdit = false;
if (unit->flags3.bits.ghostly)
cur->allowEdit = false;
if (!ENUM_ATTR(profession, can_assign_labor, unit->profession)) if (!ENUM_ATTR(profession, can_assign_labor, unit->profession))
cur->allowEdit = false; cur->allowEdit = false;

@ -179,6 +179,7 @@ address('shearable_tissues_vector',df.caste_raw,'shearable_tissue_layer')
address('extracts',df.caste_raw,'extracts','extract_matidx') address('extracts',df.caste_raw,'extracts','extract_matidx')
header('hist_entity_offsets') header('hist_entity_offsets')
address('histfigs',df.historical_entity,'histfig_ids')
address('beliefs',df.historical_entity,'resources','values') address('beliefs',df.historical_entity,'resources','values')
address('squads',df.historical_entity,'squads') address('squads',df.historical_entity,'squads')
address('positions',df.historical_entity,'positions','own') address('positions',df.historical_entity,'positions','own')
@ -300,6 +301,7 @@ address('race',df.unit,'race')
address('flags1',df.unit,'flags1') address('flags1',df.unit,'flags1')
address('flags2',df.unit,'flags2') address('flags2',df.unit,'flags2')
address('flags3',df.unit,'flags3') address('flags3',df.unit,'flags3')
address('meeting',df.unit,'meeting')
address('caste',df.unit,'caste') address('caste',df.unit,'caste')
address('sex',df.unit,'sex') address('sex',df.unit,'sex')
address('id',df.unit,'id') address('id',df.unit,'id')
@ -432,7 +434,7 @@ address('uniform_item_filter',df.squad_uniform_spec,'item_filter')
address('uniform_indiv_choice',df.squad_uniform_spec,'indiv_choice') address('uniform_indiv_choice',df.squad_uniform_spec,'indiv_choice')
header('activity_offsets') header('activity_offsets')
address('activity_type',df.activity_entry,'id') address('activity_type',df.activity_entry,'type')
address('events',df.activity_entry,'events') address('events',df.activity_entry,'events')
address('participants',df.activity_event_combat_trainingst,'participants') address('participants',df.activity_event_combat_trainingst,'participants')
address('sq_lead',df.activity_event_skill_demonstrationst,'hist_figure_id') address('sq_lead',df.activity_event_skill_demonstrationst,'hist_figure_id')

@ -87,6 +87,7 @@ versions = {
[1533] = "0.42.03", [1533] = "0.42.03",
[1534] = "0.42.04", [1534] = "0.42.04",
[1537] = "0.42.05", [1537] = "0.42.05",
[1542] = "0.42.06",
} }
min_version = math.huge min_version = math.huge

@ -56,6 +56,10 @@ orientation filters:
return return
end end
function dfprint(s)
print(dfhack.df2console(s))
end
function getSexString(sex) function getSexString(sex)
local sexStr local sexStr
if sex==0 then if sex==0 then
@ -69,7 +73,7 @@ function getSexString(sex)
end end
local function determineorientation(unit) local function determineorientation(unit)
if unit.sex~=-1 then if unit.sex~=-1 and unit.status.current_soul then
local return_string='' local return_string=''
local orientation=unit.status.current_soul.orientation_flags local orientation=unit.status.current_soul.orientation_flags
if orientation.indeterminate then if orientation.indeterminate then
@ -139,7 +143,7 @@ elseif args.named then
else else
local unit=dfhack.gui.getSelectedUnit(true) local unit=dfhack.gui.getSelectedUnit(true)
local name,ok=nameOrSpeciesAndNumber(unit) local name,ok=nameOrSpeciesAndNumber(unit)
print(name..determineorientation(unit)) dfprint(name..determineorientation(unit))
return return
end end
@ -169,35 +173,35 @@ end
if args.notStraight then if args.notStraight then
local totalNotShown=0 local totalNotShown=0
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
if isNotStraight(v) then print(v) else totalNotShown=totalNotShown+1 end if isNotStraight(v) then dfprint(v) else totalNotShown=totalNotShown+1 end
end end
print('Total not shown: '..totalNotShown) print('Total not shown: '..totalNotShown)
elseif args.gayOnly then elseif args.gayOnly then
local totalNotShown=0 local totalNotShown=0
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
if isGay(v) then print(v) else totalNotShown=totalNotShown+1 end if isGay(v) then dfprint(v) else totalNotShown=totalNotShown+1 end
end end
print('Total not shown: '..totalNotShown) print('Total not shown: '..totalNotShown)
elseif args.asexualOnly then elseif args.asexualOnly then
local totalNotShown=0 local totalNotShown=0
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
if isAsexual(v) then print(v) else totalNotShown=totalNotShown+1 end if isAsexual(v) then dfprint(v) else totalNotShown=totalNotShown+1 end
end end
print('Total not shown: '..totalNotShown) print('Total not shown: '..totalNotShown)
elseif args.straightOnly then elseif args.straightOnly then
local totalNotShown=0 local totalNotShown=0
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
if not isNotStraight(v) then print(v) else totalNotShown=totalNotShown+1 end if not isNotStraight(v) then dfprint(v) else totalNotShown=totalNotShown+1 end
end end
print('Total not shown: '..totalNotShown) print('Total not shown: '..totalNotShown)
elseif args.biOnly then elseif args.biOnly then
local totalNotShown=0 local totalNotShown=0
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
if isBi(v) then print(v) else totalNotShown=totalNotShown+1 end if isBi(v) then dfprint(v) else totalNotShown=totalNotShown+1 end
end end
print('Total not shown: '..totalNotShown) print('Total not shown: '..totalNotShown)
else else
for k,v in ipairs(orientations) do for k,v in ipairs(orientations) do
print(v) dfprint(v)
end end
end end

@ -27,6 +27,25 @@ There are the following ways to invoke this command:
local args={...} local args={...}
local cmd = args[1] local cmd = args[1]
env = env or {}
setmetatable(env, {__index = function(self, k)
if k == 'scr' or k == 'screen' then
return dfhack.gui.getCurViewscreen()
elseif k == 'bld' or k == 'building' then
return dfhack.gui.getSelectedBuilding()
elseif k == 'item' then
return dfhack.gui.getSelectedItem()
elseif k == 'job' then
return dfhack.gui.getSelectedJob()
elseif k == 'wsjob' or k == 'workshop_job' then
return dfhack.gui.getSelectedWorkshopJob()
elseif k == 'unit' then
return dfhack.gui.getSelectedUnit()
else
return _G[k]
end
end})
if cmd=="--file" or cmd=="-f" then if cmd=="--file" or cmd=="-f" then
local f,err=loadfile (args[2]) local f,err=loadfile (args[2])
if f==nil then if f==nil then
@ -68,5 +87,5 @@ elseif cmd~=nil then
end end
end end
else else
dfhack.interpreter("lua","lua.history") dfhack.interpreter("lua","lua.history",env)
end end

@ -1,8 +1,10 @@
-- create-unit.lua -- create-unit.lua
-- Originally created by warmist, edited by Putnam for the dragon ball mod to be used in reactions, modified by Dirst for use in The Earth Strikes Back mod, incorporating fixes discovered by Boltgun then Mifiki wrote the bit where it switches to arena mode briefly to do some of the messy work, then Expwnent combined that with the old script to make it function for histfigs -- Originally created by warmist, edited by Putnam for the dragon ball mod to be used in reactions, modified by Dirst for use in The Earth Strikes Back mod, incorporating fixes discovered by Boltgun then Mifiki wrote the bit where it switches to arena mode briefly to do some of the messy work, then Expwnent combined that with the old script to make it function for histfigs
-- version 0.5 -- version 0.51
-- This is a beta version. Use at your own risk. -- This is a beta version. Use at your own risk.
-- Modifications from 0.5: civ -1 creates are NOT historical figures, mitigated screen-movement bug in createUnit()
--[[ --[[
TODO TODO
children and babies: set child/baby job children and babies: set child/baby job
@ -30,6 +32,10 @@ end
local utils=require 'utils' local utils=require 'utils'
function createUnit(race_id, caste_id) function createUnit(race_id, caste_id)
local view_x = df.global.window_x
local view_y = df.global.window_y
local view_z = df.global.window_z
local curViewscreen = dfhack.gui.getCurViewscreen() local curViewscreen = dfhack.gui.getCurViewscreen()
local dwarfmodeScreen = df.viewscreen_dwarfmodest:new() local dwarfmodeScreen = df.viewscreen_dwarfmodest:new()
curViewscreen.child = dwarfmodeScreen curViewscreen.child = dwarfmodeScreen
@ -64,6 +70,11 @@ function createUnit(race_id, caste_id)
df.global.ui.main.mode = oldMode df.global.ui.main.mode = oldMode
local id = df.global.unit_next_id-1 local id = df.global.unit_next_id-1
df.global.window_x = view_x
df.global.window_y = view_y
df.global.window_z = view_z
return id return id
end end
@ -261,6 +272,22 @@ function domesticate(uid, group_id)
end end
end end
function wild(uid)
local u = df.unit.find(uid)
local caste=df.creature_raw.find(u.race).caste[u.caste]
-- x = df.global.world.world_data.active_site[0].pos.x
-- y = df.global.world.world_data.active_site[0].pos.y
-- region = df.global.map.map_blocks[df.global.map.x_count_block*x+y]
if not(caste.flags.CAN_SPEAK and caste.flags.CAN_LEARN) then
u.animal.population.region_x = 1
u.animal.population.region_y = 1
u.animal.population.unk_28 = -1
u.animal.population.population_idx = 1
u.animal.population.depth = 0
end
end
function nameUnit(id, entityRawName, civ_id) function nameUnit(id, entityRawName, civ_id)
--pick a random appropriate name --pick a random appropriate name
--choose three random words in the appropriate things --choose three random words in the appropriate things
@ -448,10 +475,17 @@ elseif args.groupId and tonumber(args.groupId) then
group_id = tonumber(args.groupId) group_id = tonumber(args.groupId)
end end
local unitId = createUnitInCiv(raceIndex, casteIndex, civ_id, group_id) local unitId
if civ_id == -1 then
unitId = createUnit(raceIndex, casteIndex)
else
unitId = createUnitInCiv(raceIndex, casteIndex, civ_id, group_id)
end
if args.domesticate then if args.domesticate then
domesticate(unitId, group_id) domesticate(unitId, group_id)
else
wild(unitId)
end end
if age or age == 0 then if age or age == 0 then

@ -6,7 +6,7 @@
modtools/force modtools/force
============== ==============
This tool triggers events like megabeasts, caravans, invaders, and migrants. This tool triggers events like megabeasts, caravans, and migrants.
=end]] =end]]
local utils = require 'utils' local utils = require 'utils'
@ -44,7 +44,6 @@ arguments:
WildlifeCurious WildlifeCurious
WildlifeMischievous WildlifeMischievous
WildlifeFlier WildlifeFlier
CivAttack
NightCreature NightCreature
-civ entity -civ entity
specify the civ of the event, if applicable specify the civ of the event, if applicable
@ -54,7 +53,7 @@ arguments:
EVIL EVIL
28 28
]]) ]])
print('force: -eventType [Megabeast, Migrants, Caravan, Diplomat, WildlifeCurious, WildlifeMischievous, WildlifeFlier, CivAttack, NightCreature] -civ [player,ENTITY_ID]') print('force: -eventType [Megabeast, Migrants, Caravan, Diplomat, WildlifeCurious, WildlifeMischievous, WildlifeFlier, NightCreature] -civ [player,ENTITY_ID]')
return return
end end
@ -67,7 +66,13 @@ end
if args.civ == 'player' then if args.civ == 'player' then
args.civ = df.historical_entity.find(df.global.ui.civ_id) args.civ = df.historical_entity.find(df.global.ui.civ_id)
elseif args.civ then elseif args.civ then
local civ = args.civ
args.civ = findCiv(args.civ) args.civ = findCiv(args.civ)
if not args.civ then
error('Invalid civ: ' .. civ)
end
elseif args.eventType == 'Caravan' or args.eventType == 'Diplomat' then
error('Specify civ for this eventType')
end end
if args.eventType == 'Migrants' then if args.eventType == 'Migrants' then