summaryrefslogtreecommitdiff
path: root/plugins/devel
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-09-11 22:46:17 +0400
committerAlexander Gavrilov2012-09-11 22:46:17 +0400
commitb0938d7e0d80720ef1a6fd264418ba20c375d9ba (patch)
treed11f0016953eacaad629b0c60b6c0fc81b8ab4b2 /plugins/devel
parent3a075f4bc716550e0a621a2db40cfa578db1d0fa (diff)
downloaddfhack-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.cpp151
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();