diff options
| author | Quietust | 2012-09-13 14:08:26 -0500 |
|---|---|---|
| committer | Quietust | 2012-09-13 14:08:26 -0500 |
| commit | cae01250ff5bc3df14677371459ef3b8b6451a08 (patch) | |
| tree | e0f29746eaddb900ed63ea1b4d66b4e50bb7bd9a | |
| parent | ae6e0f617dec8394b1572b400928f3a6676211ab (diff) | |
| parent | 881fed41def071e43c324ce81579837d8949c3b7 (diff) | |
| download | dfhack-cae01250ff5bc3df14677371459ef3b8b6451a08.tar.gz dfhack-cae01250ff5bc3df14677371459ef3b8b6451a08.tar.bz2 dfhack-cae01250ff5bc3df14677371459ef3b8b6451a08.tar.xz | |
Merge branch 'master' of https://github.com/angavrilov/dfhack
| -rw-r--r-- | plugins/devel/siege-engine.cpp | 177 | ||||
| -rw-r--r-- | scripts/gui/siege-engine.lua | 36 |
2 files changed, 139 insertions, 74 deletions
diff --git a/plugins/devel/siege-engine.cpp b/plugins/devel/siege-engine.cpp index b41ac931..a41bfe5f 100644 --- a/plugins/devel/siege-engine.cpp +++ b/plugins/devel/siege-engine.cpp @@ -49,6 +49,7 @@ #include "df/items_other_id.h" #include "df/building_stockpilest.h" #include "df/stockpile_links.h" +#include "df/workshop_profile.h" #include "MiscUtils.h" @@ -162,7 +163,7 @@ static void random_direction(float &x, float &y, float &z) } /* - * Configuration management + * Configuration object */ static bool enable_plugin(); @@ -187,6 +188,7 @@ struct EngineInfo { std::set<int> stockpiles; df::stockpile_links links; + df::workshop_profile profile; bool hasTarget() { return is_range_valid(target); } bool onTarget(df::coord pos) { return is_in_range(target, pos); } @@ -200,8 +202,6 @@ struct EngineInfo { static std::map<df::building*, EngineInfo*> engines; static std::map<df::coord, df::building*> coord_engines; -static std::set<df::building*> recheck_piles; - static EngineInfo *find_engine(df::building *bld, bool create = false) { auto ebld = strict_virtual_cast<df::building_siegeenginest>(bld); @@ -270,13 +270,16 @@ static EngineInfo *find_engine(df::coord pos) return engine; } +/* + * Configuration management + */ + static void clear_engines() { for (auto it = engines.begin(); it != engines.end(); ++it) delete it->second; engines.clear(); coord_engines.clear(); - recheck_piles.clear(); } static void load_engines() @@ -316,14 +319,32 @@ static void load_engines() pworld->DeletePersistentData(*it); continue;; } - auto plinks = pile->getStockpileLinks(); - if (!plinks) - continue; engine->stockpiles.insert(it->ival(1)); + } + + pworld->GetPersistentData(&vec, "siege-engine/profiles/", true); + for (auto it = vec.begin(); it != vec.end(); ++it) + { + auto engine = find_engine(df::building::find(it->ival(0)), true); + if (!engine) continue; + engine->profile.min_level = it->ival(1); + engine->profile.max_level = it->ival(2); + } - insert_into_vector(engine->links.take_from_pile, &df::building::id, pile); - insert_into_vector(plinks->give_to_workshop, &df::building::id, (df::building*)engine->bld); + pworld->GetPersistentData(&vec, "siege-engine/profile-workers/", true); + for (auto it = vec.begin(); it != vec.end(); ++it) + { + auto engine = find_engine(df::building::find(it->ival(0)), true); + if (!engine) + continue; + auto unit = df::unit::find(it->ival(1)); + if (!unit || !Units::isCitizen(unit)) + { + pworld->DeletePersistentData(*it); + continue; + } + engine->profile.permitted_workers.push_back(it->ival(1)); } } @@ -437,21 +458,47 @@ static int setAmmoItem(lua_State *L) return 1; } +static void forgetStockpileLink(EngineInfo *engine, int pile_id) +{ + engine->stockpiles.erase(pile_id); + + auto pworld = Core::getInstance().getWorld(); + auto key = stl_sprintf("siege-engine/stockpiles/%d/%d", engine->id, pile_id); + pworld->DeletePersistentData(pworld->GetPersistentData(key)); +} + +static void update_stockpile_links(EngineInfo *engine) +{ + engine->links.take_from_pile.clear(); + + for (auto it = engine->stockpiles.begin(); it != engine->stockpiles.end(); ) + { + int id = *it; ++it; + auto pile = df::building::find(id); + + if (!pile || pile->getType() != building_type::Stockpile) + forgetStockpileLink(engine, id); + else + // The vector is sorted, but we are iterating through a sorted set + engine->links.take_from_pile.push_back(pile); + } +} + static int getStockpileLinks(lua_State *L) { auto engine = find_engine(L, 1, false, true); if (!engine || engine->stockpiles.empty()) return 0; - int idx = 1; - lua_createtable(L, engine->stockpiles.size(), 0); + update_stockpile_links(engine); + + auto &links = engine->links.take_from_pile; + lua_createtable(L, links.size(), 0); - for (auto it = engine->stockpiles.begin(); it != engine->stockpiles.end(); ++it) + for (size_t i = 0; i < links.size(); i++) { - auto pile = df::building::find(*it); - if (!pile) continue; - Lua::Push(L, pile); - lua_rawseti(L, -2, idx++); + Lua::Push(L, links[i]); + lua_rawseti(L, -2, i+1); } return 1; @@ -472,9 +519,6 @@ static bool addStockpileLink(df::building_siegeenginest *bld, df::building_stock CHECK_NULL_POINTER(bld); CHECK_NULL_POINTER(pile); - auto plinks = pile->getStockpileLinks(); - CHECK_NULL_POINTER(plinks); - if (!enable_plugin()) return false; @@ -490,21 +534,9 @@ static bool addStockpileLink(df::building_siegeenginest *bld, df::building_stock entry.ival(1) = pile->id; engine->stockpiles.insert(pile->id); - - insert_into_vector(engine->links.take_from_pile, &df::building::id, (df::building*)pile); - insert_into_vector(plinks->give_to_workshop, &df::building::id, (df::building*)engine->bld); return true; } -static void forgetStockpileLink(EngineInfo *engine, int pile_id) -{ - engine->stockpiles.erase(pile_id); - - auto pworld = Core::getInstance().getWorld(); - auto key = stl_sprintf("siege-engine/stockpiles/%d/%d", engine->id, pile_id); - pworld->DeletePersistentData(pworld->GetPersistentData(key)); -} - static bool removeStockpileLink(df::building_siegeenginest *bld, df::building_stockpilest *pile) { CHECK_NULL_POINTER(bld); @@ -513,45 +545,56 @@ static bool removeStockpileLink(df::building_siegeenginest *bld, df::building_st if (auto engine = find_engine(bld)) { forgetStockpileLink(engine, pile->id); - - auto plinks = pile->getStockpileLinks(); - erase_from_vector(engine->links.take_from_pile, &df::building::id, pile->id); - erase_from_vector(plinks->give_to_workshop, &df::building::id, bld->id); return true; } return false; } -static void recheck_pile_links(color_ostream &out, EngineInfo *engine) +static df::workshop_profile *saveWorkshopProfile(df::building_siegeenginest *bld) { - auto removed = engine->stockpiles; + CHECK_NULL_POINTER(bld); - out.print("rechecking piles in %d\n", engine->id); + if (!enable_plugin()) + return NULL; - // Detect and save changes in take links - for (size_t i = 0; i < engine->links.take_from_pile.size(); i++) - { - auto pile = engine->links.take_from_pile[i]; + // Save skill limits + auto pworld = Core::getInstance().getWorld(); + auto key = stl_sprintf("siege-engine/profiles/%d", bld->id); + auto entry = pworld->GetPersistentData(key, NULL); + if (!entry.isValid()) + return NULL; + + auto engine = find_engine(bld, true); - removed.erase(pile->id); + entry.ival(0) = engine->id; + entry.ival(1) = engine->profile.min_level; + entry.ival(2) = engine->profile.max_level; - if (!engine->stockpiles.count(pile->id)) - addStockpileLink(engine->bld, (df::building_stockpilest*)pile); - } + // Save worker list + std::vector<PersistentDataItem> vec; + auto &workers = engine->profile.permitted_workers; + + key = stl_sprintf("siege-engine/profile-workers/%d", bld->id); + pworld->GetPersistentData(&vec, key, true); - for (auto it = removed.begin(); it != removed.end(); it++) - forgetStockpileLink(engine, *it); + for (auto it = vec.begin(); it != vec.end(); ++it) + { + if (linear_index(workers, it->ival(1)) < 0) + pworld->DeletePersistentData(*it); + } - // Remove give links - for (size_t i = 0; i < engine->links.give_to_pile.size(); i++) + for (size_t i = 0; i < workers.size(); i++) { - auto pile = engine->links.give_to_pile[i]; - auto plinks = pile->getStockpileLinks(); - erase_from_vector(plinks->take_from_workshop, &df::building::id, engine->id); + key = stl_sprintf("siege-engine/profile-workers/%d/%d", bld->id, workers[i]); + entry = pworld->GetPersistentData(key, NULL); + if (!entry.isValid()) + continue; + entry.ival(0) = engine->id; + entry.ival(1) = workers[i]; } - engine->links.give_to_pile.clear(); + return &engine->profile; } static int getOperatorSkill(df::building_siegeenginest *bld, bool force = false) @@ -585,7 +628,7 @@ static int getOperatorSkill(df::building_siegeenginest *bld, bool force = false) } /* - * Trajectory + * Trajectory raytracing */ struct ProjectilePath { @@ -1396,19 +1439,19 @@ IMPLEMENT_VMETHOD_INTERPOSE(projectile_hook, checkImpact); struct building_hook : df::building_siegeenginest { typedef df::building_siegeenginest interpose_base; - DEFINE_VMETHOD_INTERPOSE(bool, canLinkToStockpile, ()) + DEFINE_VMETHOD_INTERPOSE(df::workshop_profile*, getWorkshopProfile, ()) { - if (find_engine(this, true)) - return true; + if (auto engine = find_engine(this)) + return &engine->profile; - return INTERPOSE_NEXT(canLinkToStockpile)(); + return INTERPOSE_NEXT(getWorkshopProfile)(); } DEFINE_VMETHOD_INTERPOSE(df::stockpile_links*, getStockpileLinks, ()) { if (auto engine = find_engine(this)) { - recheck_piles.insert(this); + update_stockpile_links(engine); return &engine->links; } @@ -1476,7 +1519,7 @@ struct building_hook : df::building_siegeenginest { } }; -IMPLEMENT_VMETHOD_INTERPOSE(building_hook, canLinkToStockpile); +IMPLEMENT_VMETHOD_INTERPOSE(building_hook, getWorkshopProfile); IMPLEMENT_VMETHOD_INTERPOSE(building_hook, getStockpileLinks); IMPLEMENT_VMETHOD_INTERPOSE(building_hook, updateAction); @@ -1490,6 +1533,7 @@ DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_LUA_FUNCTION(isLinkedToPile), DFHACK_LUA_FUNCTION(addStockpileLink), DFHACK_LUA_FUNCTION(removeStockpileLink), + DFHACK_LUA_FUNCTION(saveWorkshopProfile), DFHACK_LUA_FUNCTION(getTileStatus), DFHACK_LUA_FUNCTION(paintAimScreen), DFHACK_LUA_FUNCTION(canTargetUnit), @@ -1522,7 +1566,7 @@ static void enable_hooks(bool enable) INTERPOSE_HOOK(projectile_hook, checkMovement).apply(enable); INTERPOSE_HOOK(projectile_hook, checkImpact).apply(enable); - INTERPOSE_HOOK(building_hook, canLinkToStockpile).apply(enable); + INTERPOSE_HOOK(building_hook, getWorkshopProfile).apply(enable); INTERPOSE_HOOK(building_hook, getStockpileLinks).apply(enable); INTERPOSE_HOOK(building_hook, updateAction).apply(enable); @@ -1555,15 +1599,6 @@ static void clear_caches(color_ostream &out) UnitPath::cache.clear(); } - - if (!recheck_piles.empty()) - { - for (auto it = recheck_piles.begin(); it != recheck_piles.end(); ++it) - if (auto engine = find_engine(*it)) - recheck_pile_links(out, engine); - - recheck_piles.clear(); - } } DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) diff --git a/scripts/gui/siege-engine.lua b/scripts/gui/siege-engine.lua index 716dc89b..47043cbb 100644 --- a/scripts/gui/siege-engine.lua +++ b/scripts/gui/siege-engine.lua @@ -8,6 +8,8 @@ local dlg = require 'gui.dialogs' local plugin = require 'plugins.siege-engine' local wmap = df.global.world.map +local LEGENDARY = df.skill_rating.Legendary + -- Globals kept between script calls last_target_min = last_target_min or nil last_target_max = last_target_max or nil @@ -64,7 +66,10 @@ function SiegeEngine:onShow() end function SiegeEngine:onDestroy() - if self.building then + if self.save_profile then + plugin.saveWorkshopProfile(self.building) + end + if not self.no_select_building then self:selectBuilding(self.building, self.old_cursor, self.old_viewport, 10) end end @@ -221,12 +226,20 @@ function SiegeEngine:onRenderBody_main(dc) dc:newline():newline(1) dc:string("t",COLOR_LIGHTGREEN):string(": Take from stockpile"):newline(3) local links = plugin.getStockpileLinks(self.building) + local bottom = dc.height - 5 if links then dc:string("d",COLOR_LIGHTGREEN):string(": Delete, ") dc:string("o",COLOR_LIGHTGREEN):string(": Zoom"):newline() - self:renderStockpiles(dc, links, 19-dc:localY()) + self:renderStockpiles(dc, links, bottom-2-dc:localY()) + dc:newline():newline() end + local prof = self.building:getWorkshopProfile() or {} + dc:seek(1,math.max(dc:localY(),19)):string('ghjk',COLOR_LIGHTGREEN)dc:string(': ') + dc:string(df.skill_rating.attrs[prof.min_level or 0].caption):string('-') + dc:string(df.skill_rating.attrs[math.min(LEGENDARY,prof.max_level or 3000)].caption) + dc:newline():newline() + if self.target_select_first then self:renderTargetView(self.target_select_first, guidm.getCursorPos()) else @@ -295,6 +308,23 @@ function SiegeEngine:onInput_main(keys) self.mode = self.mode_pile self:sendInputToParent('CURSOR_DOWN_Z') self:sendInputToParent('CURSOR_UP_Z') + elseif keys.CUSTOM_G then + local prof = plugin.saveWorkshopProfile(self.building) + prof.min_level = math.max(0, prof.min_level-1) + plugin.saveWorkshopProfile(self.building) + elseif keys.CUSTOM_H then + local prof = plugin.saveWorkshopProfile(self.building) + prof.min_level = math.min(LEGENDARY, prof.min_level+1) + plugin.saveWorkshopProfile(self.building) + elseif keys.CUSTOM_J then + local prof = plugin.saveWorkshopProfile(self.building) + prof.max_level = math.max(0, math.min(LEGENDARY,prof.max_level)-1) + plugin.saveWorkshopProfile(self.building) + elseif keys.CUSTOM_K then + local prof = plugin.saveWorkshopProfile(self.building) + prof.max_level = math.min(LEGENDARY, prof.max_level+1) + if prof.max_level >= LEGENDARY then prof.max_level = 3000 end + plugin.saveWorkshopProfile(self.building) elseif self:simulateViewScroll(keys) then self.cursor = nil else @@ -439,7 +469,7 @@ function SiegeEngine:onInput(keys) self:dismiss() elseif keys.LEAVESCREEN_ALL then self:dismiss() - self.building = nil + self.no_select_building = true guidm.clearCursorPos() df.global.ui.main.mode = df.ui_sidebar_mode.Default df.global.world.selected_building = nil |
