fogón

← Weapons3D assetfogon/arma-hwacha

Hwacha

by fogonCC06666 blocks
HwachaDrag to turn it
// «Hwacha» · propio
// A handheld Korean hwacha: a small wooden rack holding a bundle of fire-arrows with red feathers and gunpowder tubes.

const colors = () => {};
const WOOD_DARK  = "#4a2e1a";
const WOOD_MID   = "#7a4c28";
const WOOD_LIGHT = "#a97545";
const WOOD_HI    = "#c99b63";

const METAL_DARK = "#33353e";
const METAL_MID  = "#5c5f6b";
const METAL_HI   = "#8e93a3";

const SHAFTS  = ["#d9b878", "#c8a566", "#e6cb90"];
const SHAFT_D = "#b8945a";

const TIP_DARK = "#2f3038";
const TIP_MID  = "#55586a";
const TIP_HI   = "#8b91a3";

const FEATHS  = ["#c0392b", "#b8352a", "#cc4433"];
const FEATH_L = "#e05a3c";
const FEATH_D = "#7e221c";

const POWDER = "#2b2b33";
const BRASS  = "#c9a13a";
const BAND   = "#a82a20";
const CORD   = "#b8a066";

part("body");

// =========================================================
//  WOODEN SLED / RACK
// =========================================================
box(12, 15, 0, 38, 33, 2, WOOD_DARK);        // lower body
box(12, 15, 3, 38, 33, 3, WOOD_MID);         // top plate
box(12, 20, 3, 38, 28, 3, "#33200f");        // groove shadow floor

// side walls
box(12, 15, 4, 38, 19, 10, WOOD_MID);
box(12, 29, 4, 38, 33, 10, WOOD_MID);
box(12, 15, 11, 38, 19, 11, WOOD_LIGHT);     // caps
box(12, 29, 11, 38, 33, 11, WOOD_LIGHT);
box(12, 19, 4, 38, 19, 10, WOOD_LIGHT);      // inner faces catch light
box(12, 29, 4, 38, 29, 10, WOOD_LIGHT);

// wood grain stripes on the outer faces
box(12, 15, 7, 38, 15, 7, WOOD_DARK);
box(12, 33, 5, 38, 33, 5, WOOD_DARK);
box(12, 15, 9, 38, 15, 9, WOOD_HI);
box(12, 33, 9, 38, 33, 9, WOOD_HI);
box(38, 15, 1, 38, 33, 1, WOOD_DARK);        // front edge
box(12, 15, 1, 12, 33, 1, WOOD_DARK);        // rear edge

// metal reinforcement bands on the outside
box(13, 15, 4, 14, 15, 10, METAL_MID);
box(13, 33, 4, 14, 33, 10, METAL_MID);
box(36, 15, 4, 37, 15, 10, METAL_MID);
box(36, 33, 4, 37, 33, 10, METAL_MID);

// bolts along the wall caps
for (let x = 15; x <= 36; x += 7) {
  set(x, 17, 11, METAL_HI);
  set(x, 31, 11, METAL_HI);
}

// brass corner caps
box(12, 15, 11, 13, 16, 11, BRASS);
box(12, 32, 11, 13, 33, 11, BRASS);
box(37, 15, 11, 38, 16, 11, BRASS);
box(37, 32, 11, 38, 33, 11, BRASS);

// =========================================================
//  BUNDLE OF FIRE-ARROWS  (3 x 3)
// =========================================================
const AY = [21, 24, 27];
const AZ = [5, 8, 11];

for (let zi = 0; zi < 3; zi++) {
  for (let yi = 0; yi < 3; yi++) {
    const ay = AY[yi];
    const az = AZ[zi];
    const sc = SHAFTS[(yi + zi) % 3];
    const fc = FEATHS[(yi + zi) % 3];

    // ---- tail feathers : solid block, then a tapering cross ----
    box(4, ay - 1, az - 1, 7, ay + 1, az + 1, fc);
    box(4, ay - 1, az + 1, 7, ay + 1, az + 1, FEATH_L);
    box(4, ay - 1, az - 1, 4, ay + 1, az + 1, FEATH_D);
    for (let x = 8; x <= 11; x++) {
      set(x, ay, az, FEATH_L);
      set(x, ay - 1, az, fc);
      set(x, ay + 1, az, fc);
      set(x, ay, az - 1, fc);
      set(x, ay, az + 1, FEATH_L);
    }

    // ---- gunpowder tube ----
    box(12, ay - 1, az - 1, 19, ay + 1, az + 1, POWDER);
    box(12, ay - 1, az - 1, 12, ay + 1, az + 1, BRASS);
    box(19, ay - 1, az - 1, 19, ay + 1, az + 1, BRASS);
    box(15, ay - 1, az - 1, 16, ay + 1, az + 1, BAND);

    // ---- shaft (cross section -> gaps between the arrows) ----
    for (let x = 20; x <= 40; x++) {
      const c = (x % 8 === 0) ? SHAFT_D : sc;
      set(x, ay, az, c);
      set(x, ay - 1, az, c);
      set(x, ay + 1, az, c);
      set(x, ay, az - 1, c);
      set(x, ay, az + 1, c);
    }

    // ---- iron arrowhead ----
    box(41, ay - 1, az - 1, 41, ay + 1, az + 1, TIP_MID);
    set(41, ay, az + 1, TIP_HI);
    set(42, ay, az, TIP_MID);
    set(42, ay - 1, az, TIP_DARK);
    set(42, ay + 1, az, TIP_DARK);
    set(42, ay, az - 1, TIP_MID);
    set(42, ay, az + 1, TIP_HI);
    set(43, ay, az, TIP_HI);
  }
}

// =========================================================
//  RETAINING STRAPS OVER THE BUNDLE
// =========================================================
box(20, 15, 12, 22, 33, 13, WOOD_LIGHT);
box(34, 15, 12, 36, 33, 13, WOOD_LIGHT);
box(21, 15, 13, 21, 33, 13, METAL_MID);
box(35, 15, 13, 35, 33, 13, METAL_MID);

// =========================================================
//  SLOW MATCH / FUSE
// =========================================================
line(15, 31, 12, 11, 32, 15, 0.55, CORD);
set(14, 31, 12, METAL_MID);
set(15, 31, 12, METAL_MID);

// =========================================================
//  BURNING SPARK  (bobs + flickers)
// =========================================================
part("spark", [11, 32, 15]);
set(11, 32, 15, "#ffd45e");
set(10, 32, 15, "#ff8a2e");
set(12, 32, 15, "#ff8a2e");
set(11, 32, 16, "#fff0a0");
set(11, 31, 15, "#ffb04e");

animate("spark", { type: "bob", axis: "z", speed: 2.2, amplitude: 0.9 });
colors("spark", {
  palette: ["#ffd45e", "#ff7a1e", "#fff3b0", "#ff9a2e"],
  pattern: "flicker", speed: 3.0, glow: 1
});

// =========================================================
//  FLOATING EMBERS
// =========================================================
part("ember", [12, 32, 18]);
set(12, 32, 18, "#ff9a2e");
set(13, 31, 19, "#ff7a1e");
set(11, 32, 19, "#ffb04e");

animate("ember", { type: "bob", axis: "z", speed: 1.5, amplitude: 1.3 });
colors("ember", {
  palette: ["#ff7a1e", "#ffb04e", "#ff3a10"],
  pattern: "flicker", speed: 2.0, glow: 1
});

// =========================================================
//  FINAL WOOD-GRAIN PASS
// =========================================================
forEach(function (x, y, z, c) {
  if (c === WOOD_MID) {
    const r = rand();
    if (r < 0.10) set(x, y, z, WOOD_DARK);
    else if (r < 0.18) set(x, y, z, WOOD_LIGHT);
  }
});