diff options
| author | Alexander Gavrilov | 2012-09-11 22:46:17 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-09-11 22:46:17 +0400 |
| commit | b0938d7e0d80720ef1a6fd264418ba20c375d9ba (patch) | |
| tree | d11f0016953eacaad629b0c60b6c0fc81b8ab4b2 /plugins/devel | |
| parent | 3a075f4bc716550e0a621a2db40cfa578db1d0fa (diff) | |
| download | dfhack-b0938d7e0d80720ef1a6fd264418ba20c375d9ba.tar.gz dfhack-b0938d7e0d80720ef1a6fd264418ba20c375d9ba.tar.bz2 dfhack-b0938d7e0d80720ef1a6fd264418ba20c375d9ba.tar.xz | |
Allow specifying arbitrary items to use in catapults.
Diffstat (limited to 'plugins/devel')
| -rw-r--r-- | plugins/devel/siege-engine.cpp | 151 |
1 files changed, 148 insertions, 3 deletions
diff --git a/plugins/devel/siege-engine.cpp b/plugins/devel/siege-engine.cpp index ce835c6d..2720c62f 100644 --- a/plugins/devel/siege-engine.cpp +++ b/plugins/devel/siege-engine.cpp @@ -8,6 +8,7 @@ #include <modules/Maps.h> #include <modules/World.h> #include <modules/Units.h> +#include <modules/Job.h> #include <LuaTools.h> #include <TileTypes.h> #include <vector> @@ -41,6 +42,10 @@ #include "df/assumed_identity.h" #include "df/game_mode.h" #include "df/unit_misc_trait.h" +#include "df/job.h" +#include "df/job_item.h" +#include "df/item.h" +#include "df/items_other_id.h" #include "MiscUtils.h" @@ -148,6 +153,11 @@ struct EngineInfo { coord_range target; + df::job_item_vector_id ammo_vector_id; + df::item_type ammo_item_type; + + int operator_id, operator_frame; + bool hasTarget() { return is_range_valid(target); } bool onTarget(df::coord pos) { return is_in_range(target, pos); } df::coord getTargetSize() { return target.second - target.first; } @@ -190,6 +200,11 @@ static EngineInfo *find_engine(df::building *bld, bool create = false) obj->hit_delay = 3; obj->fire_range = get_engine_range(ebld); + obj->ammo_vector_id = job_item_vector_id::BOULDER; + obj->ammo_item_type = item_type::BOULDER; + + obj->operator_id = obj->operator_frame = -1; + coord_engines[obj->center] = bld; return obj; } @@ -198,7 +213,7 @@ static EngineInfo *find_engine(lua_State *L, int idx, bool create = false) { auto bld = Lua::CheckDFObject<df::building_siegeenginest>(L, idx); - auto engine = find_engine(bld); + auto engine = find_engine(bld, create); if (!engine) luaL_error(L, "no such engine"); @@ -243,6 +258,15 @@ static void load_engines() engine->target.first = df::coord(it->ival(1), it->ival(2), it->ival(3)); engine->target.second = df::coord(it->ival(4), it->ival(5), it->ival(6)); } + + pworld->GetPersistentData(&vec, "siege-engine/ammo/", 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->ammo_vector_id = (df::job_item_vector_id)it->ival(1); + engine->ammo_item_type = (df::item_type)it->ival(2); + } } static int getTargetArea(lua_State *L) @@ -309,6 +333,51 @@ static bool setTargetArea(df::building_siegeenginest *bld, df::coord target_min, return true; } +static int getAmmoItem(lua_State *L) +{ + auto engine = find_engine(L, 1, true); + Lua::Push(L, engine->ammo_item_type); + return 1; +} + +static int setAmmoItem(lua_State *L) +{ + auto engine = find_engine(L, 1, true); + auto item_type = (df::item_type)luaL_optint(L, 2, item_type::BOULDER); + if (!is_valid_enum_item(item_type)) + luaL_argerror(L, 2, "invalid item type"); + + if (!enable_plugin()) + return 0; + + auto pworld = Core::getInstance().getWorld(); + auto key = stl_sprintf("siege-engine/ammo/%d", engine->id); + auto entry = pworld->GetPersistentData(key, NULL); + if (!entry.isValid()) + return 0; + + engine->ammo_vector_id = job_item_vector_id::ANY_FREE; + engine->ammo_item_type = item_type; + + FOR_ENUM_ITEMS(job_item_vector_id, id) + { + auto other = ENUM_ATTR(job_item_vector_id, other, id); + auto type = ENUM_ATTR(items_other_id, item, other); + if (type == item_type) + { + engine->ammo_vector_id = id; + break; + } + } + + entry.ival(0) = engine->id; + entry.ival(1) = engine->ammo_vector_id; + entry.ival(2) = engine->ammo_item_type; + + lua_pushboolean(L, true); + return 1; +} + static int getShotSkill(df::building_siegeenginest *bld) { CHECK_NULL_POINTER(bld); @@ -446,7 +515,7 @@ static bool adjustToTarget(EngineInfo *engine, df::coord *pos) return true; for (df::coord fudge = *pos; - fudge.z < engine->target.second.z; fudge.z++) + fudge.z <= engine->target.second.z; fudge.z++) { if (!isTargetableTile(fudge)) continue; @@ -455,7 +524,7 @@ static bool adjustToTarget(EngineInfo *engine, df::coord *pos) } for (df::coord fudge = *pos; - fudge.z > engine->target.first.z; fudge.z--) + fudge.z >= engine->target.first.z; fudge.z--) { if (!isTargetableTile(fudge)) continue; @@ -1047,6 +1116,79 @@ struct projectile_hook : df::proj_itemst { IMPLEMENT_VMETHOD_INTERPOSE(projectile_hook, checkMovement); /* + * Building hook + */ + +struct building_hook : df::building_siegeenginest { + typedef df::building_siegeenginest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, updateAction, ()) + { + INTERPOSE_NEXT(updateAction)(); + + if (jobs.empty()) + return; + + if (auto engine = find_engine(this)) + { + auto job = jobs[0]; + + switch (job->job_type) + { + case job_type::LoadCatapult: + if (!job->job_items.empty()) + { + auto item = job->job_items[0]; + item->item_type = engine->ammo_item_type; + item->vector_id = engine->ammo_vector_id; + + switch (item->item_type) + { + case item_type::NONE: + case item_type::BOULDER: + case item_type::BLOCKS: + item->mat_type = 0; + break; + + case item_type::BIN: + case item_type::BARREL: + item->mat_type = -1; + // A hack to make it take objects assigned to stockpiles. + // Since reaction_id is not set, the actual value is not used. + item->contains.resize(1); + break; + + default: + item->mat_type = -1; + break; + } + } + break; + + case job_type::FireCatapult: + case job_type::FireBallista: + if (auto worker = Job::getWorker(job)) + { + color_ostream_proxy out(Core::getInstance().getConsole()); + out.print("operator %d\n", worker->id); + + engine->operator_id = worker->id; + engine->operator_frame = world->frame_counter; + } + else + engine->operator_id = -1; + break; + + default: + break; + } + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(building_hook, updateAction); + +/* * Initialization */ @@ -1064,6 +1206,8 @@ DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_PLUGIN_LUA_COMMANDS { DFHACK_LUA_COMMAND(getTargetArea), + DFHACK_LUA_COMMAND(getAmmoItem), + DFHACK_LUA_COMMAND(setAmmoItem), DFHACK_LUA_COMMAND(projPosAtStep), DFHACK_LUA_COMMAND(projPathMetrics), DFHACK_LUA_COMMAND(adjustToTarget), @@ -1080,6 +1224,7 @@ static void enable_hooks(bool enable) is_enabled = enable; INTERPOSE_HOOK(projectile_hook, checkMovement).apply(enable); + INTERPOSE_HOOK(building_hook, updateAction).apply(enable); if (enable) load_engines(); |
