Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds an onUnitAction event #2094

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/Lua API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4406,6 +4406,10 @@ These events are straight from EventManager module. Each of them first needs to

Called when a unit uses an interaction on another.

14. ``onUnitAction(unit_id, action)``

Called when a unit does an action (movement, attacking, talking and so on).

Functions
---------

Expand Down
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `EventManager`: add new event type ``JOB_STARTED``, triggered when a job first gains a worker
- `EventManager`: add new event type ``NEW_UNIT_ACTIVE``, triggered when a new unit appears on the active list
- `EventManager`: now each registered handler for an event can have its own frequency instead of all handlers using the lowest frequency of all handlers
- `EventManager`: add new event type ``UNIT_ACTION``, triggered when a unit starts an action
- `stocks`: allow search terms to match the full item label, even when the label is truncated for length
- `dfhack-examples-guide`: add mugs to ``basic`` manager orders
- `gui/create-item`: Added "(chain)" annotation text for armours with the [CHAIN_METAL_TEXT] flag set
Expand Down
6 changes: 6 additions & 0 deletions library/include/modules/EventManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace DFHack {
UNIT_ATTACK,
UNLOAD,
INTERACTION,
UNIT_ACTION,
EVENT_MAX
};
}
Expand Down Expand Up @@ -95,6 +96,11 @@ namespace DFHack {
int32_t defendReport;
};

struct ActionData {
int32_t unitId;
df::unit_action* action;
};

DFHACK_EXPORT void registerListener(EventType::EventType e, EventHandler handler, Plugin* plugin);
DFHACK_EXPORT int32_t registerTick(EventHandler handler, int32_t when, Plugin* plugin, bool absolute=false);
DFHACK_EXPORT void unregister(EventType::EventType e, EventHandler handler, Plugin* plugin);
Expand Down
35 changes: 35 additions & 0 deletions library/modules/EventManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "df/report.h"
#include "df/ui.h"
#include "df/unit.h"
#include "df/unit_action.h"
#include "df/unit_flags1.h"
#include "df/unit_inventory_item.h"
#include "df/unit_report_type.h"
Expand Down Expand Up @@ -138,6 +139,7 @@ static void manageReportEvent(color_ostream& out);
static void manageUnitAttackEvent(color_ostream& out);
static void manageUnloadEvent(color_ostream& out){};
static void manageInteractionEvent(color_ostream& out);
static void manageActionEvent(color_ostream& out);

typedef void (*eventManager_t)(color_ostream&);

Expand Down Expand Up @@ -176,6 +178,8 @@ eventManager_t getManager(EventType::EventType t) {
return manageUnloadEvent;
case EventType::INTERACTION:
return manageInteractionEvent;
case EventType::UNIT_ACTION:
return manageActionEvent;
case EventType::EVENT_MAX:
return nullptr;
//default:
Expand Down Expand Up @@ -235,6 +239,9 @@ static int32_t reportToRelevantUnitsTime = -1;
//interaction
static int32_t lastReportInteraction;

//unit action
static std::unordered_map<int32_t,std::vector<int32_t> > unitToKnownActions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this should be a std::unordered_map<int32_t,std::unordered_set<int32_t>> since there doesn't seem to be a reason to pay the cost of iterating through the vector on every lookup, or am I missing something?

Copy link
Contributor

@cppcooper cppcooper Apr 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your map<set> is a fine approach, but I still think using the action event data alone would be best. std::unordered_set<ActionData> with a hash function that hashes on the unit id and the action id. Maybe I'm missing something, but that looks like it'll give the same guarantees with the fastest lookup times

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. That would be cleaner.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Putnam3145 are you ok with this change?


void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event event) {
static bool doOnce = false;
// const string eventNames[] = {"world loaded", "world unloaded", "map loaded", "map unloaded", "viewscreen changed", "core initialized", "begin unload", "paused", "unpaused"};
Expand All @@ -257,6 +264,7 @@ void DFHack::EventManager::onStateChange(color_ostream& out, state_change_event
buildings.clear();
constructions.clear();
equipmentLog.clear();
unitToKnownActions.clear();

Buildings::clearBuildings(out);
lastReport = -1;
Expand Down Expand Up @@ -1290,3 +1298,30 @@ static void manageInteractionEvent(color_ostream& out) {
//TODO: deduce attacker from latest defend event first
}
}

static void manageActionEvent(color_ostream& out) {
if (!df::global::world)
return;
multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_ACTION].begin(), handlers[EventType::UNIT_ACTION].end());
for ( df::unit* unit : df::global::world->units.all ) {
if ( !Units::isActive(unit) ) {
unitToKnownActions.erase(unit->id);
continue;
}
auto& knownActions = unitToKnownActions[unit->id];
for ( df::unit_action* action : unit->actions ) {
if ( action->type != df::unit_action_type::None) {
if ( std::find(knownActions.begin(), knownActions.end(), action->id) == knownActions.end() ) {
knownActions.push_back(action->id);
for ( auto b = copy.begin(); b != copy.end(); b++ ) {
EventHandler handle = (*b).second;
ActionData data = {unit->id, action};
handle.eventHandler(out, (void*)&data);
}
}
} else {
knownActions.erase(std::remove(knownActions.begin(), knownActions.end(), action->id), knownActions.end());
}
}
}
}
9 changes: 9 additions & 0 deletions plugins/eventful.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "df/reaction_reagent_itemst.h"
#include "df/reaction_product_itemst.h"
#include "df/unit.h"
#include "df/unit_action.h"
#include "df/unit_inventory_item.h"
#include "df/unit_wound.h"
#include "df/world.h"
Expand Down Expand Up @@ -110,6 +111,7 @@ DEFINE_LUA_EVENT_NH_1(onReport, int32_t);
DEFINE_LUA_EVENT_NH_3(onUnitAttack, int32_t, int32_t, int32_t);
DEFINE_LUA_EVENT_NH_0(onUnload);
DEFINE_LUA_EVENT_NH_6(onInteraction, std::string, std::string, int32_t, int32_t, int32_t, int32_t);
DEFINE_LUA_EVENT_NH_2(onUnitAction, int32_t, df::unit_action*);

DFHACK_PLUGIN_LUA_EVENTS {
DFHACK_LUA_EVENT(onWorkshopFillSidebarMenu),
Expand Down Expand Up @@ -137,6 +139,7 @@ DFHACK_PLUGIN_LUA_EVENTS {
DFHACK_LUA_EVENT(onUnitAttack),
DFHACK_LUA_EVENT(onUnload),
DFHACK_LUA_EVENT(onInteraction),
DFHACK_LUA_EVENT(onUnitAction),
DFHACK_LUA_END
};

Expand Down Expand Up @@ -221,6 +224,10 @@ static void ev_mng_interaction(color_ostream& out, void* ptr) {
EventManager::InteractionData* data = (EventManager::InteractionData*)ptr;
onInteraction(out, data->attackVerb, data->defendVerb, data->attacker, data->defender, data->attackReport, data->defendReport);
}
static void ev_mng_unitAction(color_ostream& out, void* ptr) {
EventManager::ActionData* data = (EventManager::ActionData*)ptr;
onUnitAction(out, data->unitId, data->action);
}
std::vector<int> enabledEventManagerEvents(EventManager::EventType::EVENT_MAX,-1);
typedef void (*handler_t) (color_ostream&,void*);

Expand Down Expand Up @@ -260,6 +267,8 @@ handler_t getManager(EventType t) {
return ev_mng_unload;
case INTERACTION:
return ev_mng_interaction;
case UNIT_ACTION:
return ev_mng_unitAction;
case EVENT_MAX:
return nullptr;
//default:
Expand Down
1 change: 1 addition & 0 deletions plugins/lua/eventful.lua
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ eventType=invertTable{
"UNIT_ATTACK",
"UNLOAD",
"INTERACTION",
"UNIT_ACTION",
"EVENT_MAX"
}
return _ENV