diff options
| author | Kelly Martin | 2012-09-16 16:37:08 -0500 |
|---|---|---|
| committer | Kelly Martin | 2012-09-16 16:37:08 -0500 |
| commit | 847dadd3f530ab44172b0b18a73a32b76bcbd323 (patch) | |
| tree | 1c0b55a0df42ad1b0049aef02f8ed276dbb6dca3 /plugins/devel | |
| parent | 38f920dd658ba32dbe5126654b21f776386f07d5 (diff) | |
| parent | 000e3baf27e3d811e673bca08e4381c1f2c632b7 (diff) | |
| download | dfhack-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.cpp | 53 | ||||
| -rw-r--r-- | plugins/devel/siege-engine.cpp | 172 |
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> ¶meters) 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)); } } |
