summaryrefslogtreecommitdiff
path: root/plugins/devel
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-09-08 13:46:02 +0400
committerAlexander Gavrilov2012-09-08 13:46:02 +0400
commitbfa6ed3e0868c7a2fa9851c3feb8f9055b0330bb (patch)
tree13da84ac921e3e607f8908c0816783598cd13a07 /plugins/devel
parent325e294af2bbd2ba0381a476756eddbbfceb1b36 (diff)
downloaddfhack-bfa6ed3e0868c7a2fa9851c3feb8f9055b0330bb.tar.gz
dfhack-bfa6ed3e0868c7a2fa9851c3feb8f9055b0330bb.tar.bz2
dfhack-bfa6ed3e0868c7a2fa9851c3feb8f9055b0330bb.tar.xz
Support setting the target area for the siege engine.
Diffstat (limited to 'plugins/devel')
-rw-r--r--plugins/devel/siege-engine.cpp160
1 files changed, 108 insertions, 52 deletions
diff --git a/plugins/devel/siege-engine.cpp b/plugins/devel/siege-engine.cpp
index 189c43ad..6906f540 100644
--- a/plugins/devel/siege-engine.cpp
+++ b/plugins/devel/siege-engine.cpp
@@ -48,6 +48,65 @@ using Screen::Pen;
DFHACK_PLUGIN("siege-engine");
/*
+ * Misc. utils
+ */
+
+typedef std::pair<df::coord, df::coord> coord_range;
+
+static void set_range(coord_range *target, df::coord p1, df::coord p2)
+{
+ if (!p1.isValid() || !p2.isValid())
+ {
+ *target = coord_range();
+ }
+ else
+ {
+ target->first.x = std::min(p1.x, p2.x);
+ target->first.y = std::min(p1.y, p2.y);
+ target->first.z = std::min(p1.z, p2.z);
+ target->second.x = std::max(p1.x, p2.x);
+ target->second.y = std::max(p1.y, p2.y);
+ target->second.z = std::max(p1.z, p2.z);
+ }
+}
+
+static bool is_range_valid(const coord_range &target)
+{
+ return target.first.isValid() && target.second.isValid();
+}
+
+static bool is_in_range(const coord_range &target, df::coord pos)
+{
+ return target.first.isValid() && target.second.isValid() &&
+ target.first.x <= pos.x && pos.x <= target.second.x &&
+ target.first.y <= pos.y && pos.y <= target.second.y &&
+ target.first.z <= pos.z && pos.z <= target.second.z;
+}
+
+static std::pair<int, int> get_engine_range(df::building_siegeenginest *bld)
+{
+ if (bld->type == siegeengine_type::Ballista)
+ return std::make_pair(0, 200);
+ else
+ return std::make_pair(30, 100);
+}
+
+static void orient_engine(df::building_siegeenginest *bld, df::coord target)
+{
+ int dx = target.x - bld->centerx;
+ int dy = target.y - bld->centery;
+
+ if (abs(dx) > abs(dy))
+ bld->facing = (dx > 0) ?
+ df::building_siegeenginest::Right :
+ df::building_siegeenginest::Left;
+ else
+ bld->facing = (dy > 0) ?
+ df::building_siegeenginest::Down :
+ df::building_siegeenginest::Up;
+}
+
+/*
* Configuration management
*/
@@ -55,17 +114,10 @@ static bool enable_plugin();
struct EngineInfo {
int id;
- df::coord target_min, target_max;
+ coord_range target;
- bool hasTarget() {
- return target_min.isValid() && target_max.isValid();
- }
- bool onTarget(df::coord pos) {
- return hasTarget() &&
- target_min.x <= pos.x && pos.x <= target_max.x &&
- target_min.y <= pos.y && pos.y <= target_max.y &&
- target_min.z <= pos.z && pos.z <= target_max.z;
- }
+ bool hasTarget() { return is_range_valid(target); }
+ bool onTarget(df::coord pos) { return is_in_range(target, pos); }
};
static std::map<df::building*, EngineInfo> engines;
@@ -98,8 +150,8 @@ static void load_engines()
{
auto engine = find_engine(df::building::find(it->ival(0)), true);
if (!engine) continue;
- engine->target_min = df::coord(it->ival(1), it->ival(2), it->ival(3));
- engine->target_max = df::coord(it->ival(4), it->ival(5), it->ival(6));
+ 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));
}
}
@@ -109,10 +161,10 @@ static int getTargetArea(lua_State *L)
if (!bld) luaL_argerror(L, 1, "null building");
auto engine = find_engine(bld);
- if (engine && engine->target_min.isValid())
+ if (engine && engine->hasTarget())
{
- Lua::Push(L, engine->target_min);
- Lua::Push(L, engine->target_max);
+ Lua::Push(L, engine->target.first);
+ Lua::Push(L, engine->target.second);
}
else
{
@@ -128,7 +180,7 @@ static void clearTargetArea(df::building_siegeenginest *bld)
CHECK_NULL_POINTER(bld);
if (auto engine = find_engine(bld))
- engine->target_min = engine->target_max = df::coord();
+ engine->target = coord_range();
auto pworld = Core::getInstance().getWorld();
auto key = stl_sprintf("siege-engine/target/%d", bld->id);
@@ -151,13 +203,18 @@ static bool setTargetArea(df::building_siegeenginest *bld, df::coord target_min,
auto engine = find_engine(bld, true);
+ set_range(&engine->target, target_min, target_max);
+
entry.ival(0) = bld->id;
- entry.ival(1) = engine->target_min.x = std::min(target_min.x, target_max.x);
- entry.ival(2) = engine->target_min.y = std::min(target_min.y, target_max.y);
- entry.ival(3) = engine->target_min.z = std::min(target_min.z, target_max.z);
- entry.ival(4) = engine->target_max.x = std::max(target_min.x, target_max.x);
- entry.ival(5) = engine->target_max.y = std::max(target_min.y, target_max.y);
- entry.ival(6) = engine->target_max.z = std::max(target_min.z, target_max.z);
+ entry.ival(1) = engine->target.first.x;
+ entry.ival(2) = engine->target.first.y;
+ entry.ival(3) = engine->target.first.z;
+ entry.ival(4) = engine->target.second.x;
+ entry.ival(5) = engine->target.second.y;
+ entry.ival(6) = engine->target.second.z;
+
+ df::coord sum = target_min + target_max;
+ orient_engine(bld, df::coord(sum.x/2, sum.y/2, sum.z/2));
return true;
}
@@ -267,38 +324,45 @@ struct PathMetrics {
}
};
-void paintAimScreen(df::building_siegeenginest *bld, df::coord view, df::coord2d ltop, df::coord2d size)
+static std::string getTileStatus(df::building_siegeenginest *bld, df::coord tile_pos)
{
- CHECK_NULL_POINTER(bld);
+ df::coord origin(bld->centerx, bld->centery, bld->z);
+ auto fire_range = get_engine_range(bld);
- df::coord origin = df::coord(bld->centerx, bld->centery, bld->z);
+ ProjectilePath path(origin, tile_pos);
+ PathMetrics raytrace(path, tile_pos);
- auto engine = find_engine(bld);
- int min_distance, max_distance;
-
- if (bld->type == siegeengine_type::Ballista)
+ if (raytrace.hits())
{
- min_distance = 0;
- max_distance = 200;
+ if (raytrace.goal_step >= fire_range.first &&
+ raytrace.goal_step <= fire_range.second)
+ return "ok";
+ else
+ return "out_of_range";
}
else
- {
- min_distance = 30;
- max_distance = 100;
- }
+ return "blocked";
+}
+
+static void paintAimScreen(df::building_siegeenginest *bld, df::coord view, df::coord2d ltop, df::coord2d size)
+{
+ CHECK_NULL_POINTER(bld);
- df::coord cursor = Gui::getCursorPos();
+ df::coord origin(bld->centerx, bld->centery, bld->z);
+ coord_range building_rect(
+ df::coord(bld->x1, bld->y1, bld->z),
+ df::coord(bld->x2, bld->y2, bld->z)
+ );
+
+ auto engine = find_engine(bld);
+ auto fire_range = get_engine_range(bld);
for (int x = 0; x < size.x; x++)
{
for (int y = 0; y < size.y; y++)
{
df::coord tile_pos = view + df::coord(x,y,0);
- if (tile_pos == cursor)
- continue;
- if (tile_pos.z == bld->z &&
- tile_pos.x >= bld->x1 && tile_pos.x <= bld->x2 &&
- tile_pos.y >= bld->y1 && tile_pos.y <= bld->y2)
+ if (is_in_range(building_rect, tile_pos))
continue;
Pen cur_tile = Screen::readTile(ltop.x+x, ltop.y+y);
@@ -306,22 +370,13 @@ void paintAimScreen(df::building_siegeenginest *bld, df::coord view, df::coord2d
continue;
ProjectilePath path(origin, tile_pos);
-
- if (path.speed.z != 0 && abs(path.speed.z) != path.divisor) {
- path.divisor *= 20;
- path.speed.x *= 20;
- path.speed.y *= 20;
- path.speed.z *= 20;
- path.speed.z += 9;
- }
-
PathMetrics raytrace(path, tile_pos);
int color;
if (raytrace.hits())
{
- if (raytrace.goal_step >= min_distance &&
- raytrace.goal_step <= max_distance)
+ if (raytrace.goal_step >= fire_range.first &&
+ raytrace.goal_step <= fire_range.second)
color = COLOR_GREEN;
else
color = COLOR_CYAN;
@@ -357,6 +412,7 @@ void paintAimScreen(df::building_siegeenginest *bld, df::coord view, df::coord2d
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(clearTargetArea),
DFHACK_LUA_FUNCTION(setTargetArea),
+ DFHACK_LUA_FUNCTION(getTileStatus),
DFHACK_LUA_FUNCTION(paintAimScreen),
DFHACK_LUA_END
};