summaryrefslogtreecommitdiff
path: root/plugins/devel
diff options
context:
space:
mode:
authorKelly Martin2012-09-16 16:37:08 -0500
committerKelly Martin2012-09-16 16:37:08 -0500
commit847dadd3f530ab44172b0b18a73a32b76bcbd323 (patch)
tree1c0b55a0df42ad1b0049aef02f8ed276dbb6dca3 /plugins/devel
parent38f920dd658ba32dbe5126654b21f776386f07d5 (diff)
parent000e3baf27e3d811e673bca08e4381c1f2c632b7 (diff)
downloaddfhack-847dadd3f530ab44172b0b18a73a32b76bcbd323.tar.gz
dfhack-847dadd3f530ab44172b0b18a73a32b76bcbd323.tar.bz2
dfhack-847dadd3f530ab44172b0b18a73a32b76bcbd323.tar.xz
Merge remote-tracking branch 'angavrilov/master'
Diffstat (limited to 'plugins/devel')
-rw-r--r--plugins/devel/dumpmats.cpp53
-rw-r--r--plugins/devel/siege-engine.cpp172
2 files changed, 170 insertions, 55 deletions
diff --git a/plugins/devel/dumpmats.cpp b/plugins/devel/dumpmats.cpp
index ba888e7c..0af1fce5 100644
--- a/plugins/devel/dumpmats.cpp
+++ b/plugins/devel/dumpmats.cpp
@@ -11,6 +11,7 @@
#include "df/matter_state.h"
#include "df/descriptor_color.h"
#include "df/item_type.h"
+#include "df/strain_type.h"
using std::string;
using std::vector;
@@ -195,47 +196,17 @@ command_result df_dumpmats (color_ostream &out, vector<string> &parameters)
if (mat->molar_mass != 0xFBBC7818)
out.print("\t[MOLAR_MASS:%i]\n", mat->molar_mass);
- if (mat->strength.impact_yield != 10000)
- out.print("\t[IMPACT_YIELD:%i]\n", mat->strength.impact_yield);
- if (mat->strength.impact_fracture != 10000)
- out.print("\t[IMPACT_FRACTURE:%i]\n", mat->strength.impact_fracture);
- if (mat->strength.impact_strain_at_yield != 0)
- out.print("\t[IMPACT_STRAIN_AT_YIELD:%i]\n", mat->strength.impact_strain_at_yield);
-
- if (mat->strength.compressive_yield != 10000)
- out.print("\t[COMPRESSIVE_YIELD:%i]\n", mat->strength.compressive_yield);
- if (mat->strength.compressive_fracture != 10000)
- out.print("\t[COMPRESSIVE_FRACTURE:%i]\n", mat->strength.compressive_fracture);
- if (mat->strength.compressive_strain_at_yield != 0)
- out.print("\t[COMPRESSIVE_STRAIN_AT_YIELD:%i]\n", mat->strength.compressive_strain_at_yield);
-
- if (mat->strength.tensile_yield != 10000)
- out.print("\t[TENSILE_YIELD:%i]\n", mat->strength.tensile_yield);
- if (mat->strength.tensile_fracture != 10000)
- out.print("\t[TENSILE_FRACTURE:%i]\n", mat->strength.tensile_fracture);
- if (mat->strength.tensile_strain_at_yield != 0)
- out.print("\t[TENSILE_STRAIN_AT_YIELD:%i]\n", mat->strength.tensile_strain_at_yield);
-
- if (mat->strength.torsion_yield != 10000)
- out.print("\t[TORSION_YIELD:%i]\n", mat->strength.torsion_yield);
- if (mat->strength.torsion_fracture != 10000)
- out.print("\t[TORSION_FRACTURE:%i]\n", mat->strength.torsion_fracture);
- if (mat->strength.torsion_strain_at_yield != 0)
- out.print("\t[TORSION_STRAIN_AT_YIELD:%i]\n", mat->strength.torsion_strain_at_yield);
-
- if (mat->strength.shear_yield != 10000)
- out.print("\t[SHEAR_YIELD:%i]\n", mat->strength.shear_yield);
- if (mat->strength.shear_fracture != 10000)
- out.print("\t[SHEAR_FRACTURE:%i]\n", mat->strength.shear_fracture);
- if (mat->strength.shear_strain_at_yield != 0)
- out.print("\t[SHEAR_STRAIN_AT_YIELD:%i]\n", mat->strength.shear_strain_at_yield);
-
- if (mat->strength.bending_yield != 10000)
- out.print("\t[BENDING_YIELD:%i]\n", mat->strength.bending_yield);
- if (mat->strength.bending_fracture != 10000)
- out.print("\t[BENDING_FRACTURE:%i]\n", mat->strength.bending_fracture);
- if (mat->strength.bending_strain_at_yield != 0)
- out.print("\t[BENDING_STRAIN_AT_YIELD:%i]\n", mat->strength.bending_strain_at_yield);
+ FOR_ENUM_ITEMS(strain_type, strain)
+ {
+ auto name = ENUM_KEY_STR(strain_type,strain);
+
+ if (mat->strength.yield[strain] != 10000)
+ out.print("\t[%s_YIELD:%i]\n", name.c_str(), mat->strength.yield[strain]);
+ if (mat->strength.fracture[strain] != 10000)
+ out.print("\t[%s_FRACTURE:%i]\n", name.c_str(), mat->strength.fracture[strain]);
+ if (mat->strength.strain_at_yield[strain] != 0)
+ out.print("\t[%s_STRAIN_AT_YIELD:%i]\n", name.c_str(), mat->strength.strain_at_yield[strain]);
+ }
if (mat->strength.max_edge != 0)
out.print("\t[MAX_EDGE:%i]\n", mat->strength.max_edge);
diff --git a/plugins/devel/siege-engine.cpp b/plugins/devel/siege-engine.cpp
index a41bfe5f..b8a2f087 100644
--- a/plugins/devel/siege-engine.cpp
+++ b/plugins/devel/siege-engine.cpp
@@ -10,6 +10,7 @@
#include <modules/World.h>
#include <modules/Units.h>
#include <modules/Job.h>
+#include <modules/Materials.h>
#include <LuaTools.h>
#include <TileTypes.h>
#include <vector>
@@ -45,11 +46,14 @@
#include "df/unit_misc_trait.h"
#include "df/job.h"
#include "df/job_item.h"
-#include "df/item.h"
+#include "df/item_actual.h"
#include "df/items_other_id.h"
#include "df/building_stockpilest.h"
#include "df/stockpile_links.h"
#include "df/workshop_profile.h"
+#include "df/strain_type.h"
+#include "df/material.h"
+#include "df/flow_type.h"
#include "MiscUtils.h"
@@ -162,6 +166,63 @@ static void random_direction(float &x, float &y, float &z)
z = 1.0f - 2.0f*d;
}
+static const int WEAR_TICKS = 806400;
+
+static bool apply_impact_damage(df::item *item, int minv, int maxv)
+{
+ MaterialInfo info(item);
+ if (!info.isValid())
+ {
+ item->setWear(3);
+ return false;
+ }
+
+ auto &strength = info.material->strength;
+
+ // Use random strain type excluding COMPRESSIVE (conveniently last)
+ int type = random_int(strain_type::COMPRESSIVE);
+ int power = minv + random_int(maxv-minv+1);
+
+ // High elasticity materials just bend
+ if (strength.strain_at_yield[type] >= 5000)
+ return true;
+
+ // Instant fracture?
+ int fracture = strength.fracture[type];
+ if (fracture <= power)
+ {
+ item->setWear(3);
+ return false;
+ }
+
+ // Impact within elastic strain range?
+ int yield = strength.yield[type];
+ if (yield > power)
+ return true;
+
+ // Can wear?
+ auto actual = virtual_cast<df::item_actual>(item);
+ if (!actual)
+ return false;
+
+ // Transform plastic deformation to wear
+ int max_wear = WEAR_TICKS * 4;
+ int cur_wear = WEAR_TICKS * actual->wear + actual->wear_timer;
+ cur_wear += int64_t(power - yield)*max_wear/(fracture - yield);
+
+ if (cur_wear >= max_wear)
+ {
+ actual->wear = 3;
+ return false;
+ }
+ else
+ {
+ actual->wear = cur_wear / WEAR_TICKS;
+ actual->wear_timer = cur_wear % WEAR_TICKS;
+ return true;
+ }
+}
+
/*
* Configuration object
*/
@@ -1225,6 +1286,12 @@ static int proposeUnitHits(lua_State *L)
* Projectile hook
*/
+static const int offsets[8][2] = {
+ { -1, -1 }, { 0, -1 }, { 1, -1 },
+ { -1, 0 }, { 1, 0 },
+ { -1, 1 }, { 0, 1 }, { 1, 1 }
+};
+
struct projectile_hook : df::proj_itemst {
typedef df::proj_itemst interpose_base;
@@ -1232,6 +1299,9 @@ struct projectile_hook : df::proj_itemst {
{
target_pos = path.target;
+ // Debug
+ Maps::getTileOccupancy(path.goal)->bits.arrow_color = COLOR_LIGHTMAGENTA;
+
PathMetrics raytrace(path);
// Materialize map blocks, or the projectile will crash into them
@@ -1259,7 +1329,53 @@ struct projectile_hook : df::proj_itemst {
fall_threshold = std::min(fall_threshold, engine->fire_range.second);
}
- void aimAtArea(EngineInfo *engine)
+ void aimAtPoint(EngineInfo *engine, int skill, const ProjectilePath &path)
+ {
+ df::coord fail_target = path.goal;
+
+ orient_engine(engine->bld, path.goal);
+
+ // Debug
+ Maps::getTileOccupancy(path.goal)->bits.arrow_color = COLOR_LIGHTRED;
+
+ // Dabbling always hit in 7x7 area
+ if (skill < skill_rating::Novice)
+ {
+ fail_target.x += random_int(7)-3;
+ fail_target.y += random_int(7)-3;
+ aimAtPoint(engine, ProjectilePath(path.origin, fail_target));
+ return;
+ }
+
+ // Exact hit chance
+ float hit_chance = 1.04f - powf(0.8f, skill);
+
+ if (float(rand())/RAND_MAX < hit_chance)
+ {
+ aimAtPoint(engine, path);
+ return;
+ }
+
+ // Otherwise perturb
+ if (skill <= skill_rating::Proficient)
+ {
+ // 5x5
+ fail_target.x += random_int(5)-2;
+ fail_target.y += random_int(5)-2;
+ }
+ else
+ {
+ // 3x3
+ int idx = random_int(8);
+ fail_target.x += offsets[idx][0];
+ fail_target.y += offsets[idx][1];
+ }
+
+ ProjectilePath fail(path.origin, fail_target, path.fudge_delta, path.fudge_factor);
+ aimAtPoint(engine, fail);
+ }
+
+ void aimAtArea(EngineInfo *engine, int skill)
{
df::coord target, last_passable;
df::coord tbase = engine->target.first;
@@ -1282,7 +1398,7 @@ struct projectile_hook : df::proj_itemst {
if (raytrace.hits() && engine->isInRange(raytrace.goal_step))
{
- aimAtPoint(engine, path);
+ aimAtPoint(engine, skill, path);
return;
}
}
@@ -1290,7 +1406,7 @@ struct projectile_hook : df::proj_itemst {
if (!last_passable.isValid())
last_passable = target;
- aimAtPoint(engine, ProjectilePath(engine->center, last_passable));
+ aimAtPoint(engine, skill, ProjectilePath(engine->center, last_passable));
}
static int safeAimProjectile(lua_State *L)
@@ -1312,9 +1428,9 @@ struct projectile_hook : df::proj_itemst {
lua_call(L, 5, 1);
if (lua_isnil(L, -1))
- proj->aimAtArea(engine);
+ proj->aimAtArea(engine, skill);
else
- proj->aimAtPoint(engine, decode_path(L, -1, engine->center));
+ proj->aimAtPoint(engine, skill, decode_path(L, -1, engine->center));
return 0;
}
@@ -1335,13 +1451,19 @@ struct projectile_hook : df::proj_itemst {
int skill = getOperatorSkill(engine->bld, true);
- lua_pushcfunction(L, safeAimProjectile);
- lua_pushlightuserdata(L, this);
- lua_pushlightuserdata(L, engine);
- lua_pushinteger(L, skill);
+ // Dabbling can't aim
+ if (skill < skill_rating::Novice)
+ aimAtArea(engine, skill);
+ else
+ {
+ lua_pushcfunction(L, safeAimProjectile);
+ lua_pushlightuserdata(L, this);
+ lua_pushlightuserdata(L, engine);
+ lua_pushinteger(L, skill);
- if (!Lua::Core::SafeCall(out, 3, 0))
- aimAtArea(engine);
+ if (!Lua::Core::SafeCall(out, 3, 0))
+ aimAtArea(engine, skill);
+ }
switch (item->getType())
{
@@ -1363,6 +1485,10 @@ struct projectile_hook : df::proj_itemst {
float speed = 100000.0f / (fall_delay + 1);
int min_zspeed = (fall_delay+1)*4900;
+ float bonus = 1.0f + 0.1f*(origin_pos.z -cur_pos.z);
+ bonus *= 1.0f + (distance_flown - 60) / 200.0f;
+ speed *= bonus;
+
// Flight direction vector
df::coord dist = target_pos - origin_pos;
float vx = dist.x, vy = dist.y, vz = fabs(dist.z);
@@ -1383,10 +1509,28 @@ struct projectile_hook : df::proj_itemst {
for (size_t i = 0; i < contents.size(); i++)
{
auto child = contents[i];
+
+ // Liquids are vaporized so that they cover nearby units
+ if (child->isLiquid())
+ {
+ auto flow = Maps::spawnFlow(
+ cur_pos,
+ flow_type::MaterialVapor,
+ child->getMaterial(), child->getMaterialIndex(),
+ 100
+ );
+
+ // should it leave a puddle too?..
+ if (flow && Items::remove(mc, child))
+ continue;
+ }
+
auto proj = Items::makeProjectile(mc, child);
if (!proj) continue;
- proj->flags.bits.no_impact_destroy = true;
+ bool keep = apply_impact_damage(child, 50000, int(250000*bonus));
+
+ proj->flags.bits.no_impact_destroy = keep;
//proj->flags.bits.bouncing = true;
proj->flags.bits.piercing = true;
proj->flags.bits.parabolic = true;
@@ -1403,7 +1547,7 @@ struct projectile_hook : df::proj_itemst {
proj->speed_x = int(speed * sx);
proj->speed_y = int(speed * sy);
- proj->speed_z = int(speed * sz);
+ proj->speed_z = std::max(min_zspeed, int(speed * sz));
}
}